/** * read_dir_subdirs: grabs subdirs in a specific directory * @sysdir: sysfs directory to read * returns list of directory names with success and NULL with error. */ struct sysfs_device *sysfs_read_dir_subdirs(const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; char file_path[SYSFS_PATH_MAX]; struct sysfs_device *dev = NULL; if (!path) { errno = EINVAL; return NULL; } dev = sysfs_open_device_path(path); dir = opendir(path); if (!dir) { dprintf("Error opening directory %s\n", path); return NULL; } while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if (!sysfs_path_is_dir(file_path)) add_subdirectory(dev, file_path); } closedir(dir); return dev; }
/** * sysfs_get_bus_devices: gets all devices for bus * @bus: bus to get devices for * returns dlist of devices with success and NULL with failure */ struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus) { struct sysfs_device *dev; struct dlist *linklist; char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; char target[SYSFS_PATH_MAX]; char *curlink; if (!bus) { errno = EINVAL; return NULL; } memset(path, 0, SYSFS_PATH_MAX); safestrcpy(path, bus->path); safestrcat(path, "/"); safestrcat(path, SYSFS_DEVICES_NAME); linklist = read_dir_links(path); if (linklist) { dlist_for_each_data(linklist, curlink, char) { if (bus->devices) { dev = (struct sysfs_device *) dlist_find_custom(bus->devices, (void *)curlink, name_equal); if (dev) continue; } safestrcpy(devpath, path); safestrcat(devpath, "/"); safestrcat(devpath, curlink); if (sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { dprintf("Error getting link - %s\n", devpath); continue; } dev = sysfs_open_device_path(target); if (!dev) { dprintf("Error opening device at %s\n", target); continue; } if (!bus->devices) bus->devices = dlist_new_with_delete (sizeof(struct sysfs_device), sysfs_close_dev); dlist_unshift_sorted(bus->devices, dev, sort_list); } sysfs_close_list(linklist); } return (bus->devices); }
static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath) { struct usbip_exported_device *edev = NULL; size_t size; int i; edev = calloc(1, sizeof(*edev)); if (!edev) { dbg("calloc failed"); return NULL; } edev->sudev = sysfs_open_device_path(sdevpath); if (!edev->sudev) { dbg("sysfs_open_device_path failed: %s", sdevpath); goto err; } read_usb_device(edev->sudev, &edev->udev); edev->status = read_attr_usbip_status(&edev->udev); if (edev->status < 0) goto err; /* reallocate buffer to include usb interface data */ size = sizeof(*edev) + edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface); edev = realloc(edev, size); if (!edev) { dbg("realloc failed"); goto err; } for (i = 0; i < edev->udev.bNumInterfaces; i++) read_usb_interface(&edev->udev, i, &edev->uinf[i]); return edev; err: if (edev && edev->sudev) sysfs_close_device(edev->sudev); if (edev) free(edev); return NULL; }
int add_subdirectory(struct sysfs_device *dev, char *path) { struct sysfs_device *newdev; if (!path) return -1; newdev = sysfs_open_device_path(path); if (newdev == NULL) return -1; if (dev->children == NULL) dev->children = dlist_new_with_delete( sizeof(struct sysfs_device), sysfs_close_dev_tree); dlist_unshift_sorted(dev->children, newdev, sort_list); return 0; }
/** * sysfs_get_bus_device: Get specific device on bus using device's id * @bus: bus to find device on * @id: bus_id for device * returns struct sysfs_device reference or NULL if not found. */ struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, const char *id) { struct sysfs_device *dev = NULL; char devpath[SYSFS_PATH_MAX], target[SYSFS_PATH_MAX]; if (!bus || !id) { errno = EINVAL; return NULL; } if (bus->devices) { dev = (struct sysfs_device *)dlist_find_custom (bus->devices, (void *)id, name_equal); if (dev) return dev; } safestrcpy(devpath, bus->path); safestrcat(devpath, "/"); safestrcat(devpath, SYSFS_DEVICES_NAME); safestrcat(devpath, "/"); safestrcat(devpath, id); if (sysfs_path_is_link(devpath)) { dprintf("No such device %s on bus %s?\n", id, bus->name); return NULL; } if (!sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { dev = sysfs_open_device_path(target); if (!dev) { dprintf("Error opening device at %s\n", target); return NULL; } if (!bus->devices) bus->devices = dlist_new_with_delete (sizeof(struct sysfs_device), sysfs_close_dev); dlist_unshift_sorted(bus->devices, dev, sort_list); } return dev; }
/** * sysfs_get_classdev_device: gets the sysfs_device associated with the * given sysfs_class_device * @clsdev: class device whose associated sysfs_device is needed * returns struct sysfs_device * on success or NULL on error */ struct sysfs_device *sysfs_get_classdev_device (struct sysfs_class_device *clsdev) { char linkpath[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; if (!clsdev) { errno = EINVAL; return NULL; } if (clsdev->sysdevice) return clsdev->sysdevice; memset(linkpath, 0, SYSFS_PATH_MAX); safestrcpy(linkpath, clsdev->path); safestrcat(linkpath, "/device"); if (!sysfs_path_is_link(linkpath)) { memset(devpath, 0, SYSFS_PATH_MAX); if (!sysfs_get_link(linkpath, devpath, SYSFS_PATH_MAX)) clsdev->sysdevice = sysfs_open_device_path(devpath); } return clsdev->sysdevice; }
void get_usb_devs(hd_data_t *hd_data) { uint64_t ul0; unsigned u1, u2, u3; hd_t *hd, *hd1; usb_t *usb; str_list_t *sl, *usb_devs = NULL; char *s, *s1, *t; hd_res_t *res; size_t l; struct sysfs_bus *sf_bus; struct dlist *sf_dev_list; struct sysfs_device *sf_dev; struct sysfs_device *sf_dev_2; sf_bus = sysfs_open_bus("usb"); if(!sf_bus) { ADD2LOG("sysfs: no such bus: usb\n"); return; } sf_dev_list = sysfs_get_bus_devices(sf_bus); if(sf_dev_list) dlist_for_each_data(sf_dev_list, sf_dev, struct sysfs_device) { if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bNumInterfaces"), &ul0, 0)) { add_str_list(&usb_devs, sf_dev->path); ADD2LOG(" usb dev: %s\n", hd_sysfs_id(sf_dev->path)); } } if(sf_dev_list) dlist_for_each_data(sf_dev_list, sf_dev, struct sysfs_device) { ADD2LOG( " usb device: name = %s, bus_id = %s, bus = %s\n path = %s\n", sf_dev->name, sf_dev->bus_id, sf_dev->bus, hd_sysfs_id(sf_dev->path) ); if( hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceNumber"), &ul0, 16) ) { hd = add_hd_entry(hd_data, __LINE__, 0); hd->detail = new_mem(sizeof *hd->detail); hd->detail->type = hd_detail_usb; hd->detail->usb.data = usb = new_mem(sizeof *usb); hd->sysfs_id = new_str(hd_sysfs_id(sf_dev->path)); hd->sysfs_bus_id = new_str(sf_dev->bus_id); hd->bus.id = bus_usb; hd->func = ul0; usb->ifdescr = ul0; if((s = hd_attr_str(sysfs_get_device_attr(sf_dev, "modalias")))) { s = canon_str(s, strlen(s)); ADD2LOG(" modalias = \"%s\"\n", s); if(s && *s) { hd->modalias = s; s = NULL; } s = free_mem(s); } ADD2LOG(" bInterfaceNumber = %u\n", hd->func); if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceClass"), &ul0, 16)) { usb->i_cls = ul0; ADD2LOG(" bInterfaceClass = %u\n", usb->i_cls); } if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceSubClass"), &ul0, 16)) { usb->i_sub = ul0; ADD2LOG(" bInterfaceSubClass = %u\n", usb->i_sub); } if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceProtocol"), &ul0, 16)) { usb->i_prot = ul0; ADD2LOG(" bInterfaceProtocol = %u\n", usb->i_prot); } /* device has longest matching sysfs id */ u2 = strlen(sf_dev->path); s = NULL; for(u3 = 0, sl = usb_devs; sl; sl = sl->next) { u1 = strlen(sl->str); if(u1 > u3 && u1 <= u2 && !strncmp(sf_dev->path, sl->str, u1)) { u3 = u1; s = sl->str; } } if(s) { ADD2LOG(" if: %s @ %s\n", hd->sysfs_bus_id, hd_sysfs_id(s)); sf_dev_2 = sysfs_open_device_path(s); if(sf_dev_2) { if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bDeviceClass"), &ul0, 16)) { usb->d_cls = ul0; ADD2LOG(" bDeviceClass = %u\n", usb->d_cls); } if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bDeviceSubClass"), &ul0, 16)) { usb->d_sub = ul0; ADD2LOG(" bDeviceSubClass = %u\n", usb->d_sub); } if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bDeviceProtocol"), &ul0, 16)) { usb->d_prot = ul0; ADD2LOG(" bDeviceProtocol = %u\n", usb->d_prot); } if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "idVendor"), &ul0, 16)) { usb->vendor = ul0; ADD2LOG(" idVendor = 0x%04x\n", usb->vendor); } if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "idProduct"), &ul0, 16)) { usb->device = ul0; ADD2LOG(" idProduct = 0x%04x\n", usb->device); } if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "manufacturer")))) { usb->manufact = canon_str(s, strlen(s)); ADD2LOG(" manufacturer = \"%s\"\n", usb->manufact); } if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "product")))) { usb->product = canon_str(s, strlen(s)); ADD2LOG(" product = \"%s\"\n", usb->product); } if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "serial")))) { usb->serial = canon_str(s, strlen(s)); ADD2LOG(" serial = \"%s\"\n", usb->serial); } if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bcdDevice"), &ul0, 16)) { usb->rev = ul0; ADD2LOG(" bcdDevice = %04x\n", usb->rev); } if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "speed")))) { s = canon_str(s, strlen(s)); if(!strcmp(s, "1.5")) usb->speed = 15*100000; else if(!strcmp(s, "12")) usb->speed = 12*1000000; else if(!strcmp(s, "480")) usb->speed = 480*1000000; ADD2LOG(" speed = \"%s\"\n", s); s = free_mem(s); } sysfs_close_device(sf_dev_2); } } if(usb->vendor || usb->device) { hd->vendor.id = MAKE_ID(TAG_USB, usb->vendor); hd->device.id = MAKE_ID(TAG_USB, usb->device); } if(usb->manufact) hd->vendor.name = new_str(usb->manufact); if(usb->product) hd->device.name = new_str(usb->product); if(usb->serial) hd->serial = new_str(usb->serial); if(usb->rev) str_printf(&hd->revision.name, 0, "%x.%02x", usb->rev >> 8, usb->rev & 0xff); if(usb->speed) { res = add_res_entry(&hd->res, new_mem(sizeof *res)); res->baud.type = res_baud; res->baud.speed = usb->speed; } s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1); if(s) add_str_list(&hd->drivers, s); set_class_entries(hd_data, hd, usb); if(!hd_data->scanner_db) { hd_data->scanner_db = hd_module_list(hd_data, 1); } if( hd->drivers && search_str_list(hd_data->scanner_db, hd->drivers->str) ) { hd->base_class.id = bc_scanner; } // ###### FIXME if(hd->base_class.id == bc_modem) { hd->unix_dev_name = new_str("/dev/ttyACM0"); } }