/* * lshwd - lists hardware devices and their approp modules. * see the README for additional information. * * by z4ziggy at bliss-solutions dot org * */ #include #include #include #include #include #include #include #include #include #include "usb_names.h" #include "psaux.h" #include "pcmcia.h" #include /* * only 1 thing should usually be tampered with - the updated_modules. behind that, * its your program :-) */ /* * generic modules to be changed. format = "generic module name", "kernel module name" * change to suit whatever changes are needed in the table files (pci/usb/pcmcia) */ const char * updated_modules[][2] = { //{ "Mouse:USB|Wheel", "usbhid"}, { "nv", "nvidia"}, { "via82cxxx", "snd_via82xx"}, { "usb-uhci", "uhci_hcd"}, // usb-uhci=2.4 uhci-hcd=2.6 { "usb-ohci", "ohci_hcd"} // usb-uhci=2.4 uhci-hcd=2.6 }; /* the defines, we cant live without... ;) */ #define LSHWD_VERSION "lshwd 1.1, list hardware devices with approp modules\n" \ "Detects all types of PCI/PCMCIA/USB/FireWire cards/chips (ethernet,vga,sound,etc.).\n" \ "coded by for Arch linux, Nov. 2004\n\n" #define SHARED_PATH "/usr/share/hwdata" /* shared path which contains \ pcitable/usbtable/pcmciatable*/ #define USBIDS_FILE "/usr/share/usb.ids" /* file used for usb naming */ #define MODPROBE_PGM "/sbin/modprobe" /* the secret of life */ #ifdef DEBUG #undef DEBUG #define DEBUG(s...) fprintf(stderr, s) #else #define DEBUG(s...) ; #endif /* * * below here nothing should be changed * */ /* some global vars */ char *lookup_block; /* allocated buffer for modules list (table files) */ uint lookup_block_len; /* length of allocated buffer (table files) */ static struct pci_dev *first_dev; /* first device in pci device list from pci-lib */ static struct usb_device *first_usb_dev; int showids, autoload, disdefdesc,machinemode,plainmode,showlist,removeduplicates,outputxinfo; int usbmousefound; // ANSI COLORS (from Arch scheme) #define COLOR_NORMAL "\033[0;39m" // RED: Warning message #define COLOR_RED "\033[1;31m" // GREEN: Success message #define COLOR_GREEN "\033[1;32m" // YELLOW: Attention message #define COLOR_YELLOW "\033[1;33m" // BLUE: System message #define COLOR_BLUE "\033[1;34m" // BOLD WHITE: Found devices and modules #define COLOR_WHITE "\033[1;37m" char *title_color = COLOR_BLUE; char *modules_color = COLOR_WHITE; char *normal_color = COLOR_NORMAL; /* char *green = "\033[0;40;32m"; char *title_color = "\033[1;34m"; char *modules_color = "\033[1;36m"; // cyan char *normal_color = "\033[0m"; */ /* char *green = "\033[0;40;32m"; char *title_color = "\033[0;34m"; //--- device category char *modules_color = "\033[1;36m"; //--- modules and devices char *normal_color = "\033[0m"; //--- description */ /* * * let the real work begin * */ int usage(char *option) { printf(LSHWD_VERSION); if (option) fprintf(stderr,"lshwd: invalid option '%s'\n",option); printf( "usage: lshwd [-a] [-c] [-cc] [-d] [-id] [-m] [-n] [-ox]\n" "\t-a auto-modprobe\n" "\t-c categorized output\n" "\t-cc colorized & categorized output\n" "\t-d display default description\n" "\t-id display hardware id\n" "\t-m machine readable format\n" "\t-n no duplicates\n" "\t-ox output X info to /tmp/xinfo (gfx card section only)\n" ); return option? 1 : 0; } /* qsort procedure for sorting pci devices per class type */ int compare_pci_class(const void *A, const void *B) { struct pci_dev *a = (*(struct pci_dev **)A); struct pci_dev *b = (*(struct pci_dev **)B); unsigned int ca,cb; ca = pci_read_word(a, PCI_CLASS_DEVICE); /* Read config register directly */ cb = pci_read_word(b, PCI_CLASS_DEVICE); /* Read config register directly */ if (ca > cb) return 1; if (ca < cb) return -1; return 0; } /* qsort procedure for sorting pci devices per device bus/dev/func id */ int compare_pci_id(const void *A, const void *B) { struct pci_dev *a = (*(struct pci_dev **)A); struct pci_dev *b = (*(struct pci_dev **)B); if (a->bus < b->bus) return -1; if (a->bus > b->bus) return 1; if (a->dev < b->dev) return -1; if (a->dev > b->dev) return 1; if (a->func < b->func) return -1; if (a->func > b->func) return 1; return 0; } /* sorting the pci devices */ void sort_pci_list(void) { struct pci_dev **index, **h, **last_dev; int cnt; struct pci_dev *d; /* counting number of total devices */ for(cnt=0,d=first_dev; d; d=d->next) cnt++; /* allocating memory for all pci devices */ h = index = alloca(sizeof(struct pci_dev *) * cnt); for(d=first_dev; d; d=d->next) *h++ = d; if (showlist) qsort(index, cnt, sizeof(struct pci_dev *), compare_pci_id); else qsort(index, cnt, sizeof(struct pci_dev *), compare_pci_class); /* arranging result of qsort starting from first_dev */ last_dev = &first_dev; h = index; /* loop on all devices and copy contents from array to pci device list */ while (cnt--) { *last_dev = *h; /* checking for duplicates only if removeduplicates is on */ /* we compare the vendor_id and device_id of next item */ if (!removeduplicates || ((!cnt) || //((!(*(h+1))) || (!( ((*(h+1))->vendor_id == (*last_dev)->vendor_id) && ((*(h+1))->device_id == (*last_dev)->device_id) )))) { last_dev = &(*last_dev)->next; } h++; } *last_dev = NULL; } /* qsort procedure for sorting usb devices per bInterfaceClass */ int compare_usb_class(const void *A, const void *B) { struct usb_device *a = (*(struct usb_device **)A); struct usb_device *b = (*(struct usb_device **)B); unsigned int ca,cb; ca = a->config[0].interface[0].altsetting[0].bInterfaceClass; /* get USB class */ cb = b->config[0].interface[0].altsetting[0].bInterfaceClass; /* get USB class */ if (ca > cb) return 1; if (ca < cb) return -1; return 0; } /* sorting usb devices */ void sort_usb_list(void) { struct usb_bus *bus; struct usb_device *dev; struct usb_device **index, **h, **last_dev; int cnt; cnt = 0; /* counting number of total devices */ for (bus = usb_busses; bus; bus = bus->next) for (dev = bus->devices; dev; dev = dev->next) cnt++; /* allocating memory for all usb devices */ h = index = alloca(sizeof(struct usb_device *) * cnt); /* arranging all usb devices in 1 array */ for (bus = usb_busses; bus; bus = bus->next) for (dev = bus->devices; dev; dev = dev->next) *h++ = dev; /* only need to sort if not in showlist mode - since its sorted already */ if (!showlist) qsort(index, cnt, sizeof(struct usb_device *), compare_usb_class); /* arranging result of qsort starting from first_dev */ last_dev = &first_usb_dev; h = index; /* loop on all devices and copy contents from array to usb device list */ while (cnt--) { *last_dev = *h; if (!removeduplicates || (!(cnt) || !(((*(h+1))->descriptor.idVendor == (*last_dev)->descriptor.idVendor) && ((*(h+1))->descriptor.idProduct == (*last_dev)->descriptor.idProduct) && ((*(h+1))->descriptor.bcdUSB == (*last_dev)->descriptor.bcdUSB)))) { last_dev = &(*last_dev)->next; } h++; } *last_dev = NULL; } /* quick compare strings procedure */ int compare(char *string1,char *string2,int len) { while(len) { if(*string1 != *string2) break; string1++; string2++; len--; } return(!len); } /* search in updated_modules for module name, and replace with updated one if found */ void updated_module_name(char* module) { uint i = 0; for (i=sizeof(updated_modules)/sizeof(updated_modules[0]); i--;) { if (compare((char*)updated_modules[i][0], module, strlen(updated_modules[i][0]))) { sprintf(module, updated_modules[i][1]); } } } /* search for module name and description according to vendorid and deviceid. */ /* the search uses buffer (lookup_block) allocated by init_lookup_block which must to be called prior */ int lookup_module(int vendorid, int deviceid, char* module, int sizeofbuf, char* description, int sizeofdesc) { char cmpbuf[16]; /* formatting the string to search for */ sprintf(cmpbuf, "0x%04x\t0x%04x", vendorid, deviceid); //memset(module, 0, sizeofbuf); /* default module name... */ sprintf(module,"unknown"); uint i = 0; char *buf = lookup_block; while (i /dev/null 2>&1"); //strcat(cmd,"&>/dev/null"); strcat(cmd,">&/dev/null"); return system(cmd); } #endif #define QM_INFO 5 struct module_info { unsigned long addr; unsigned long size; unsigned long flags; long usecount; }; //#define USE_SYSCALL_MODULE_CHECK #ifdef USE_SYSCALL_MODULE_CHECK int isLoaded(char *module) { struct module_info mi; int tmp; return !syscall(SYS_query_module,module,QM_INFO,&mi,sizeof(mi),&tmp); } #else /* * using rmmod technique to search for mdoule, since syscall(SYS_query_module... * doesnt work... */ /* If we can check usage without entering kernel, do so. */ int isLoaded(const char *module) { FILE *module_list; char line[10240], name[64]; unsigned long size, refs; int scanned; module_list = fopen("/proc/modules", "r"); if (!module_list) { if (errno == ENOENT) /* /proc may not be mounted. */ return 0; DEBUG("can't open /proc/modules: %s\n", strerror(errno)); } while (fgets(line, sizeof(line)-1, module_list) != NULL) { if (strchr(line, '\n') == NULL) { DEBUG("V. v. long line broke rmmod.\n"); refs = 0; goto out; } scanned = sscanf(line, "%s %lu %lu", name, &size, &refs); DEBUG("%s %s\n",name, module); if (strcmp(name, module) == 0) { refs = 1; goto out; } } DEBUG("Module %s does not exist in /proc/modules\n", module); refs = 0; out: fclose(module_list); return refs; } #endif /* loading module using modprobe */ int loadModule(char *module) { char *args[] = { MODPROBE_PGM, NULL, "-q", NULL }; if (isLoaded(module)) { return -1; } else { args[1] = module; DEBUG("> modprobe %s\n", module); return execCommand(args); } } /* removing module using modprobe */ int removeModule(char *module) { char *args[] = { MODPROBE_PGM, "-r", NULL, NULL }; if (isLoaded(module)) { args[2] = module; DEBUG("> modprobe -r %s\n", module); return execCommand(args); } else { return -1; } } /* checking if module has attached ethernet device */ char * find_ethernet_devices(char *module) { DIR *dirp; struct dirent *direntry; char dirbuf[127], result[127], *res = result; memset(dirbuf, 0, sizeof(dirbuf)); memset(result, 0, sizeof(result)); sprintf(dirbuf, "/proc/net/%s", module); /* check if directory with module name exists */ if ((dirp = opendir(dirbuf)) != NULL) { /* we found a matching module dir, lets enum */ while ((direntry = readdir(dirp)) != NULL) { if (direntry->d_type == DT_REG) { memset(dirbuf, 0, sizeof(dirbuf)); if (machinemode) sprintf(dirbuf,"\" \"%s" ,direntry->d_name); else sprintf(dirbuf," %s[%s]%s" ,modules_color,direntry->d_name,normal_color); strcat(result, dirbuf); } } closedir(dirp); } return res; } /* copied getxinfo from hwsetup, by Klaus Knopper */ #define CARDSDB "/usr/share/hwdata/Cards" #define XPATH "/usr/X11R6/bin/" #define XMODPATH "/usr/X11R6/lib/modules/drivers/" int exists(char *filename) { struct stat s; return !stat(filename,&s); } struct xinfo { char xserver[16]; char xmodule[16]; char xdesc[128]; char xopts[128]; }; /* searching in /usr/share/kudzu/Cards for x module name and parameters */ /* if outputxinfo is on, /tmp/xinfo will be created containing gfx card section for X config */ struct xinfo * getxinfo ( char* devdesc, char* devdriver ) { const char *xfree4 = "XFree86", *xvesa4 = "vesa"; const char *xpath = XPATH; static struct xinfo xi; int rescanned = 0; char *xinfo_opt = malloc(0); int xinfo_opt_len = 0; memset ( &xi, 0, sizeof ( struct xinfo ) ); if ( devdesc ) strncpy ( xi.xdesc, devdesc, sizeof ( xi.xdesc ) ); if ( devdriver ) { const char * driver[] = { "3DLabs", "Mach64", "Mach32", "Mach8", "AGX", "P9000", "S3 ViRGE", "S3V", "S3", "W32", "8514", "I128", "SVGA", xfree4, NULL }; const char *server[] = { driver[ 0 ], driver[ 1 ], driver[ 2 ], driver[ 3 ], driver[ 4 ], driver[ 5 ], "S3V", driver[ 7 ], driver[ 8 ], driver[ 9 ], driver[ 10 ], driver[ 11 ], driver[ 12 ], xfree4, NULL }; if ( !strncasecmp ( devdriver, "Card:", 5 ) ) /* RedHat Cards-DB */ { /* Kudzu "Cards" format */ FILE * cardsdb; char xfree3server[ 128 ]; memset ( xfree3server, 0, sizeof ( xfree3server ) ); if ( ( cardsdb = fopen ( CARDSDB, "r" ) ) != NULL ) { /* Try to find Server and Module in /usr/share/kudzu/Cards */ char buffer[ 1024 ]; char searchfor[ 128 ]; int found = 0; memset ( searchfor, 0, sizeof ( searchfor ) ); sscanf ( &devdriver[ 5 ], "%127[^\r\n]", searchfor ); while ( !found && !feof ( cardsdb ) && fgets ( buffer, 1024, cardsdb ) ) { char sfound[ 128 ]; memset ( sfound, 0, sizeof ( sfound ) ); if ( strncasecmp ( buffer, "NAME ", 5 ) || ( sscanf( &buffer[ 5 ], "%127[^\r\n]", sfound ) != 1 ) || strcasecmp ( sfound, searchfor ) ) continue; while ( !feof ( cardsdb ) && fgets ( buffer, 1024, cardsdb ) ) { if ( buffer[ 0 ] < 32 ) break; /* End-of-line */ if ( !strncasecmp( buffer, "SERVER ", 7 ) ) { char x[ 20 ] = ""; if ( sscanf( &buffer[ 7 ], "%19s", x ) == 1 ) { char xserver[ 32 ]; char fullpath[ 128 ]; char *xf[ 2 ] = { "", "XF86_" }; int i; for ( i = 0; i < 2; i++ ) { sprintf ( xserver, "%s%.24s", xf[ i ], x ); sprintf ( fullpath, "%.90s%.32s", xpath, xserver ); if ( exists ( fullpath ) ) { strncpy ( xfree3server, xserver, sizeof ( xfree3server ) ); break; /* for */ } } } } else if ( !strncasecmp( buffer, "DRIVER ", 7 ) ) { char xmodule[ 32 ]; char fullpath[ 128 ]; sscanf ( &buffer[ 7 ], "%31s", xmodule ); sprintf ( fullpath, XMODPATH "%.31s_drv.o", xmodule ); if ( exists ( fullpath ) ) { strncpy ( xi.xmodule, xmodule, sizeof( xi.xmodule ) ); } } else if ( !strncasecmp( buffer, "SEE ", 4 ) && rescanned < 10 ) { /* rescan Cards-DB for other server */ fseek ( cardsdb, 0L, SEEK_SET ); ++rescanned; memset ( searchfor, 0, sizeof( searchfor ) ); sscanf ( &buffer[ 4 ], "%127[^\r\n]", searchfor ); break; /* Continue with outer while() */ } else if ( !strncasecmp( buffer, "LINE ", 5 ) && outputxinfo ) { char xinfo_opt_line[128]; sscanf ( &buffer[ 5 ], "%127[^\r\n]", xinfo_opt_line ); xinfo_opt_len += strlen(xinfo_opt_line) + 1; xinfo_opt = (char*)realloc(xinfo_opt, xinfo_opt_len ); strcat(xinfo_opt, xinfo_opt_line); strcat(xinfo_opt,"\n"); } } } fclose ( cardsdb ); } if ( *xi.xmodule || *xi.xserver || *xfree3server ) /* (Partial) Success */ { if ( !*xi.xserver ) { if ( *xfree3server && !*xi.xmodule ) strncpy ( xi.xserver, xfree3server, sizeof ( xi.xserver ) ); else strncpy ( xi.xserver, xfree4, sizeof ( xi.xserver ) ); } if ( !*xi.xmodule ) strcpy ( xi.xmodule, xvesa4 ); goto bailout; } } /* Card not found in Cards database -> Try to guess from description */ { int i; for ( i = 0; driver[ i ] != NULL; i++ ) { if ( strstr ( devdriver, driver[ i ] ) ) { char * xpos; if ( ( xpos = strstr ( devdriver, xfree4 ) ) != NULL ) /* Check for XFree 4 */ { char xm[ 32 ] = ""; strcpy ( xi.xserver, xfree4 ); if ( sscanf ( xpos, "XFree86(%30[^)])", xm ) == 1 ) strcpy ( xi.xmodule, xm ); else strcpy ( xi.xmodule, xvesa4 ); } else { char xserver[ 32 ]; char fullpath[ 128 ]; char *xf[ 2 ] = { "", "XF86_" }; int j; for ( j = 0; j < 2; j++ ) { sprintf ( xserver, "%s%.24s", xf[ j ], server[ i ] ); sprintf ( fullpath, "%.90s%.32s", xpath, xserver ); if ( exists ( fullpath ) ) { strncpy ( xi.xserver, xserver, sizeof( xi.xserver ) ); break; /* for */ } } } } } } } /* TODO: include xopts as Option in X config instead of startx parameters */ /* Special options required? */ if ( devdesc ) { strncpy ( xi.xdesc, devdesc, sizeof ( xi.xdesc ) - 1 ); /* Handle special cards that require special options */ if ( strstr ( devdesc, "Trident" ) || strstr ( devdesc, "TGUI" ) || strstr ( devdesc, "Cirrus" ) || strstr ( devdesc, "clgd" ) ) { if ( !strcmp ( xi.xserver, xfree4 ) ) strncpy ( xi.xopts, "-depth 16", sizeof ( xi.xopts ) - 1 ); else strncpy ( xi.xopts, "-bpp 16", sizeof ( xi.xopts ) - 1 ); } else if ( strstr ( devdesc, "Savage 4" ) ) /* S3 Inc.|Savage 4 */ { if ( !strcmp ( xi.xserver, xfree4 ) ) strncpy ( xi.xopts, "-depth 32", sizeof ( xi.xopts ) - 1 ); else strncpy ( xi.xopts, "-bpp 32", sizeof ( xi.xopts ) - 1 ); } } /* Fallback values */ if ( !*xi.xserver ) strcpy ( xi.xserver, xfree4 ); if ( !*xi.xmodule ) strcpy ( xi.xmodule, xvesa4 ); bailout: if (outputxinfo) { /* dump gfx X config section to /tmp/xinfo */ FILE *f; if ((f=fopen("/tmp/xinfo", "w")) != NULL) { *xinfo_opt='\0'; /* marking end of string */ fprintf(f,"Section \"Device\"\n"); fprintf(f,"\tIdentifier \"Card0\"\n"); fprintf(f,"\tDriver \"%s\"\n",xi.xmodule); fprintf(f,"\tVendorName \"All\"\n"); fprintf(f,"\tBoardName \"All\"\n"); fprintf(f,"%s", xinfo_opt); fprintf(f,"EndSection\n"); fclose(f); free(xinfo_opt); } } return ξ } int check_module(char *module) { struct pci_dev *d; byte descbuf[128], modulebuf[128]; for(d=first_dev; d; d=d->next) { lookup_module(d->vendor_id, d->device_id, modulebuf, sizeof(modulebuf), descbuf, sizeof(descbuf)); if (!strcmp(modulebuf, module)) { return !isLoaded(modulebuf); } } return 0; } /* listing pci devices using pci busses and devices initialized using pcilib function */ void list_pci(void) { unsigned int c; struct pci_access *pacc; struct pci_dev *dev; byte lastclassbuf[128]={0}; byte classbuf[128], descbuf[128], modulebuf[128]; char idstring[20]={0}; init_lookup_block("pcitable"); //pci_begin: pacc = pci_alloc(); /* Get the pci_access structure */ /* Set all options you want -- here we stick with the defaults */ pci_init(pacc); /* Initialize the PCI library */ pci_scan_bus(pacc); /* We want to get the list of devices */ first_dev = pacc->devices; /* * checking for CardBus devices, which requires loading yenta_socket module, and rescanning * pci bus in autoload moduled mode * */ if (autoload) { if (check_module("yenta_socket")) /* check for yenta_socket module */ { //printf("Probing FireWire devices...\r"); //fflush(stdout); loadModule("yenta_socket"); //system("modprobe yenta_socket > /dev/null 2>&1"); //while (!isLoaded("yenta_socket")); sleep(1); pci_cleanup(pacc); /* Close everything */ pacc = NULL; //goto pci_begin; pacc = pci_alloc(); /* Get the pci_access structure */ pci_init(pacc); /* Initialize the PCI library */ pci_scan_bus(pacc); /* We want to get the list of devices */ first_dev = pacc->devices; //printf("\r"); //fflush(stdout); } } sort_pci_list(); /* sorting according to display format */ for(dev=first_dev; dev; dev=dev->next) /* Iterate over all devices */ { /* look for pci information : name, module, description */ pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES); /* Fill in header info we need */ c = pci_read_word(dev, PCI_CLASS_DEVICE); /* Read config register directly */ char *pclassbuf = pci_lookup_name(pacc, classbuf, sizeof(classbuf), PCI_LOOKUP_CLASS, c, 0, 0, 0); int foundmodule = lookup_module(dev->vendor_id, dev->device_id, modulebuf, sizeof(modulebuf), descbuf, sizeof(descbuf)); /* check if its a gfx card to get X module and info for */ if ((c >> 8) == PCI_BASE_CLASS_DISPLAY) { /* getxinfo will retrieve x info and create /tmp/xinfo if needed */ struct xinfo *x = getxinfo(descbuf, modulebuf); strcpy(modulebuf, x->xmodule); DEBUG("%s\n%s\n%s\n%s\n", x->xserver, x->xmodule, x->xdesc, x->xopts); } if (foundmodule && autoload) { loadModule(modulebuf); } if (disdefdesc) { pci_lookup_name(pacc, descbuf, sizeof(descbuf), PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id, 0, 0); } /* if this is a ethernet controller, lets find the device(s) its attached to */ if (((c >> 8) == PCI_BASE_CLASS_NETWORK) && foundmodule) { char *ethdev=find_ethernet_devices(modulebuf); if (*ethdev) strcat(machinemode ? modulebuf : descbuf, ethdev); } /* now lets display results... */ if (machinemode) { //sprintf(idstring, "\"%04x:%04x\" ",dev->vendor_id, dev->device_id); printf("\"%s\" \"%s\" \"%s\"\n", pclassbuf, descbuf, modulebuf ); } else if (showlist) { /* printf("%02x:%02x.%d Class %04x: %04x:%04x %s (%s)\n", dev->bus, dev->dev, dev->func, c, dev->vendor_id, dev->device_id, descbuf, modulebuf);*/ sprintf(idstring, "%04x:%04x ",dev->vendor_id, dev->device_id); printf("%02x:%02x.%d %s%s: %s (%s)\n", dev->bus, dev->dev, dev->func, showids ? idstring : "", pclassbuf, descbuf, modulebuf); } else { if (strcmp(lastclassbuf, pclassbuf)) printf("%s%s%s\n",title_color, pclassbuf, normal_color); strcpy(lastclassbuf,pclassbuf); printf(" %s%-16s:%s %s\n", modules_color,modulebuf, normal_color, descbuf); } } pci_cleanup(pacc); /* Close everything */ cleanup_lookup_block(); /* free modules memory... */ } /* search for usb class name using pci.ids file. */ /* the search uses allocated memory by names_init which must to be called prior */ static int get_usb_class_string(char *buf, size_t size, u_int8_t class) { const char *cp; if (size < 1) return 0; *buf = 0; if (!(cp = names_class(class))) return 0; return snprintf(buf, size, "%s", cp); } /* listing usb devices using busses and devices initialized using usblib functions */ /* thanks to the sorting procedure all devices are organized in 1 list */ void list_usb(void) { int ret; usb_dev_handle *udev; struct usb_device *dev; struct usb_interface_descriptor desc; byte lastclassbuf[128]={0}; byte string[128],classbuf[128], descbuf[128], modulebuf[128]; char idstring[20]={0}; /* TODO: the approp modules are loaded anyway if usb controllers were found, so * there is no need to load those modules again. instead, need to find a * better way to make sure usb modules are loaded to continue autoload. */ if (autoload) { //if ((!isLoaded("uhci_hcd")) && (!isLoaded("ohci_hcd")) && (!isLoaded("ehci_hcd"))) { loadModule("ohci_hcd"); loadModule("ehci_hcd"); loadModule("uhci_hcd"); } } /* 1st we load usb.ids for usb naming */ if ((ret = names_init("./usb.ids")) != 0) { if ((ret = names_init(USBIDS_FILE))) { DEBUG("Error, cannot open USBIDS File \"%s\", %s\n", USBIDS_FILE, strerror(ret)); return; } } /* load usbtable file for module name and extra description */ init_lookup_block("usbtable"); /* executing mount command just to make sure we have /proc/bus/usb mounted. * if its not mounted, devices cant be browsed... * and if usb module wasnt loaded on system-startup, mount doesnt exists yet - * at least not on my computer... */ char *mountargs[] = { "/bin/mount", "-t", "usbfs", "none", "/proc/bus/usb", NULL }; execCommand(mountargs); /* now we init and load usblib functions */ usb_init(); usb_find_busses(); if (!usb_find_devices()) { DEBUG("No USB devices. maybe no usb module is loaded, or /proc/bus/usb is not mounted\n"); goto out_list_usb; } first_usb_dev = usb_busses->devices; sort_usb_list(); /* lets enum busses and devices ... */ for(dev=first_usb_dev; dev; dev=dev->next) /* Iterate over all devices */ { udev = usb_open(dev); if (!udev) continue; string[0] = classbuf[0] = modulebuf[0] = descbuf[0] = 0; desc = dev->config[0].interface[0].altsetting[0]; get_usb_class_string(classbuf, sizeof(classbuf), desc.bInterfaceClass); lookup_module(dev->descriptor.idVendor, dev->descriptor.idProduct, modulebuf, sizeof(modulebuf), descbuf, sizeof(descbuf)); /* if device already has a module attached (ie, loaded), show it instead */ if (usb_get_driver_np(udev, desc.bInterfaceNumber, string, sizeof(string)) == 0) { strcpy(modulebuf, string); /* no need to check for autoload, since module is already loaded */ } else { if (autoload) { loadModule(modulebuf); } } if (disdefdesc || !*descbuf) usb_get_string_simple(udev, dev->descriptor.iProduct, descbuf, sizeof(descbuf)); usb_close (udev); /* check if mouse device, and if so add [input/mice] */ if ((desc.bInterfaceClass == USB_CLASS_HID) && (desc.bInterfaceProtocol == 2)) { usbmousefound = 1; if (machinemode) { strcat(modulebuf, "\" \"/dev/input/mice"); } else { char mouse_string[128]={0}; sprintf(mouse_string, " %s[/dev/input/mice]%s",modules_color, normal_color); strcat(descbuf, mouse_string); } } /* check if this is a communication device, and attach device name if so */ else if (desc.bInterfaceClass == USB_CLASS_COMM) { char *ethdev=find_ethernet_devices(modulebuf); if (*ethdev) strcat(machinemode ? modulebuf : descbuf, ethdev); } if (machinemode) { printf("\"USB %s\" \"%s\" \"%s\"\n", classbuf, descbuf, modulebuf ); } else if (showlist) { sprintf(idstring, "%04x:%04x ",dev->descriptor.idVendor, dev->descriptor.idProduct); printf("%s:%s %sUSB %s: %s (%s)\n", dev->bus->dirname, dev->filename, showids ? idstring : "", classbuf, descbuf, modulebuf); } else { if (strcmp(lastclassbuf, classbuf)) printf("%sUSB %s%s\n",title_color, classbuf, normal_color); strcpy(lastclassbuf,classbuf); printf(" %s%-16s:%s %s\n", modules_color, modulebuf, normal_color, descbuf); } } out_list_usb: cleanup_lookup_block(); /* free modules memory... */ } /* testing mouse to see if one exists and list it. only 1 mouse is actually needed, so if usb mouse was found it will report only as ps/2 port */ void list_mouse(void) { byte devicebuf[128], descbuf[128], modulebuf[128]; char idstring[20]={0}; if (psauxProbe( devicebuf, modulebuf, descbuf)) { if (usbmousefound) { sprintf(descbuf, "PS/2 Mouse port"); } if (machinemode) { printf("\"Mouse\" \"%s\" \"%s\" \"%s\"\n", descbuf, modulebuf, devicebuf); } else if (showlist) { sprintf(idstring, "----:---- "); printf("---:--- %sMouse: %s [%s] (%s)\n", showids ? idstring : "", descbuf, devicebuf, modulebuf); } else { printf("%sMouse%s\n",title_color, normal_color); printf(" %s%-16s:%s %s %s[%s]%s\n", modules_color,modulebuf, normal_color, descbuf, modules_color, devicebuf, normal_color); } } } #define MAX_SOCKS 8 /* listing pcmcia devices according to /proc/devices */ void list_pcmcia(void) { if (!init_pcmcia()) return; int ns; ds_ioctl_arg_t arg; /* setting pointers to point to the approp variables */ cistpl_vers_1_t *vers = &arg.tuple_parse.parse.version_1; cistpl_manfid_t *manfid = &arg.tuple_parse.parse.manfid; cistpl_funcid_t *funcid = &arg.tuple_parse.parse.funcid; config_info_t config; int fd[MAX_SOCKS]; byte lastclassbuf[128]={0}; byte string[128],classbuf[128], descbuf[128], modulebuf[128]; char idstring[20]={0}; static char *pcmcia_fn[] = { "Multifunction", "Memory", "Serial", "Parallel", "Fixed disk", "Video", "Network", "AIMS", "SCSI" }; init_lookup_block("pcmciatable"); for (ns = 0; ns < MAX_SOCKS; ns++) { fd[ns] = open_sock(ns); if (fd[ns] < 0) break; vers->ns = 0; get_tuple(fd[ns], CISTPL_VERS_1, &arg); /* check if socket is empty */ if (vers->ns <= 0) continue; string[0] = classbuf[0] = modulebuf[0] = descbuf[0] = 0; *manfid = (cistpl_manfid_t) { 0, 0 }; get_tuple(fd[ns], CISTPL_MANFID, &arg); int foundmodule = lookup_module(manfid->manf, manfid->card, modulebuf, sizeof(modulebuf), descbuf, sizeof(descbuf)); if (disdefdesc || !*descbuf) { sprintf(descbuf,"%s|%s", vers->str+vers->ofs[0], vers->str+vers->ofs[1]); } *funcid = (cistpl_funcid_t) { 0xff, 0xff }; get_tuple(fd[ns], CISTPL_FUNCID, &arg); config.Function = config.ConfigBase = 0; /* if this is a ethernet controller, lets find the device(s) its attached to */ if (funcid->func == 6 && foundmodule) { char *ethdev=find_ethernet_devices(modulebuf); if (*ethdev) strcat(machinemode ? modulebuf : descbuf, ethdev); } if (machinemode) { printf("\"PCMCIA %s card\" \"%s\" \"%s\"\n", pcmcia_fn[funcid->func], descbuf, modulebuf ); } else if (showlist) { sprintf(idstring, "%04x:%04x ",manfid->manf, manfid->card); printf("--:%02x.%x %sPCMCIA %s card: %s (%s)\n", ns, funcid->func, showids ? idstring : "", pcmcia_fn[funcid->func], descbuf, modulebuf); } else { if (strcmp(lastclassbuf, pcmcia_fn[funcid->func])) printf("%sPCMCIA %s card%s\n",title_color, pcmcia_fn[funcid->func], normal_color); strcpy(lastclassbuf,pcmcia_fn[funcid->func]); printf(" %s%-16s:%s %s\n", modules_color, modulebuf, normal_color,descbuf); } } cleanup_lookup_block(); /* free modules memory... */ } /* listing firewire deivces according to /proc/bus/ieee1394/devices */ /* lame as hell, but keep the users happy... */ void list_firewire(void) { //int loaded_driver = 0; unsigned long specid, version; byte lastclassbuf[128]={0}; byte node[16],classbuf[128], descbuf[128], modulebuf[128]; char idstring[20]={0}; char *next, *buf = NULL, *tmp; char tmpbuf[4096]; int fd, bytes =0; /* Do NOT attempt to load firewire module (may crash), rather check for existing one. -KK */ #if 0 if (!loadModule("ohci1394")) loaded_driver = 1; #endif fd = open("/proc/bus/ieee1394/devices", O_RDONLY); if (fd < 0) goto out; memset(tmpbuf,'\0',4096); while (read(fd,tmpbuf,4096) > 0) { buf = realloc(buf,bytes+4096); memcpy(buf+bytes,tmpbuf,4096); bytes += 4096; memset(tmpbuf,'\0',4096); } close(fd); if (!buf) goto out; while (buf && *buf) { specid = version = 0; node[0] = classbuf[0] = modulebuf[0] = descbuf[0] = 0; next = strstr(buf+1,"Node["); if (next) { *(next-1) = '\0'; char *end; end = strstr(next,"]"); if (end) *end = '\0'; strcpy(node, next); } /* if (tmp = strstr(buf,"Vendor ID: ")) { char *end; end = strstr(tmp,"\'"); if (end) *end = '\0'; strcpy(classbuf, tmp+12); } */ if ((tmp=strstr(buf,"Software Specifier ID: "))) { int vendor_id = 0, product_id = 0; specid = strtoul(tmp+23,NULL,16); tmp = strstr(buf,"Software Version: "); if (tmp) version = strtoul(tmp+18,NULL,16); if (version == 0x010483 && specid == 0x00609e) { strcpy(modulebuf, "sbp2"); tmp = strstr(buf,"Vendor ID:"); if (tmp) { char *end; end = strstr(tmp,"\n"); int pos = end - tmp - 9; char vendor_id_str[10]; strncpy(vendor_id_str, tmp+pos, 8); vendor_id = strtoul(vendor_id_str,NULL,16); } tmp = strstr(buf,"Vendor/Model ID:"); if (tmp) { char *end; end = strstr(tmp,"\n"); if (end) *end = '\0'; strcpy(descbuf, tmp+17); int pos = end - tmp - 7; char product_id_str[10]; strncpy(product_id_str, tmp+pos, 6); product_id = strtoul(product_id_str,NULL,16); } else { strcpy(descbuf, "Generic Firewire Storage Controller"); } if (machinemode) { printf("\"FireWire device\" \"%s\" \"%s\"\n", descbuf, modulebuf ); } else if (showlist) { sprintf(idstring, "%04x:%04x ",vendor_id, product_id); printf("%s %sFireWire device: %s (%s)\n", node, showids ? idstring : "", descbuf, modulebuf); } else { if (strcmp(lastclassbuf, "FireWire")) printf("%sFireWire device(s)%s\n",title_color, normal_color); strcpy(lastclassbuf,"FireWire"); printf(" %s%-16s:%s %s\n", modules_color, modulebuf, normal_color,descbuf); } } } buf = next; } out: free(buf); /* Do NOT attempt to unload firewire module (may crash), rather check for existing one. -KK */ #if 0 if (loaded_driver == 1) removeModule("ohci1394"); #endif } int main(int argc, char **argv) { //struct device *devlst; //firewireProbe(CLASS_SCSI, 0, devlst); //return 0; unsigned int c; /* default settings */ autoload = disdefdesc = removeduplicates = machinemode = outputxinfo = usbmousefound = showids = 0; showlist = plainmode =1; /* checking for command line parameters*/ for(c=1;c