/* read the 256 bytes PCI configuration space to check the multi-function bit */ static bool is_pci_multifunction(struct udev_device *dev) { char filename[256]; FILE *f = NULL; char config[64]; bool multi = false; snprintf(filename, sizeof(filename), "%s/config", udev_device_get_syspath(dev)); f = fopen(filename, "re"); if (!f) goto out; if (fread(&config, sizeof(config), 1, f) != 1) goto out; /* bit 0-6 header type, bit 7 multi/single function device */ if ((config[PCI_HEADER_TYPE] & 0x80) != 0) multi = true; out: if(f) fclose(f); return multi; }
static int get_ncontrollers(void) { struct dirent **namelist; struct udev_device *platform; int n; platform = udev_device_get_parent(vhci_driver->hc_device); if (platform == NULL) return -1; n = scandir(udev_device_get_syspath(platform), &namelist, vhci_hcd_filter, NULL); if (n < 0) err("scandir failed"); else { for (int i = 0; i < n; i++) free(namelist[i]); free(namelist); } return n; }
static struct udev_device *handle_scsi(struct udev_device *parent, char **path) { const char *devtype; const char *name; const char *id; devtype = udev_device_get_devtype(parent); if (devtype == NULL || strcmp(devtype, "scsi_device") != 0) return parent; /* firewire */ id = udev_device_get_sysattr_value(parent, "ieee1394_id"); if (id != NULL) { parent = skip_subsystem(parent, "scsi"); path_prepend(path, "ieee1394-0x%s", id); goto out; } /* lousy scsi sysfs does not have a "subsystem" for the transport */ name = udev_device_get_syspath(parent); if (strstr(name, "/rport-") != NULL) { parent = handle_scsi_fibre_channel(parent, path); goto out; } if (strstr(name, "/end_device-") != NULL) { parent = handle_scsi_sas(parent, path); goto out; } if (strstr(name, "/session") != NULL) { parent = handle_scsi_iscsi(parent, path); goto out; } parent = handle_scsi_default(parent, path); out: return parent; }
///////////////////////////////////////////////////////////////////////////// /// calculate disk indices using scsi_host unique_id int DeviceMonitor::scsiHostIndex_( udev_device* device ) { udev* udev = udev_device_get_udev(device); std::string device_sys_path (udev_device_get_syspath(device)); std::string bus_prefix (""); bool use_ata = false; int host_index = 0; int bus_index_correction = 0; size_t index_of = device_sys_path.find("/ata"); if (index_of != std::string::npos) { bus_prefix.append(device_sys_path.substr(0, index_of + 4)); host_index = device_sys_path.at(index_of + 10) - '0'; bus_index_correction = device_sys_path.at(index_of + 4) - '0' - host_index; use_ata = true; } else { index_of = device_sys_path.find("/host"); bus_prefix.append(device_sys_path.substr(0, index_of)); host_index = device_sys_path.at(index_of) - '0'; } int scsi_host_index = -1; for (int i = 0; i <= host_index; i++) { std::string dev_path (bus_prefix); if (use_ata) { dev_path.append(1, '0' + bus_index_correction + i); } dev_path.append("/host"); dev_path.append(1, '0' + i); udev_device* dev_host = udev_device_new_from_syspath(udev, dev_path.c_str()); if (dev_host) { scsi_host_index++; } } return scsi_host_index; }
static bool _on_event(void *data, int fd, uint32_t cond) { struct udev_data *mdata = data; struct udev_device *device; bool event, inform = true; const char *action; if (cond & (SOL_FD_FLAGS_ERR | SOL_FD_FLAGS_HUP)) { SOL_WRN("Error with the monitor"); mdata->watch = NULL; sol_flow_send_error_packet(mdata->node, EIO, NULL); return false; } device = udev_monitor_receive_device(mdata->monitor); if (device == NULL) return true; if (mdata->addr && !streq(udev_device_get_syspath(device), mdata->addr)) goto end; action = udev_device_get_action(device); if (streq(action, "add")) event = true; else if (streq(action, "remove")) event = false; else inform = false; if (inform) sol_flow_send_boolean_packet(mdata->node, SOL_FLOW_NODE_TYPE_UDEV_BOOLEAN__OUT__OUT, event); end: udev_device_unref(device); return true; }
/* * Add 'legacy' device * * The term legacy is a bit misleading, but this adds devices according * to the original ofono model. * * - We cannot assume that these are USB devices * - The modem consists of only a single interface * - The device must have an OFONO_DRIVER property from udev */ static void add_serial_device(struct udev_device *dev) { const char *syspath, *devpath, *devname, *devnode; struct modem_info *modem; struct serial_device_info *info; const char *subsystem; struct udev_device* mdev; const char* driver; mdev = get_serial_modem_device(dev); if (!mdev) { DBG("Device is missing required OFONO_DRIVER property"); return; } driver = udev_device_get_property_value(mdev, "OFONO_DRIVER"); syspath = udev_device_get_syspath(mdev); devname = udev_device_get_devnode(mdev); devpath = udev_device_get_devpath(mdev); devnode = udev_device_get_devnode(dev); if (!syspath || !devname || !devpath || !devnode) return; modem = g_hash_table_lookup(modem_list, syspath); if (modem == NULL) { modem = g_try_new0(struct modem_info, 1); if (modem == NULL) return; modem->type = MODEM_TYPE_SERIAL; modem->syspath = g_strdup(syspath); modem->devname = g_strdup(devname); modem->driver = g_strdup("legacy"); g_hash_table_replace(modem_list, modem->syspath, modem); }
static int usb_dongle_probe_print_list(struct udev_enumerate *enumerate) { struct udev_list_entry *list_entry; unsigned int vid, pid; int ret = -1; udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(enumerate)) { struct udev_device *device; device = udev_device_new_from_syspath(udev_enumerate_get_udev(enumerate), udev_list_entry_get_name(list_entry)); if (device != NULL) { mylog_info("device: '%s' (%s)\n", udev_device_get_syspath(device), udev_device_get_subsystem(device)); get_vid_pid(device, &vid, &pid); ret = wlan_driver_match(vid, pid, wlan_driver_add_callback); udev_device_unref(device); if (!ret) break; } } return ret; }
/* private function to further filter watch results based on Eeze_Udev_Type * specified; helpful for new udev versions, but absolutely required for * old udev, which does not implement filtering in device monitors. */ static Eina_Bool _get_syspath_from_watch(void *data, Ecore_Fd_Handler *fd_handler) { struct _store_data *store = data; _udev_device *device = NULL, *parent, *tmpdev; const char *ret, *test; Eeze_Udev_Watch_Cb func = store->func; void *sdata = store->data; Eeze_Udev_Watch *watch = store->watch; int event = 0; if (!ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ)) return EINA_TRUE; device = udev_monitor_receive_device(store->mon); if (!device) return EINA_TRUE; if ((!(test = udev_device_get_action(device))) || (!(ret = udev_device_get_syspath(device)))) goto error; if (store->event) { if (!strcmp(test, "add")) { if ((store->event != EEZE_UDEV_EVENT_NONE) && ((store->event & EEZE_UDEV_EVENT_ADD) != EEZE_UDEV_EVENT_ADD)) goto error; event |= EEZE_UDEV_EVENT_ADD; } else if (!strcmp(test, "remove")) { if ((store->event != EEZE_UDEV_EVENT_NONE) && ((store->event & EEZE_UDEV_EVENT_REMOVE) != EEZE_UDEV_EVENT_REMOVE)) goto error; event |= EEZE_UDEV_EVENT_REMOVE; } else if (!strcmp(test, "change")) { if ((store->event != EEZE_UDEV_EVENT_NONE) && ((store->event & EEZE_UDEV_EVENT_CHANGE) != EEZE_UDEV_EVENT_CHANGE)) goto error; event |= EEZE_UDEV_EVENT_CHANGE; } else if (!strcmp(test, "online")) { if ((store->event != EEZE_UDEV_EVENT_NONE) && ((store->event & EEZE_UDEV_EVENT_ONLINE) != EEZE_UDEV_EVENT_ONLINE)) goto error; event |= EEZE_UDEV_EVENT_ONLINE; } else { if ((store->event != EEZE_UDEV_EVENT_NONE) && ((store->event & EEZE_UDEV_EVENT_OFFLINE) != EEZE_UDEV_EVENT_OFFLINE)) goto error; event |= EEZE_UDEV_EVENT_OFFLINE; } } if ((event & EEZE_UDEV_EVENT_OFFLINE) || (event & EEZE_UDEV_EVENT_REMOVE)) goto out; switch (store->type) { case EEZE_UDEV_TYPE_KEYBOARD: #ifdef OLD_UDEV_RRRRRRRRRRRRRR if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "input"))) goto error; test = udev_device_get_property_value(device, "ID_CLASS"); if ((_walk_parents_test_attr(device, "bInterfaceProtocol", "01")) || ((test) && (!strcmp(test, "kbd")))) break; goto error; #endif if ((!udev_device_get_property_value(device, "ID_INPUT_KEYBOARD")) && (!udev_device_get_property_value(device, "ID_INPUT_KEY"))) goto error; break; case EEZE_UDEV_TYPE_MOUSE: #ifdef OLD_UDEV_RRRRRRRRRRRRRR if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "input"))) goto error; test = udev_device_get_property_value(device, "ID_CLASS"); if ((_walk_parents_test_attr(device, "bInterfaceProtocol", "02")) || ((test) && (!strcmp(test, "mouse")))) break; goto error; #endif if (!udev_device_get_property_value(device, "ID_INPUT_MOUSE")) goto error; break; case EEZE_UDEV_TYPE_TOUCHPAD: #ifdef OLD_UDEV_RRRRRRRRRRRRRR if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "input"))) goto error; if (_walk_parents_test_attr(device, "resolution", NULL)) break; goto error; #endif if (!udev_device_get_property_value(device, "ID_INPUT_TOUCHPAD")) goto error; break; case EEZE_UDEV_TYPE_DRIVE_MOUNTABLE: #ifdef OLD_UDEV_RRRRRRRRRRRRRR if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "block"))) goto error; #endif if (!(test = (udev_device_get_property_value(device, "ID_FS_USAGE"))) || (strcmp("filesystem", test))) goto error; { int devcheck; devcheck = open(udev_device_get_devnode(device), O_RDONLY); if (devcheck < 0) goto error; close(devcheck); } break; case EEZE_UDEV_TYPE_DRIVE_INTERNAL: if (udev_device_get_property_value(device, "ID_FS_USAGE")) goto error; test = udev_device_get_sysattr_value(device, "removable"); if (test && test[0] == '1') goto error; test = udev_device_get_property_value(device, "ID_BUS"); if ((!test) || strcmp(test, "ata")) goto error; test = udev_device_get_property_value(device, "ID_TYPE"); if ((!test) || strcmp(test, "disk")) goto error; break; case EEZE_UDEV_TYPE_DRIVE_REMOVABLE: if (udev_device_get_sysattr_value(device, "partition")) goto error; test = udev_device_get_sysattr_value(device, "removable"); if ((!test) || (test[0] == '0')) goto error; test = udev_device_get_property_value(device, "ID_TYPE"); if ((!test) || strcmp(test, "disk")) goto error; break; case EEZE_UDEV_TYPE_DRIVE_CDROM: if (!udev_device_get_property_value(device, "ID_CDROM")) goto error; break; case EEZE_UDEV_TYPE_POWER_AC: #ifdef OLD_UDEV_RRRRRRRRRRRRRR if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "power_supply"))) goto error; #endif test = udev_device_get_property_value(device, "POWER_SUPPLY_ONLINE"); if (!test) goto error; break; case EEZE_UDEV_TYPE_POWER_BAT: #ifdef OLD_UDEV_RRRRRRRRRRRRRR if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "power_supply"))) goto error; #endif test = udev_device_get_property_value(device, "POWER_SUPPLY_PRESENT"); if (!test) goto error; break; case EEZE_UDEV_TYPE_IS_IT_HOT_OR_IS_IT_COLD_SENSOR: #ifdef OLD_UDEV_RRRRRRRRRRRRRR if ((!(test = udev_device_get_subsystem(device))) || (strcmp(test, "hwmon"))) goto error; #endif /* have to do stuff up here since we need info from the parent */ if (!_walk_parents_test_attr(device, "temp1_input", NULL)) goto error; /* if device is not the one which has the temp input, we must go up the chain */ if (!udev_device_get_sysattr_value(device, "temp1_input")) { for (parent = udev_device_get_parent(device); parent; parent = udev_device_get_parent(parent)) /*check for parent */ if (udev_device_get_sysattr_value(parent, "temp1_input")) { tmpdev = device; if (!(device = _copy_device(parent))) goto error; udev_device_unref(tmpdev); break; } } break; default: break; } out: (*func)(eina_stringshare_add(ret), event, sdata, watch); error: if (device) udev_device_unref(device); return EINA_TRUE; }
static struct udev_device *handle_scsi_default(struct udev_device *parent, char **path) { struct udev_device *hostdev; int host, bus, target, lun; const char *name; char *base; char *pos; DIR *dir; struct dirent *dent; int basenum; hostdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); if (hostdev == NULL) return NULL; name = udev_device_get_sysname(parent); if (sscanf(name, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) return NULL; /* rebase host offset to get the local relative number */ basenum = -1; base = strdup(udev_device_get_syspath(hostdev)); if (base == NULL) return NULL; pos = strrchr(base, '/'); if (pos == NULL) { parent = NULL; goto out; } pos[0] = '\0'; dir = opendir(base); if (dir == NULL) { parent = NULL; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { char *rest; int i; if (dent->d_name[0] == '.') continue; if (dent->d_type != DT_DIR && dent->d_type != DT_LNK) continue; if (strncmp(dent->d_name, "host", 4) != 0) continue; i = strtoul(&dent->d_name[4], &rest, 10); if (rest[0] != '\0') continue; if (basenum == -1 || i < basenum) basenum = i; } closedir(dir); if (basenum == -1) { parent = NULL; goto out; } host -= basenum; path_prepend(path, "scsi-%u:%u:%u:%u", host, bus, target, lun); out: free(base); return hostdev; }
int main(int argc, char **argv) { struct udev *udev = udev_new(); if (udev == NULL) { fprintf(stderr, "Unable to initialize udev context"); return -1; } #ifdef DEBUG struct udev_enumerate *enumerate = udev_enumerate_new(udev); if (enumerate == NULL) { fprintf(stderr, "Unable to enumerate devices"); return -1; } udev_enumerate_add_match_subsystem(enumerate, "drm"); udev_enumerate_scan_devices(enumerate); struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate); if (devices == NULL) { fprintf(stderr, "Unable to enumerate devices"); return -1; } // List devices struct udev_list_entry *dev_entry; udev_list_entry_foreach(dev_entry, devices) { const char *path = udev_list_entry_get_name(dev_entry); struct udev_device *dev = udev_device_new_from_syspath(udev, path); printf("%s [devtype=%s]\n", path, udev_device_get_devtype(dev)); } udev_enumerate_unref(enumerate); #endif // Setup monitor struct udev_monitor *monitor = udev_monitor_new_from_netlink(udev, "udev"); if (monitor == NULL) { fprintf(stderr, "Unable to initialize udev monitor"); return -1; } if (udev_monitor_filter_add_match_subsystem_devtype(monitor, "drm", "drm_minor") < 0) { fprintf(stderr, "Unable to setup udev monitor"); return -1; } if (udev_monitor_filter_update(monitor) < 0) { fprintf(stderr, "Unable to setup udev monitor"); return -1; } if (udev_monitor_enable_receiving(monitor) < 0) { fprintf(stderr, "Unable to listen in udev monitor"); return -1; } // The same issue as in SO, receive_device does not block, use select // http://stackoverflow.com/questions/15687784/libudev-monitoring-returns-null-pointer-on-raspbian int fd = udev_monitor_get_fd(monitor); while(1) { fd_set fds; FD_ZERO(&fds); FD_SET(fd, &fds); int ret = select(fd+1, &fds, NULL, NULL, NULL); if (ret > 0 && FD_ISSET(fd, &fds)) { struct udev_device *dev = udev_monitor_receive_device(monitor); if (dev == NULL) { continue; } printf("%s\n", udev_device_get_syspath(dev)); for (int i=1; i<argc; i++) { system(argv[i]); } udev_device_unref(dev); } } udev_monitor_unref(monitor); udev_unref(udev); return 0; }
int dev_create(struct wiimote_dev *dev) { int ret = 0; struct udev *udev; struct udev_device *d, *p; struct stat st; const char *root, *snum, *driver, *subs; int num; if (!dev->device) { ret = EINVAL; goto exit; } if (stat(dev->device, &st)) { ret = errno; goto exit; } udev = udev_new(); if (!udev) { fputs("could not connect to udev\n", stderr); ret = errno; goto exit; } d = udev_device_new_from_devnum(udev, 'c', st.st_rdev); if (!d) { fputs("could not find udev device\n", stderr); ret = errno; goto exit_udev; } p = udev_device_get_parent_with_subsystem_devtype(d, "hid", NULL); if (!p) { fputs("could not find parent HID device\n", stderr); ret = errno; goto exit_dev; } driver = udev_device_get_driver(p); subs = udev_device_get_subsystem(p); if (!driver || strcmp(driver, "wiimote") || !subs || strcmp(subs, "hid")) { fputs("parent is not a HID Wiimote\n", stderr); ret = errno; goto exit_dev; } root = udev_device_get_syspath(p); snum = udev_device_get_sysname(p); snum = snum ? strchr(snum, '.') : NULL; if (!root || !snum) { fputs("Could not get root path\n", stderr); ret = errno; goto exit_dev; } num = strtol(&snum[1], NULL, 16); if (num < 0) { fputs("Negative device number!\n", stderr); ret = errno; goto exit_dev; } dev->dev_id = num; dev->root = strdup(root); if (!dev->root) { fputs("Could not set device root\n", stderr); ret = errno; goto exit_dev; } printf("using device %d from root %s for %s\n", dev->dev_id, dev->root, dev->device); dev->ifs = XWII_IFACE_CORE | XWII_IFACE_ACCEL; ret = xwii_iface_new(&dev->iface, dev->root); if (ret) { fputs("Could not create xwiimote interface\n", stderr); ret = errno; goto exit_wii; } ret = xwii_iface_open(dev->iface, dev->ifs); if (ret) { fputs("Could not open xwiimote interface\n", stderr); ret = errno; goto exit_wii; } if (xwii_iface_opened(dev->iface) != dev->ifs) { fputs("Some interfaces failed to open\n", stderr); ret = errno; goto exit_wii; } dev->fd = xwii_iface_get_fd(dev->iface); goto exit_dev; exit_wii: free(dev->root); dev->root = NULL; exit_dev: udev_device_unref(d); exit_udev: udev_unref(udev); exit: return ret; }
void UdevSubsystem::print_info(udev_device* device) { log_debug("/---------------------------------------------"); log_debug("devpath: " << udev_device_get_devpath(device)); if (udev_device_get_action(device)) log_debug("action: " << udev_device_get_action(device)); //log_debug("init: " << udev_device_get_is_initialized(device)); if (udev_device_get_subsystem(device)) log_debug("subsystem: " << udev_device_get_subsystem(device)); if (udev_device_get_devtype(device)) log_debug("devtype: " << udev_device_get_devtype(device)); if (udev_device_get_syspath(device)) log_debug("syspath: " << udev_device_get_syspath(device)); if (udev_device_get_sysname(device)) log_debug("sysname: " << udev_device_get_sysname(device)); if (udev_device_get_sysnum(device)) log_debug("sysnum: " << udev_device_get_sysnum(device)); if (udev_device_get_devnode(device)) log_debug("devnode: " << udev_device_get_devnode(device)); if (udev_device_get_driver(device)) log_debug("driver: " << udev_device_get_driver(device)); if (udev_device_get_action(device)) log_debug("action: " << udev_device_get_action(device)); //udev_device_get_sysattr_value(device, "busnum"); //udev_device_get_sysattr_value(device, "devnum"); #if 0 // FIXME: only works with newer versions of libudev { log_debug("list: "); struct udev_list_entry* it = udev_device_get_tags_list_entry(device); while((it = udev_list_entry_get_next(it)) != 0) { log_debug(" " << udev_list_entry_get_name(it) << " = " << udev_list_entry_get_value(it) ); } } { log_debug("properties: "); struct udev_list_entry* it = udev_device_get_properties_list_entry(device); while((it = udev_list_entry_get_next(it)) != 0) { log_debug(" " << udev_list_entry_get_name(it) << " = " << udev_list_entry_get_value(it) ); } } { log_debug("devlist: "); struct udev_list_entry* it = udev_device_get_tags_list_entry(device); while((it = udev_list_entry_get_next(it)) != 0) { log_debug(" " << udev_list_entry_get_name(it) << " = " << udev_list_entry_get_value(it) ); } } #endif log_debug("\\----------------------------------------------"); }
void* udevmain(void* context){ // Enumerate all currently connected devices udevenum(); if(connectstatus & 2) // If a device failed to connect, enumerate again to make sure we reconnect it (if possible) udevenum(); // Done scanning. Enter a loop to poll for device updates struct udev_monitor* monitor = udev_monitor_new_from_netlink(udev, "udev"); udev_monitor_filter_add_match_subsystem_devtype(monitor, "usb", 0); udev_monitor_enable_receiving(monitor); // Get an fd for the monitor int fd = udev_monitor_get_fd(monitor); fd_set fds; while(udev){ FD_ZERO(&fds); FD_SET(fd, &fds); // Block until an event is read if(select(fd + 1, &fds, 0, 0, 0) > 0 && FD_ISSET(fd, &fds)){ struct udev_device* dev = udev_monitor_receive_device(monitor); if(dev){ const char* action = udev_device_get_action(dev); if(action && !strcmp(action, "add")){ // Device added. Check vendor and product ID and add the device if it matches. const char* vendor = udev_device_get_sysattr_value(dev, "idVendor"); if(vendor && !strcmp(vendor, V_CORSAIR_STR)){ const char* product = udev_device_get_sysattr_value(dev, "idProduct"); if(product && !strcmp(product, P_K70_STR)){ pthread_mutex_lock(&kblistmutex); openusb(dev, 70); pthread_mutex_unlock(&kblistmutex); } else if(product && !strcmp(product, P_K95_STR)){ pthread_mutex_lock(&kblistmutex); openusb(dev, 95); pthread_mutex_unlock(&kblistmutex); } else // Free the device if it wasn't used udev_device_unref(dev); } else udev_device_unref(dev); // Wait a little bit and then re-enumerate devices. Sometimes the keyboard doesn't get picked up right away. usleep(100000); connectstatus = 0; udevenum(); if(connectstatus & 2) udevenum(); } else if(!strcmp(action, "remove")){ // Device removed. Look for it in our list of keyboards pthread_mutex_lock(&kblistmutex); const char* path = udev_device_get_syspath(dev); for(int i = 1; i < DEV_MAX; i++){ if(keyboard[i].udev && !strcmp(path, udev_device_get_syspath(keyboard[i].udev))){ pthread_mutex_lock(&keyboard[i].mutex); closeusb(i); break; } } pthread_mutex_unlock(&kblistmutex); } } } } udev_monitor_unref(monitor); return 0; }
static void device_added(struct udev_device *udev_device) { const char *path, *name = NULL; char *config_info = NULL; const char *syspath; const char *tags_prop; const char *key, *value, *tmp; InputOption *options = NULL, *tmpo; InputAttributes attrs = {}; DeviceIntPtr dev = NULL; struct udev_list_entry *set, *entry; struct udev_device *parent; int rc; path = udev_device_get_devnode(udev_device); syspath = udev_device_get_syspath(udev_device); if (!path || !syspath) return; if (!udev_device_get_property_value(udev_device, "ID_INPUT")) { LogMessageVerb(X_INFO, 10, "config/udev: ignoring device %s without " "property ID_INPUT set\n", path); return; } options = calloc(sizeof(*options), 1); if (!options) return; options->key = strdup("_source"); options->value = strdup("server/udev"); if (!options->key || !options->value) goto unwind; parent = udev_device_get_parent(udev_device); if (parent) { const char *ppath = udev_device_get_devnode(parent); const char *product = udev_device_get_property_value(parent, "PRODUCT"); const char *pnp_id = udev_device_get_sysattr_value(parent, "id"); unsigned int usb_vendor, usb_model; name = udev_device_get_sysattr_value(parent, "name"); LOG_SYSATTR(ppath, "name", name); if (!name) { name = udev_device_get_property_value(parent, "NAME"); LOG_PROPERTY(ppath, "NAME", name); } if (pnp_id) attrs.pnp_id = strdup(pnp_id); LOG_SYSATTR(ppath, "id", pnp_id); /* construct USB ID in lowercase hex - "0000:ffff" */ if (product && sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) { if (asprintf(&attrs.usb_id, "%04x:%04x", usb_vendor, usb_model) == -1) attrs.usb_id = NULL; else LOG_PROPERTY(path, "PRODUCT", product); } } if (!name) name = "(unnamed)"; else attrs.product = strdup(name); add_option(&options, "name", name); add_option(&options, "path", path); add_option(&options, "device", path); if (path) attrs.device = strdup(path); tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags"); LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop); attrs.tags = xstrtokenize(tags_prop, ","); if (asprintf(&config_info, "udev:%s", syspath) == -1) { config_info = NULL; goto unwind; } if (device_is_duplicate(config_info)) { LogMessage(X_WARNING, "config/udev: device %s already added. " "Ignoring.\n", name); goto unwind; } set = udev_device_get_properties_list_entry(udev_device); udev_list_entry_foreach(entry, set) { key = udev_list_entry_get_name(entry); if (!key) continue; value = udev_list_entry_get_value(entry); if (!strncasecmp(key, UDEV_XKB_PROP_KEY, sizeof(UDEV_XKB_PROP_KEY) - 1)) { LOG_PROPERTY(path, key, value); tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1; if (!strcasecmp(tmp, "rules")) add_option(&options, "xkb_rules", value); else if (!strcasecmp(tmp, "layout")) add_option(&options, "xkb_layout", value); else if (!strcasecmp(tmp, "variant")) add_option(&options, "xkb_variant", value); else if (!strcasecmp(tmp, "model")) add_option(&options, "xkb_model", value); else if (!strcasecmp(tmp, "options")) add_option(&options, "xkb_options", value); } else if (!strcmp(key, "ID_VENDOR")) { LOG_PROPERTY(path, key, value); attrs.vendor = strdup(value); } else if (!strcmp(key, "ID_INPUT_KEY")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_KEYBOARD; } else if (!strcmp(key, "ID_INPUT_MOUSE")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_POINTER; } else if (!strcmp(key, "ID_INPUT_JOYSTICK")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_JOYSTICK; } else if (!strcmp(key, "ID_INPUT_TABLET")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TABLET; } else if (!strcmp(key, "ID_INPUT_TOUCHPAD")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TOUCHPAD; } else if (!strcmp(key, "ID_INPUT_TOUCHSCREEN")) { LOG_PROPERTY(path, key, value); attrs.flags |= ATTR_TOUCHSCREEN; } }
static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len) { _cleanup_free_ char *filename = NULL; _cleanup_close_ int fd = -1; ssize_t size; unsigned char buf[18 + 65535]; int pos = 0; unsigned strpos = 0; struct usb_interface_descriptor { u_int8_t bLength; u_int8_t bDescriptorType; u_int8_t bInterfaceNumber; u_int8_t bAlternateSetting; u_int8_t bNumEndpoints; u_int8_t bInterfaceClass; u_int8_t bInterfaceSubClass; u_int8_t bInterfaceProtocol; u_int8_t iInterface; } __attribute__((packed)); if (asprintf(&filename, "%s/descriptors", udev_device_get_syspath(dev)) < 0) return log_oom(); fd = open(filename, O_RDONLY|O_CLOEXEC); if (fd < 0) { fprintf(stderr, "error opening USB device 'descriptors' file\n"); return -errno; } size = read(fd, buf, sizeof(buf)); if (size < 18 || size == sizeof(buf)) return -EIO; ifs_str[0] = '\0'; while (pos < size && strpos+7 < len-2) { struct usb_interface_descriptor *desc; char if_str[8]; desc = (struct usb_interface_descriptor *) &buf[pos]; if (desc->bLength < 3) break; pos += desc->bLength; if (desc->bDescriptorType != USB_DT_INTERFACE) continue; if (snprintf(if_str, 8, ":%02x%02x%02x", desc->bInterfaceClass, desc->bInterfaceSubClass, desc->bInterfaceProtocol) != 7) continue; if (strstr(ifs_str, if_str) != NULL) continue; memcpy(&ifs_str[strpos], if_str, 8), strpos += 7; } if (strpos > 0) { ifs_str[strpos++] = ':'; ifs_str[strpos++] = '\0'; } return 0; }
//----------------------------------------------------------------------------- void HIDDeviceManager::OnEvent(int i, int fd) { OVR_UNUSED(i); OVR_UNUSED(fd); // There is a device status change udev_device* hid = udev_monitor_receive_device(HIDMonitor); if (hid) { const char* dev_path = udev_device_get_devnode(hid); const char* action = udev_device_get_action(hid); HIDDeviceDesc device_info; device_info.Path = dev_path; MessageType notify_type; if (OVR_strcmp(action, "add") == 0) { notify_type = Message_DeviceAdded; // Retrieve the device info. This can only be done on a connected // device and is invalid for a disconnected device // Get the USB device hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device"); if (!hid) { return; } const char* path = udev_device_get_syspath(hid); GetDescriptorFromPath(path, &device_info); } else if (OVR_strcmp(action, "remove") == 0) { notify_type = Message_DeviceRemoved; } else { return; } bool error = false; bool deviceFound = false; for (UPInt i = 0; i < NotificationDevices.GetSize(); i++) { if (NotificationDevices[i] && NotificationDevices[i]->OnDeviceNotification(notify_type, &device_info, &error)) { // The notification was for an existing device deviceFound = true; break; } } if (notify_type == Message_DeviceAdded && !deviceFound) { DevManager->DetectHIDDevice(device_info); } udev_device_unref(hid); } }
static int enumerate_partitions(dev_t devnum) { _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL; _cleanup_udev_device_unref_ struct udev_device *d = NULL; _cleanup_blkid_free_probe_ blkid_probe b = NULL; _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_free_ char *boot = NULL, *home = NULL, *srv = NULL; struct udev_list_entry *first, *item; struct udev_device *parent = NULL; const char *name, *node, *pttype, *devtype; int boot_nr = -1, home_nr = -1, srv_nr = -1; bool home_rw = true, srv_rw = true; blkid_partlist pl; int r, k; dev_t pn; udev = udev_new(); if (!udev) return log_oom(); d = udev_device_new_from_devnum(udev, 'b', devnum); if (!d) return log_oom(); name = udev_device_get_devnode(d); if (!name) name = udev_device_get_syspath(d); if (!name) { log_debug("Device %u:%u does not have a name, ignoring.", major(devnum), minor(devnum)); return 0; } parent = udev_device_get_parent(d); if (!parent) { log_debug("%s: not a partitioned device, ignoring.", name); return 0; } /* Does it have a devtype? */ devtype = udev_device_get_devtype(parent); if (!devtype) { log_debug("%s: parent doesn't have a device type, ignoring.", name); return 0; } /* Is this a disk or a partition? We only care for disks... */ if (!streq(devtype, "disk")) { log_debug("%s: parent isn't a raw disk, ignoring.", name); return 0; } /* Does it have a device node? */ node = udev_device_get_devnode(parent); if (!node) { log_debug("%s: parent device does not have device node, ignoring.", name); return 0; } log_debug("%s: root device %s.", name, node); pn = udev_device_get_devnum(parent); if (major(pn) == 0) return 0; errno = 0; b = blkid_new_probe_from_filename(node); if (!b) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to allocate prober: %m", node); } blkid_probe_enable_partitions(b, 1); blkid_probe_set_partitions_flags(b, BLKID_PARTS_ENTRY_DETAILS); errno = 0; r = blkid_do_safeprobe(b); if (r == 1) return 0; /* no results */ else if (r == -2) { log_warning("%s: probe gave ambiguous results, ignoring", node); return 0; } else if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to probe: %m", node); errno = 0; r = blkid_probe_lookup_value(b, "PTTYPE", &pttype, NULL); if (r != 0) return log_error_errno(errno ?: EIO, "%s: failed to determine partition table type: %m", node); /* We only do this all for GPT... */ if (!streq_ptr(pttype, "gpt")) { log_debug("%s: not a GPT partition table, ignoring.", node); return 0; } errno = 0; pl = blkid_probe_get_partitions(b); if (!pl) { if (errno == 0) return log_oom(); return log_error_errno(errno, "%s: failed to list partitions: %m", node); } e = udev_enumerate_new(udev); if (!e) return log_oom(); r = udev_enumerate_add_match_parent(e, parent); if (r < 0) return log_oom(); r = udev_enumerate_add_match_subsystem(e, "block"); if (r < 0) return log_oom(); r = udev_enumerate_scan_devices(e); if (r < 0) return log_error_errno(r, "%s: failed to enumerate partitions: %m", node); first = udev_enumerate_get_list_entry(e); udev_list_entry_foreach(item, first) { _cleanup_udev_device_unref_ struct udev_device *q; unsigned long long flags; const char *stype, *subnode; sd_id128_t type_id; blkid_partition pp; dev_t qn; int nr; q = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); if (!q) continue; qn = udev_device_get_devnum(q); if (major(qn) == 0) continue; if (qn == devnum) continue; if (qn == pn) continue; subnode = udev_device_get_devnode(q); if (!subnode) continue; pp = blkid_partlist_devno_to_partition(pl, qn); if (!pp) continue; nr = blkid_partition_get_partno(pp); if (nr < 0) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type_id) < 0) continue; flags = blkid_partition_get_flags(pp); if (sd_id128_equal(type_id, GPT_SWAP)) { if (flags & GPT_FLAG_NO_AUTO) continue; if (flags & GPT_FLAG_READ_ONLY) { log_debug("%s marked as read-only swap partition, which is bogus. Ignoring.", subnode); continue; } k = add_swap(subnode); if (k < 0) r = k; } else if (sd_id128_equal(type_id, GPT_ESP)) { /* We only care for the first /boot partition */ if (boot && nr >= boot_nr) continue; /* Note that we do not honour the "no-auto" * flag for the ESP, as it is often unset, to * hide it from Windows. */ boot_nr = nr; r = free_and_strdup(&boot, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_HOME)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /home partition */ if (home && nr >= home_nr) continue; home_nr = nr; home_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&home, subnode); if (r < 0) return log_oom(); } else if (sd_id128_equal(type_id, GPT_SRV)) { if (flags & GPT_FLAG_NO_AUTO) continue; /* We only care for the first /srv partition */ if (srv && nr >= srv_nr) continue; srv_nr = nr; srv_rw = !(flags & GPT_FLAG_READ_ONLY), r = free_and_strdup(&srv, subnode); if (r < 0) return log_oom(); } }
static int builtin_firmware(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev *udev = udev_device_get_udev(dev); static const char *searchpath[] = { FIRMWARE_PATH }; char fwencpath[UTIL_PATH_SIZE]; char misspath[UTIL_PATH_SIZE]; char loadpath[UTIL_PATH_SIZE]; char datapath[UTIL_PATH_SIZE]; char fwpath[UTIL_PATH_SIZE]; const char *firmware; FILE *fwfile = NULL; struct utsname kernel; struct stat statbuf; unsigned int i; int rc = EXIT_SUCCESS; firmware = udev_device_get_property_value(dev, "FIRMWARE"); if (firmware == NULL) { log_error("firmware parameter missing\n\n"); rc = EXIT_FAILURE; goto exit; } /* lookup firmware file */ uname(&kernel); for (i = 0; i < ELEMENTSOF(searchpath); i++) { util_strscpyl(fwpath, sizeof(fwpath), searchpath[i], kernel.release, "/", firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; util_strscpyl(fwpath, sizeof(fwpath), searchpath[i], firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; } util_path_encode(firmware, fwencpath, sizeof(fwencpath)); util_strscpyl(misspath, sizeof(misspath), "/run/udev/firmware-missing/", fwencpath, NULL); util_strscpyl(loadpath, sizeof(loadpath), udev_device_get_syspath(dev), "/loading", NULL); if (fwfile == NULL) { int err; /* This link indicates the missing firmware file and the associated device */ log_debug("did not find firmware file '%s'\n", firmware); do { err = mkdir_parents(misspath, 0755); if (err != 0 && err != -ENOENT) break; err = symlink(udev_device_get_devpath(dev), misspath); if (err != 0) err = -errno; } while (err == -ENOENT); rc = EXIT_FAILURE; /* * Do not cancel the request in the initrd, the real root might have * the firmware file and the 'coldplug' run in the real root will find * this pending request and fulfill or cancel it. * */ if (!in_initrd()) set_loading(udev, loadpath, "-1"); goto exit; } if (stat(fwpath, &statbuf) < 0 || statbuf.st_size == 0) { if (!in_initrd()) set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; } if (unlink(misspath) == 0) util_delete_path(udev, misspath); if (!set_loading(udev, loadpath, "1")) goto exit; util_strscpyl(datapath, sizeof(datapath), udev_device_get_syspath(dev), "/data", NULL); if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) { log_error("error sending firmware '%s' to device\n", firmware); set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; }; set_loading(udev, loadpath, "0"); exit: if (fwfile) fclose(fwfile); return rc; }
static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev_list_entry *entry; unsigned release[1024]; unsigned release_count = 0; _cleanup_close_ int fd = -1; const char *node; node = udev_device_get_devnode(dev); if (!node) { log_error("No device node for \"%s\"", udev_device_get_syspath(dev)); return EXIT_FAILURE; } udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) { const char *key; char *endptr; key = udev_list_entry_get_name(entry); if (startswith(key, "KEYBOARD_KEY_")) { const char *keycode; unsigned scancode; /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */ scancode = strtoul(key + 13, &endptr, 16); if (endptr[0] != '\0') { log_warning("Unable to parse scan code from \"%s\"", key); continue; } keycode = udev_list_entry_get_value(entry); /* a leading '!' needs a force-release entry */ if (keycode[0] == '!') { keycode++; release[release_count] = scancode; if (release_count < ELEMENTSOF(release)-1) release_count++; if (keycode[0] == '\0') continue; } if (fd == -1) { fd = open_device(node); if (fd < 0) return EXIT_FAILURE; } map_keycode(fd, node, scancode, keycode); } else if (startswith(key, "EVDEV_ABS_")) { unsigned evcode; /* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */ evcode = strtoul(key + 10, &endptr, 16); if (endptr[0] != '\0') { log_warning("Unable to parse EV_ABS code from \"%s\"", key); continue; } if (fd == -1) { fd = open_device(node); if (fd < 0) return EXIT_FAILURE; } override_abs(fd, node, evcode, udev_list_entry_get_value(entry)); } else if (streq(key, "POINTINGSTICK_SENSITIVITY")) set_trackpoint_sensitivity(dev, udev_list_entry_get_value(entry)); } /* install list of force-release codes */ if (release_count > 0) install_force_release(dev, release, release_count); return EXIT_SUCCESS; }
static int update_link(struct udev_device *dev, const char *slink, int test) { struct udev *udev = udev_device_get_udev(dev); struct udev_list_node dev_list; struct udev_list_entry *dev_entry; char target[UTIL_PATH_SIZE]; int count; int priority = 0; int rc = 0; dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev)); udev_list_init(&dev_list); count = name_index_get_devices(udev, slink, &dev_list); if (count > 1) info(udev, "found %i devices with name '%s'\n", count, slink); /* if we don't have a reference, delete it */ if (count <= 0) { info(udev, "no reference left, remove '%s'\n", slink); if (!test) { unlink(slink); util_delete_path(udev, slink); } goto out; } /* find the device with the highest priority */ target[0] = '\0'; udev_list_entry_foreach(dev_entry, udev_list_get_entry(&dev_list)) { const char *syspath; struct udev_device *dev_db; const char *devnode; syspath = udev_list_entry_get_name(dev_entry); dbg(udev, "found '%s' for '%s'\n", syspath, slink); /* did we find ourself? we win, if we have the same priority */ if (strcmp(udev_device_get_syspath(dev), syspath) == 0) { dbg(udev, "compare (our own) priority of '%s' %i >= %i\n", udev_device_get_devpath(dev), udev_device_get_devlink_priority(dev), priority); if (strcmp(udev_device_get_devnode(dev), slink) == 0) { info(udev, "'%s' is our device node, database inconsistent, skip link update\n", udev_device_get_devnode(dev)); } else if (target[0] == '\0' || udev_device_get_devlink_priority(dev) >= priority) { priority = udev_device_get_devlink_priority(dev); util_strlcpy(target, udev_device_get_devnode(dev), sizeof(target)); } continue; } /* another device, read priority from database */ dev_db = udev_device_new_from_syspath(udev, syspath); if (dev_db == NULL) continue; devnode = udev_device_get_devnode(dev_db); if (devnode != NULL) { if (strcmp(devnode, slink) == 0) { info(udev, "'%s' is a device node of '%s', skip link update\n", devnode, syspath); } else { dbg(udev, "compare priority of '%s' %i > %i\n", udev_device_get_devpath(dev_db), udev_device_get_devlink_priority(dev_db), priority); if (target[0] == '\0' || udev_device_get_devlink_priority(dev_db) > priority) { priority = udev_device_get_devlink_priority(dev_db); util_strlcpy(target, devnode, sizeof(target)); } } } udev_device_unref(dev_db); } udev_list_cleanup_entries(udev, &dev_list); if (target[0] == '\0') { info(udev, "no current target for '%s' found\n", slink); rc = 1; goto out; } /* create symlink to the target with the highest priority */ info(udev, "'%s' with target '%s' has the highest priority %i, create it\n", slink, target, priority); if (!test) { util_create_path(udev, slink); node_symlink(udev, target, slink); } out: return rc; }
/* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */ int util_resolve_subsys_kernel(struct udev *udev, const char *string, char *result, size_t maxsize, int read_value) { char temp[UTIL_PATH_SIZE]; char *subsys; char *sysname; struct udev_device *dev; char *attr; if (string[0] != '[') return -1; util_strscpy(temp, sizeof(temp), string); subsys = &temp[1]; sysname = strchr(subsys, '/'); if (sysname == NULL) return -1; sysname[0] = '\0'; sysname = &sysname[1]; attr = strchr(sysname, ']'); if (attr == NULL) return -1; attr[0] = '\0'; attr = &attr[1]; if (attr[0] == '/') attr = &attr[1]; if (attr[0] == '\0') attr = NULL; if (read_value && attr == NULL) return -1; dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname); if (dev == NULL) return -1; if (read_value) { const char *val; val = udev_device_get_sysattr_value(dev, attr); if (val != NULL) util_strscpy(result, maxsize, val); else result[0] = '\0'; info(udev, "value '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result); } else { size_t l; char *s; s = result; l = util_strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL); if (attr != NULL) util_strpcpyl(&s, l, "/", attr, NULL); info(udev, "path '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result); } udev_device_unref(dev); return 0; }
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK udevGetIfaceDefBond(struct udev *udev, struct udev_device *dev, const char *name, virInterfaceDef *ifacedef) { struct dirent **slave_list = NULL; int slave_count = 0; size_t i; const char *tmp_str; int tmp_int; /* Initial defaults */ ifacedef->data.bond.target = NULL; ifacedef->data.bond.nbItf = 0; ifacedef->data.bond.itf = NULL; /* Set the bond specifics */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/downdelay"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/downdelay' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/downdelay' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.downdelay = tmp_int; tmp_str = udev_device_get_sysattr_value(dev, "bonding/updelay"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/updelay' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/updelay' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.updelay = tmp_int; tmp_str = udev_device_get_sysattr_value(dev, "bonding/miimon"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/miimon' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/miimon' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.frequency = tmp_int; tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_interval"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/arp_interval' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/arp_interval' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.interval = tmp_int; /* bonding/mode is in the format: "balance-rr 0" so we find the * space and increment the pointer to get the number and convert * it to an interger. libvirt uses 1 through 7 while the raw * number is 0 through 6 so increment it by 1. */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/mode"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/mode' for '%s'"), name); goto error; } tmp_str = strchr(tmp_str, ' '); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid format for 'bonding/mode' for '%s'"), name); goto error; } if (strlen(tmp_str) < 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to find correct value in 'bonding/mode' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str + 1, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/mode' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.mode = tmp_int + 1; /* bonding/arp_validate is in the format: "none 0" so we find the * space and increment the pointer to get the number and convert * it to an interger. */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_validate"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/arp_validate' for '%s'"), name); goto error; } tmp_str = strchr(tmp_str, ' '); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid format for 'bonding/arp_validate' for '%s'"), name); goto error; } if (strlen(tmp_str) < 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unable to find correct value in 'bonding/arp_validate' " "for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str + 1, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/arp_validate' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.validate = tmp_int; /* bonding/use_carrier is 0 or 1 and libvirt stores it as 1 or 2. */ tmp_str = udev_device_get_sysattr_value(dev, "bonding/use_carrier"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/use_carrier' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &tmp_int) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bonding/use_carrier' '%s' for '%s'"), tmp_str, name); goto error; } ifacedef->data.bond.carrier = tmp_int + 1; /* MII or ARP Monitoring is based on arp_interval and miimon. * if arp_interval > 0 then ARP monitoring is in play, if * miimon > 0 then MII monitoring is in play. */ if (ifacedef->data.bond.interval > 0) ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_ARP; else if (ifacedef->data.bond.frequency > 0) ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_MII; else ifacedef->data.bond.monit = VIR_INTERFACE_BOND_MONIT_NONE; tmp_str = udev_device_get_sysattr_value(dev, "bonding/arp_ip_target"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bonding/arp_ip_target' for '%s'"), name); goto error; } if (VIR_STRDUP(ifacedef->data.bond.target, tmp_str) < 0) goto error; /* Slaves of the bond */ /* Get each slave in the bond */ slave_count = scandir(udev_device_get_syspath(dev), &slave_list, udevBondScanDirFilter, alphasort); if (slave_count < 0) { virReportSystemError(errno, _("Could not get slaves of bond '%s'"), name); goto error; } /* Allocate our list of slave devices */ if (VIR_ALLOC_N(ifacedef->data.bond.itf, slave_count) < 0) goto error; ifacedef->data.bond.nbItf = slave_count; for (i = 0; i < slave_count; i++) { /* Names are slave_interface. e.g. slave_eth0 * so we use the part after the _ */ tmp_str = strchr(slave_list[i]->d_name, '_'); if (!tmp_str || strlen(tmp_str) < 2) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid enslaved interface name '%s' seen for " "bond '%s'"), slave_list[i]->d_name, name); goto error; } /* go past the _ */ tmp_str++; ifacedef->data.bond.itf[i] = udevGetIfaceDef(udev, tmp_str); if (!ifacedef->data.bond.itf[i]) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get interface information for '%s', which is " "a enslaved in bond '%s'"), slave_list[i]->d_name, name); goto error; } VIR_FREE(slave_list[i]); } VIR_FREE(slave_list); return 0; error: for (i = 0; slave_count != -1 && i < slave_count; i++) { VIR_FREE(slave_list[i]); } VIR_FREE(slave_list); return -1; }
static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev_list_entry *entry; struct { unsigned int scan; unsigned int key; } map[1024]; unsigned int map_count = 0; unsigned int release[1024]; unsigned int release_count = 0; udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) { const char *key; unsigned int scancode; char *endptr; const char *keycode; const struct key *k; key = udev_list_entry_get_name(entry); if (!startswith(key, "KEYBOARD_KEY_")) continue; /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */ scancode = strtoul(key + 13, &endptr, 16); if (endptr[0] != '\0') { log_error("Error, unable to parse scan code from '%s'", key); continue; } keycode = udev_list_entry_get_value(entry); /* a leading '!' needs a force-release entry */ if (keycode[0] == '!') { keycode++; release[release_count] = scancode; if (release_count < ELEMENTSOF(release)-1) release_count++; if (keycode[0] == '\0') continue; } /* translate identifier to key code */ k = keyboard_lookup_key(keycode, strlen(keycode)); if (!k) { log_error("Error, unknown key identifier '%s'", keycode); continue; } map[map_count].scan = scancode; map[map_count].key = k->id; if (map_count < ELEMENTSOF(map)-1) map_count++; } if (map_count > 0 || release_count > 0) { const char *node; int fd; unsigned int i; node = udev_device_get_devnode(dev); if (!node) { log_error("Error, no device node for '%s'", udev_device_get_syspath(dev)); return EXIT_FAILURE; } fd = open(udev_device_get_devnode(dev), O_RDWR|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); if (fd < 0) { log_error("Error, opening device '%s': %m", node); return EXIT_FAILURE; } /* install list of map codes */ for (i = 0; i < map_count; i++) { log_debug("keyboard: mapping scan code %d (0x%x) to key code %d (0x%x)", map[i].scan, map[i].scan, map[i].key, map[i].key); if (ioctl(fd, EVIOCSKEYCODE, &map[i]) < 0) log_error("Error calling EVIOCSKEYCODE on device node '%s' (scan code 0x%x, key code %d): %m", node, map[i].scan, map[i].key); } /* install list of force-release codes */ if (release_count > 0) install_force_release(dev, release, release_count); close(fd); } return EXIT_SUCCESS; }
int open_wii_device(struct wiimoteglue_state *state, struct wii_device* dev) { if (dev->xwii != NULL) { return 0; //Already open. } if (dev->udev == NULL) { return -1; //Not even connected. } int i; struct xwii_iface *wiidev; char* syspath = udev_device_get_syspath(dev->udev); if (syspath == NULL) return -1; xwii_iface_new(&wiidev,syspath); xwii_iface_watch(wiidev,true); xwii_iface_open(wiidev, XWII_IFACE_WRITABLE | (XWII_IFACE_ALL ^ XWII_IFACE_ACCEL ^ XWII_IFACE_IR ^ XWII_IFACE_MOTION_PLUS)); if (!(xwii_iface_available(wiidev) & (XWII_IFACE_CORE | XWII_IFACE_PRO_CONTROLLER | XWII_IFACE_BALANCE_BOARD))) { printf("Tried to open a non-wiimote device...\n"); printf("Or we didn't have permission on the event devices?\n"); printf("You might need to add a udev rule to give permission.\n"); xwii_iface_unref(wiidev); return -1; } dev->xwii = wiidev; dev->ifaces = xwii_iface_opened(wiidev); if (state->ignore_pro && (dev->ifaces & XWII_IFACE_PRO_CONTROLLER)) { xwii_iface_unref(wiidev); dev->xwii = NULL; return 0; } dev->type = REMOTE; if (dev->ifaces & XWII_IFACE_BALANCE_BOARD) { dev->type = BALANCE; } if (dev->ifaces & XWII_IFACE_PRO_CONTROLLER) { dev->type = PRO; } dev->fd = xwii_iface_get_fd(wiidev); wiimoteglue_epoll_watch_wiimote(state->epfd, dev); compute_device_map(state,dev); if (dev->map->accel_active) { xwii_iface_open(wiidev,XWII_IFACE_ACCEL); } else { xwii_iface_close(wiidev,XWII_IFACE_ACCEL); } if (dev->map->IR_count) { xwii_iface_open(wiidev,XWII_IFACE_IR); } else { xwii_iface_close(wiidev,XWII_IFACE_IR); } /*LEDs only checked after opening, *and we want to store the state *only on the very initial opening.*/ if (dev->original_leds[0] == -2) store_led_state(state,dev); return 0; }
/* * A unique USB identification is generated like this: * * 1.) Get the USB device type from InterfaceClass and InterfaceSubClass * 2.) If the device type is 'Mass-Storage/SPC-2' or 'Mass-Storage/RBC', * use the SCSI vendor and model as USB-Vendor and USB-model. * 3.) Otherwise, use the USB manufacturer and product as * USB-Vendor and USB-model. Any non-printable characters * in those strings will be skipped; a slash '/' will be converted * into a full stop '.'. * 4.) If that fails, too, we will use idVendor and idProduct * as USB-Vendor and USB-model. * 5.) The USB identification is the USB-vendor and USB-model * string concatenated with an underscore '_'. * 6.) If the device supplies a serial number, this number * is concatenated with the identification with an underscore '_'. */ static int builtin_usb_id(struct udev_device *dev, int argc, char *argv[], bool test) { char vendor_str[64]; char vendor_str_enc[256]; const char *vendor_id; char model_str[64]; char model_str_enc[256]; const char *product_id; char serial_str[UTIL_NAME_SIZE]; char packed_if_str[UTIL_NAME_SIZE]; char revision_str[64]; char type_str[64]; char instance_str[64]; const char *ifnum = NULL; const char *driver = NULL; char serial[256]; struct udev_device *dev_interface = NULL; struct udev_device *dev_usb = NULL; const char *if_class, *if_subclass; int if_class_num; int protocol = 0; size_t l; char *s; vendor_str[0] = '\0'; model_str[0] = '\0'; serial_str[0] = '\0'; packed_if_str[0] = '\0'; revision_str[0] = '\0'; type_str[0] = '\0'; instance_str[0] = '\0'; /* shortcut, if we are called directly for a "usb_device" type */ if (udev_device_get_devtype(dev) != NULL && streq(udev_device_get_devtype(dev), "usb_device")) { dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str)); dev_usb = dev; goto fallback; } /* usb interface directory */ dev_interface = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface"); if (dev_interface == NULL) { log_debug("unable to access usb_interface device of '%s'", udev_device_get_syspath(dev)); return EXIT_FAILURE; } ifnum = udev_device_get_sysattr_value(dev_interface, "bInterfaceNumber"); driver = udev_device_get_sysattr_value(dev_interface, "driver"); if_class = udev_device_get_sysattr_value(dev_interface, "bInterfaceClass"); if (!if_class) { log_debug("%s: cannot get bInterfaceClass attribute", udev_device_get_sysname(dev)); return EXIT_FAILURE; } if_class_num = strtoul(if_class, NULL, 16); if (if_class_num == 8) { /* mass storage */ if_subclass = udev_device_get_sysattr_value(dev_interface, "bInterfaceSubClass"); if (if_subclass != NULL) protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1); } else { set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1); } log_debug("%s: if_class %d protocol %d", udev_device_get_syspath(dev_interface), if_class_num, protocol); /* usb device directory */ dev_usb = udev_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device"); if (!dev_usb) { log_debug("unable to find parent 'usb' device of '%s'", udev_device_get_syspath(dev)); return EXIT_FAILURE; } /* all interfaces of the device in a single string */ dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str)); /* mass storage : SCSI or ATAPI */ if ((protocol == 6 || protocol == 2)) { struct udev_device *dev_scsi; const char *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev; int host, bus, target, lun; /* get scsi device */ dev_scsi = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device"); if (dev_scsi == NULL) { log_debug("unable to find parent 'scsi' device of '%s'", udev_device_get_syspath(dev)); goto fallback; } if (sscanf(udev_device_get_sysname(dev_scsi), "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) { log_debug("invalid scsi device '%s'", udev_device_get_sysname(dev_scsi)); goto fallback; } /* Generic SPC-2 device */ scsi_vendor = udev_device_get_sysattr_value(dev_scsi, "vendor"); if (!scsi_vendor) { log_debug("%s: cannot get SCSI vendor attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } udev_util_encode_string(scsi_vendor, vendor_str_enc, sizeof(vendor_str_enc)); util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1); util_replace_chars(vendor_str, NULL); scsi_model = udev_device_get_sysattr_value(dev_scsi, "model"); if (!scsi_model) { log_debug("%s: cannot get SCSI model attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } udev_util_encode_string(scsi_model, model_str_enc, sizeof(model_str_enc)); util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1); util_replace_chars(model_str, NULL); scsi_type = udev_device_get_sysattr_value(dev_scsi, "type"); if (!scsi_type) { log_debug("%s: cannot get SCSI type attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } set_scsi_type(type_str, scsi_type, sizeof(type_str)-1); scsi_rev = udev_device_get_sysattr_value(dev_scsi, "rev"); if (!scsi_rev) { log_debug("%s: cannot get SCSI revision attribute", udev_device_get_sysname(dev_scsi)); goto fallback; } util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); /* * some broken devices have the same identifiers * for all luns, export the target:lun number */ sprintf(instance_str, "%d:%d", target, lun); } fallback: vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor"); product_id = udev_device_get_sysattr_value(dev_usb, "idProduct"); /* fallback to USB vendor & device */ if (vendor_str[0] == '\0') { const char *usb_vendor = NULL; usb_vendor = udev_device_get_sysattr_value(dev_usb, "manufacturer"); if (!usb_vendor) usb_vendor = vendor_id; if (!usb_vendor) { log_debug("No USB vendor information available"); return EXIT_FAILURE; } udev_util_encode_string(usb_vendor, vendor_str_enc, sizeof(vendor_str_enc)); util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1); util_replace_chars(vendor_str, NULL); } if (model_str[0] == '\0') { const char *usb_model = NULL; usb_model = udev_device_get_sysattr_value(dev_usb, "product"); if (!usb_model) usb_model = product_id; if (!usb_model) return EXIT_FAILURE; udev_util_encode_string(usb_model, model_str_enc, sizeof(model_str_enc)); util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1); util_replace_chars(model_str, NULL); } if (revision_str[0] == '\0') { const char *usb_rev; usb_rev = udev_device_get_sysattr_value(dev_usb, "bcdDevice"); if (usb_rev) { util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); } } if (serial_str[0] == '\0') { const char *usb_serial; usb_serial = udev_device_get_sysattr_value(dev_usb, "serial"); if (usb_serial) { const unsigned char *p; /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */ for (p = (unsigned char *)usb_serial; *p != '\0'; p++) if (*p < 0x20 || *p > 0x7f || *p == ',') { usb_serial = NULL; break; } } if (usb_serial) { util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1); util_replace_chars(serial_str, NULL); } } s = serial; l = strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL); if (serial_str[0] != '\0') l = strpcpyl(&s, l, "_", serial_str, NULL); if (instance_str[0] != '\0') strpcpyl(&s, l, "-", instance_str, NULL); udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str); udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc); udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id); udev_builtin_add_property(dev, test, "ID_MODEL", model_str); udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc); udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id); udev_builtin_add_property(dev, test, "ID_REVISION", revision_str); udev_builtin_add_property(dev, test, "ID_SERIAL", serial); if (serial_str[0] != '\0') udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str); if (type_str[0] != '\0') udev_builtin_add_property(dev, test, "ID_TYPE", type_str); if (instance_str[0] != '\0') udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str); udev_builtin_add_property(dev, test, "ID_BUS", "usb"); if (packed_if_str[0] != '\0') udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str); if (ifnum != NULL) udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum); if (driver != NULL) udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver); return EXIT_SUCCESS; }
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { struct udev *udev = udev_device_get_udev(names->pcidev); unsigned domain, bus, slot, func, dev_port = 0; size_t l; char *s; const char *attr; struct udev_device *pci = NULL; char slots[256], str[256]; _cleanup_closedir_ DIR *dir = NULL; struct dirent *dent; int hotplug_slot = 0, err = 0; if (sscanf(udev_device_get_sysname(names->pcidev), "%x:%x:%x.%u", &domain, &bus, &slot, &func) != 4) return -ENOENT; /* kernel provided port index for multiple ports on a single PCI function */ attr = udev_device_get_sysattr_value(dev, "dev_port"); if (attr) dev_port = strtol(attr, NULL, 10); /* compose a name based on the raw kernel's PCI bus, slot numbers */ s = names->pci_path; l = sizeof(names->pci_path); if (domain > 0) l = strpcpyf(&s, l, "P%u", domain); l = strpcpyf(&s, l, "p%us%u", bus, slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%u", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%u", dev_port); if (l == 0) names->pci_path[0] = '\0'; /* ACPI _SUN — slot user number */ pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); if (!pci) { err = -ENOENT; goto out; } xsprintf(slots, "%s/slots", udev_device_get_syspath(pci)); dir = opendir(slots); if (!dir) { err = -errno; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { int i; char *rest; char *address; if (dent->d_name[0] == '.') continue; i = strtol(dent->d_name, &rest, 10); if (rest[0] != '\0') continue; if (i < 1) continue; xsprintf(str, "%s/%s/address", slots, dent->d_name); if (read_one_line_file(str, &address) >= 0) { /* match slot address with device by stripping the function */ if (strneq(address, udev_device_get_sysname(names->pcidev), strlen(address))) hotplug_slot = i; free(address); } if (hotplug_slot > 0) break; } if (hotplug_slot > 0) { s = names->pci_slot; l = sizeof(names->pci_slot); if (domain > 0) l = strpcpyf(&s, l, "P%d", domain); l = strpcpyf(&s, l, "s%d", hotplug_slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = strpcpyf(&s, l, "f%d", func); if (dev_port > 0) l = strpcpyf(&s, l, "d%d", dev_port); if (l == 0) names->pci_slot[0] = '\0'; } out: udev_device_unref(pci); return err; }
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { struct udev *udev = udev_device_get_udev(names->pcidev); unsigned int bus; unsigned int slot; unsigned int func; unsigned int dev_id = 0; size_t l; char *s; const char *attr; struct udev_device *pci = NULL; char slots[256]; DIR *dir; struct dirent *dent; char str[256]; int hotplug_slot = 0; int err = 0; if (sscanf(udev_device_get_sysname(names->pcidev), "0000:%x:%x.%d", &bus, &slot, &func) != 3) return -ENOENT; /* kernel provided multi-device index */ attr = udev_device_get_sysattr_value(dev, "dev_id"); if (attr) dev_id = strtol(attr, NULL, 16); /* compose a name based on the raw kernel's PCI bus, slot numbers */ s = names->pci_path; l = util_strpcpyf(&s, sizeof(names->pci_path), "p%ds%d", bus, slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = util_strpcpyf(&s, l, "f%d", func); if (dev_id > 0) l = util_strpcpyf(&s, l, "d%d", dev_id); if (l == 0) names->pci_path[0] = '\0'; /* ACPI _SUN -- slot user number */ pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); if (!pci) { err = -ENOENT; goto out; } snprintf(slots, sizeof(slots), "%s/slots", udev_device_get_syspath(pci)); dir = opendir(slots); if (!dir) { err = -errno; goto out; } for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { int i; char *rest; char *address; if (dent->d_name[0] == '.') continue; i = strtol(dent->d_name, &rest, 10); if (rest[0] != '\0') continue; if (i < 1) continue; snprintf(str, sizeof(str), "%s/%s/address", slots, dent->d_name); if (read_one_line_file(str, &address) >= 0) { /* match slot address with device by stripping the function */ if (strncmp(address, udev_device_get_sysname(names->pcidev), strlen(address)) == 0) hotplug_slot = i; free(address); } if (hotplug_slot > 0) break; } closedir(dir); if (hotplug_slot > 0) { s = names->pci_slot; l = util_strpcpyf(&s, sizeof(names->pci_slot), "s%d", hotplug_slot); if (func > 0 || is_pci_multifunction(names->pcidev)) l = util_strpcpyf(&s, l, "f%d", func); if (dev_id > 0) l = util_strpcpyf(&s, l, "d%d", dev_id); if (l == 0) names->pci_path[0] = '\0'; } out: udev_device_unref(pci); return err; }
static int builtin_firmware(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev *udev = udev_device_get_udev(dev); static const char *searchpath[] = { FIRMWARE_PATH }; char loadpath[UTIL_PATH_SIZE]; char datapath[UTIL_PATH_SIZE]; char fwpath[UTIL_PATH_SIZE]; const char *firmware; FILE *fwfile = NULL; struct utsname kernel; struct stat statbuf; unsigned int i; int rc = EXIT_SUCCESS; firmware = udev_device_get_property_value(dev, "FIRMWARE"); if (firmware == NULL) { log_error("firmware parameter missing"); rc = EXIT_FAILURE; goto exit; } /* lookup firmware file */ uname(&kernel); for (i = 0; i < ELEMENTSOF(searchpath); i++) { strscpyl(fwpath, sizeof(fwpath), searchpath[i], kernel.release, "/", firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; strscpyl(fwpath, sizeof(fwpath), searchpath[i], firmware, NULL); fwfile = fopen(fwpath, "re"); if (fwfile != NULL) break; } strscpyl(loadpath, sizeof(loadpath), udev_device_get_syspath(dev), "/loading", NULL); if (fwfile == NULL) { log_debug("did not find firmware file '%s'", firmware); rc = EXIT_FAILURE; /* * Do not cancel the request in the initrd, the real root might have * the firmware file and the 'coldplug' run in the real root will find * this pending request and fulfill or cancel it. * */ if (!in_initrd()) set_loading(udev, loadpath, "-1"); goto exit; } if (stat(fwpath, &statbuf) < 0 || statbuf.st_size == 0) { if (!in_initrd()) set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; } if (!set_loading(udev, loadpath, "1")) goto exit; strscpyl(datapath, sizeof(datapath), udev_device_get_syspath(dev), "/data", NULL); if (!copy_firmware(udev, fwpath, datapath, statbuf.st_size)) { log_error("error sending firmware '%s' to device", firmware); set_loading(udev, loadpath, "-1"); rc = EXIT_FAILURE; goto exit; }; set_loading(udev, loadpath, "0"); exit: if (fwfile) fclose(fwfile); return rc; }
int main(int argc, char *argv[]) { static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "mode", required_argument, NULL, 'm' }, { "devpath", required_argument, NULL, 'p' }, { "method", required_argument, NULL, 'M' }, { } }; enum method { METHOD_UNDEF, METHOD_CSR, METHOD_LOGITECH_HID, METHOD_DELL, } method = METHOD_UNDEF; struct udev *udev; struct udev_device *udev_dev = NULL; char syspath[PATH_MAX]; int (*usb_switch)(int fd, enum mode mode) = NULL; enum mode mode = HCI; const char *devpath = NULL; int err = -1; int rc = 1; for (;;) { int option; option = getopt_long(argc, argv, "m:p:M:h", options, NULL); if (option == -1) break; switch (option) { case 'm': if (!strcmp(optarg, "hid")) { mode = HID; } else if (!strcmp(optarg, "hci")) { mode = HCI; } else { usage("error: undefined radio mode\n"); exit(1); } break; case 'p': devpath = optarg; break; case 'M': if (!strcmp(optarg, "csr")) { method = METHOD_CSR; usb_switch = usb_switch_csr; } else if (!strcmp(optarg, "logitech-hid")) { method = METHOD_LOGITECH_HID; } else if (!strcmp(optarg, "dell")) { method = METHOD_DELL; usb_switch = usb_switch_dell; } else { usage("error: undefined switching method\n"); exit(1); } break; case 'h': usage(NULL); } } if (!devpath || method == METHOD_UNDEF) { usage("error: --devpath= and --method= must be defined\n"); exit(1); } udev = udev_new(); if (udev == NULL) goto exit; snprintf(syspath, sizeof(syspath), "/sys/%s", devpath); udev_dev = udev_device_new_from_syspath(udev, syspath); if (udev_dev == NULL) { fprintf(stderr, "error: could not find '%s'\n", devpath); goto exit; } switch (method) { case METHOD_CSR: case METHOD_DELL: { struct udev_device *dev; int handle; const char *type; /* get the parent usb_device if needed */ dev = udev_dev; type = udev_device_get_devtype(dev); if (type == NULL || strcmp(type, "usb_device") != 0) { dev = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_device"); if (dev == NULL) { fprintf(stderr, "error: could not find usb_device for '%s'\n", devpath); goto exit; } } handle = find_device(dev); if (handle < 0) { fprintf(stderr, "error: unable to handle '%s'\n", udev_device_get_syspath(dev)); goto exit; } err = usb_switch(handle, mode); close(handle); break; } case METHOD_LOGITECH_HID: { const char *device; device = udev_device_get_devnode(udev_dev); if (device == NULL) { fprintf(stderr, "error: could not find hiddev device node\n"); goto exit; } err = hid_switch_logitech(device); break; } default: break; } if (err < 0) fprintf(stderr, "error: switching device '%s' failed.\n", udev_device_get_syspath(udev_dev)); exit: udev_device_unref(udev_dev); udev_unref(udev); return rc; }
ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK udevGetIfaceDefBridge(struct udev *udev, struct udev_device *dev, const char *name, virInterfaceDef *ifacedef) { struct dirent **member_list = NULL; int member_count = 0; char *member_path; const char *tmp_str; int stp; size_t i; /* Set our type to Bridge */ ifacedef->type = VIR_INTERFACE_TYPE_BRIDGE; /* Retrieve the forward delay */ tmp_str = udev_device_get_sysattr_value(dev, "bridge/forward_delay"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bridge/forward_delay' for '%s'"), name); goto error; } if (VIR_STRDUP(ifacedef->data.bridge.delay, tmp_str) < 0) goto error; /* Retrieve Spanning Tree State. Valid values = -1, 0, 1 */ tmp_str = udev_device_get_sysattr_value(dev, "bridge/stp_state"); if (!tmp_str) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not retrieve 'bridge/stp_state' for '%s'"), name); goto error; } if (virStrToLong_i(tmp_str, NULL, 10, &stp) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not parse 'bridge/stp_state' '%s' for '%s'"), tmp_str, name); goto error; } switch (stp) { case -1: case 0: case 1: ifacedef->data.bridge.stp = stp; break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("Invalid STP state value %d received for '%s'. Must be " "-1, 0, or 1."), stp, name); goto error; } /* Members of the bridge */ if (virAsprintf(&member_path, "%s/%s", udev_device_get_syspath(dev), "brif") < 0) goto error; /* Get each member of the bridge */ member_count = scandir(member_path, &member_list, udevBridgeScanDirFilter, alphasort); /* Don't need the path anymore */ VIR_FREE(member_path); if (member_count < 0) { virReportSystemError(errno, _("Could not get members of bridge '%s'"), name); goto error; } /* Allocate our list of member devices */ if (VIR_ALLOC_N(ifacedef->data.bridge.itf, member_count) < 0) goto error; ifacedef->data.bridge.nbItf = member_count; /* Get the interface defintions for each member of the bridge */ for (i = 0; i < member_count; i++) { ifacedef->data.bridge.itf[i] = udevGetIfaceDef(udev, member_list[i]->d_name); if (!ifacedef->data.bridge.itf[i]) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Could not get interface information for '%s', which is " "a member of bridge '%s'"), member_list[i]->d_name, name); goto error; } VIR_FREE(member_list[i]); } VIR_FREE(member_list); return 0; error: for (i = 0; member_count != -1 && i < member_count; i++) { VIR_FREE(member_list[i]); } VIR_FREE(member_list); return -1; }