static int usb_emul_get_descriptor(struct usb_dev_platdata *plat, int value, void *buffer, int length) { struct usb_generic_descriptor **ptr; int type = value >> 8; int index = value & 0xff; int upto, todo; debug("%s: type=%d, index=%d, plat=%p\n", __func__, type, index, plat); if (type == USB_DT_STRING) { return usb_emul_get_string(plat->strings, index, buffer, length); } ptr = find_descriptor((struct usb_generic_descriptor **)plat->desc_list, type, index); if (!ptr) { debug("%s: Could not find descriptor type %d, index %d\n", __func__, type, index); return -ENOENT; } for (upto = 0; *ptr && upto < length; ptr++, upto += todo) { todo = min(length - upto, (int)(*ptr)->bLength); memcpy(buffer + upto, *ptr, todo); } return upto ? upto : length ? -EIO : 0; }
size_t list_make_sequence(struct list_table* table, size_t a, size_t b) { size_t id = list_allocate_int(table); struct list_descriptor* desc = find_descriptor(table, id); for(size_t i = a; i <= b; ++i) insert_list_element(desc, desc->list_size, &i); return id; }
/* Look for a descriptor in the active configuration * Will also find extra descriptors which are normally * not returned by the standard libusb_get_descriptor() */ int usb_get_any_descriptor(struct libusb_device_handle *dev_handle, uint8_t desc_type, uint8_t desc_index, unsigned char *resbuf, int res_len) { struct libusb_device *dev; struct libusb_config_descriptor *config; int ret; uint16_t conflen; unsigned char *cbuf; dev = libusb_get_device(dev_handle); if (!dev) { fprintf(stderr, "Error: Broken device handle\n"); return -1; } /* Get the total length of the configuration descriptors */ ret = libusb_get_active_config_descriptor(dev, &config); if (ret == LIBUSB_ERROR_NOT_FOUND) { fprintf(stderr, "Error: Device is unconfigured\n"); return -1; } else if (ret) { fprintf(stderr, "Error: failed " "libusb_get_active_config_descriptor()\n"); exit(1); } conflen = config->wTotalLength; libusb_free_config_descriptor(config); /* Suck in the configuration descriptor list from device */ cbuf = malloc(conflen); ret = libusb_get_descriptor(dev_handle, LIBUSB_DT_CONFIG, desc_index, cbuf, conflen); if (ret < conflen) { fprintf(stderr, "Warning: failed to retrieve complete " "configuration descriptor, got %i/%i\n", ret, conflen); conflen = ret; } /* Search through the configuration descriptor list */ ret = find_descriptor(cbuf, conflen, desc_type, desc_index, resbuf, res_len); free(cbuf); /* A descriptor must be at least 2 bytes long */ if (ret > 1) { if (verbose) printf("Found descriptor in complete configuration " "descriptor list\n"); return ret; } /* Finally try to retrieve it requesting the device directly * This is not supported on all devices for non-standard types */ return libusb_get_descriptor(dev_handle, desc_type, desc_index, resbuf, res_len); }
void list_insert_bool(struct list_table* table, size_t lid, size_t pos, bool value) { if(!table) return; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return; insert_list_element(desc, pos, &value); }
void list_push_back_string(struct list_table* table, size_t lid, size_t value) { if(!table) return; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return; insert_list_element(desc, desc->list_size, &value); }
void list_push_front_char(struct list_table* table, size_t lid, char value) { if(!table) return; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return; insert_list_element(desc, 0, &value); }
void list_add_reference(struct list_table* table, size_t lid) { if(!table) return; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return; desc->ref_count++; }
size_t list_size(struct list_table* table, size_t lid) { if(!table) return 0; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return 0; return desc->list_size; }
char list_get_char(struct list_table* table, size_t lid, size_t pos) { if(!table) return '\0'; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return '\0'; void* value = get_list_element(desc, pos); return *((char*)value); }
bool list_back_bool(struct list_table* table, size_t lid) { if(!table) return 0; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return 0; void* value = get_list_element(desc, desc->list_size - 1); return *((bool*)value); }
float list_front_float(struct list_table* table, size_t lid) { if(!table) return 0; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return 0; void* value = get_list_element(desc, 0); return *((float*)value); }
size_t list_get_string(struct list_table* table, size_t lid, size_t pos) { if(!table) return 0; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return 0; void* value = get_list_element(desc, pos); return *((size_t*)value); }
size_t list_pop_back_string(struct list_table* table, size_t lid) { if(!table) return 0; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return 0; void* value = remove_list_element(desc, desc->list_size - 1); size_t casted_value = *((size_t*)value); free(value); return casted_value; }
char list_pop_back_char(struct list_table* table, size_t lid) { if(!table) return '\0'; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return '\0'; void* value = remove_list_element(desc, desc->list_size - 1); char casted_value = *((char*)value); free(value); return casted_value; }
bool list_pop_front_bool(struct list_table* table, size_t lid) { if(!table) return 0; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return 0; void* value = remove_list_element(desc, 0); bool casted_value = *((bool*)value); free(value); return casted_value; }
void list_rm_reference(struct list_table* table, size_t lid) { if(!table) return; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return; desc->ref_count--; if(desc->ref_count == 0) // list shouldn't be freed list_deallocate(table, lid); }
char list_remove_char(struct list_table* table, size_t lid, size_t pos) { if(!table) return 0; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return 0; void* value = remove_list_element(desc, pos); char casted_value = *((char*)value); free(value); return casted_value; }
enum hxb_datatype endpoint_get_datatype(uint32_t eid) { if (eid % 32 == 0) { return HXB_DTYPE_UINT32; } else { struct endpoint_descriptor ep = {}; if (find_descriptor(eid, &ep)) { return ep.datatype; } else { return HXB_DTYPE_UNDEFINED; } } }
enum hxb_error_code endpoint_read(uint32_t eid, struct hxb_value* value) { if (eid % 32 == 0) { synthesize_read_m32(eid, value); return HXB_ERR_SUCCESS; } else { struct endpoint_descriptor ep = {}; if (find_descriptor(eid, &ep)) { value->datatype = ep.datatype; return ep.read(value); } else { return HXB_ERR_UNKNOWNEID; } } }
void list_clear(struct list_table* table, size_t lid) { if(!table) return; struct list_descriptor* desc = find_descriptor(table, lid); if(!desc) return; if(!desc->list_head) // list is already empty return; // set to null the head and the tail desc->list_head = desc->list_tail = free_node_recur(desc->list_head); desc->list_size = 0; }
/* Remove watch associated with (descriptor, id). */ static void remove_watch (Lisp_Object descriptor, Lisp_Object id) { Lisp_Object prevtail = find_descriptor (descriptor); if (NILP (prevtail)) return; Lisp_Object elt = XCAR (CONSP (prevtail) ? XCDR (prevtail) : watch_list); for (Lisp_Object prev = elt; !NILP (XCDR (prev)); prev = XCDR (prev)) if (EQ (id, XCAR (XCAR (XCDR (prev))))) { XSETCDR (prev, XCDR (XCDR (prev))); if (NILP (XCDR (elt))) remove_descriptor (prevtail, false); break; } }
/* Look for a descriptor in the active configuration * Will also find extra descriptors which are normally * not returned by the standard libusb_get_descriptor() */ static int usb_get_any_descriptor(struct libusb_device_handle *dev_handle, uint8_t desc_type, uint8_t desc_index, unsigned char *resbuf, int res_len) { struct libusb_device *dev; struct libusb_config_descriptor *config; int ret; uint16_t conflen; unsigned char *cbuf; dev = libusb_get_device(dev_handle); if (!dev) { return -1; } /* Get the total length of the configuration descriptors */ ret = libusb_get_active_config_descriptor(dev, &config); if (ret) return -1; conflen = config->wTotalLength; libusb_free_config_descriptor(config); /* Suck in the configuration descriptor list from device */ cbuf = (unsigned char *)malloc(conflen); ret = libusb_get_descriptor(dev_handle, LIBUSB_DT_CONFIG, desc_index, cbuf, conflen); if (ret < conflen) { conflen = ret; } /* Search through the configuration descriptor list */ ret = find_descriptor(cbuf, conflen, desc_type, desc_index, resbuf, res_len); free(cbuf); /* A descriptor must be at least 2 bytes long */ if (ret > 1) { return ret; } /* Finally try to retrieve it requesting the device directly * This is not supported on all devices for non-standard types */ return libusb_get_descriptor(dev_handle, desc_type, desc_index, resbuf, res_len); }
enum hxb_error_code endpoint_get_name(uint32_t eid, char* buffer, size_t len) { if (eid % 32 == 0) { if (len >= nvm_size(domain_name)) { len = nvm_size(domain_name) - 1; } nvm_read_block(domain_name, buffer, len); buffer[nvm_size(domain_name)] = '\0'; return HXB_ERR_SUCCESS; } else { struct endpoint_descriptor ep; if (find_descriptor(eid, &ep)) { strncpy_from_rodata(buffer, ep.name, len); return HXB_ERR_SUCCESS; } else { return HXB_ERR_UNKNOWNEID; } } }
enum hxb_error_code endpoint_write(uint32_t eid, const struct hxb_envelope* env) { if (eid % 32 == 0) { return HXB_ERR_WRITEREADONLY; } else { struct endpoint_descriptor ep = {}; if (find_descriptor(eid, &ep)) { if (ep.write == 0) { return HXB_ERR_WRITEREADONLY; } else if (ep.datatype != env->value.datatype) { return HXB_ERR_DATATYPE; } else { return ep.write(env); } } else { return HXB_ERR_UNKNOWNEID; } } }
OptPluginBasePtr OptPluginRegistry::get_instance(const std::string& name) { BlockWriteLock lock(*this); OptPluginDescriptor* desc = find_descriptor(name); if (desc == NULL) return OptPluginBasePtr(); OptPluginBasePtr inst = desc->create_instance(); if (!inst) return OptPluginBasePtr(); ++descriptors_[desc]; plugins_[inst.get()] = desc; changed(lock); return inst; }
/* This callback is called when the FD is available for read. The inotify events are read from FD and converted into input_events. */ static void inotify_callback (int fd, void *_) { int to_read; if (ioctl (fd, FIONREAD, &to_read) < 0) report_file_notify_error ("Error while retrieving file system events", Qnil); USE_SAFE_ALLOCA; char *buffer = SAFE_ALLOCA (to_read); ssize_t n = read (fd, buffer, to_read); if (n < 0) report_file_notify_error ("Error while reading file system events", Qnil); struct input_event event; EVENT_INIT (event); event.kind = FILE_NOTIFY_EVENT; for (ssize_t i = 0; i < n; ) { struct inotify_event *ev = (struct inotify_event *) &buffer[i]; Lisp_Object descriptor = INTEGER_TO_CONS (ev->wd); Lisp_Object prevtail = find_descriptor (descriptor); if (! NILP (prevtail)) { Lisp_Object tail = CONSP (prevtail) ? XCDR (prevtail) : watch_list; for (Lisp_Object watches = XCDR (XCAR (tail)); ! NILP (watches); watches = XCDR (watches)) { event.arg = inotifyevent_to_event (XCAR (watches), ev); if (!NILP (event.arg)) kbd_buffer_store_event (&event); } /* If event was removed automatically: Drop it from watch list. */ if (ev->mask & IN_IGNORED) remove_descriptor (prevtail, true); } i += sizeof (*ev) + ev->len; } SAFE_FREE (); }
/* Get cached extra descriptor from libusb for an interface * Returns length of found descriptor */ int get_cached_extra_descriptor(struct libusb_device *dev, uint8_t bConfValue, uint8_t intf, uint8_t desc_type, uint8_t desc_index, unsigned char *resbuf, int res_len) { struct libusb_config_descriptor *cfg; const unsigned char *extra; int extra_len; int ret; int alt; ret = libusb_get_config_descriptor_by_value(dev, bConfValue, &cfg); if (ret == LIBUSB_ERROR_NOT_FOUND) { fprintf(stderr, "Error: Device is unconfigured\n"); return -1; } else if (ret) { fprintf(stderr, "Error: failed " "libusb_config_descriptor_by_value()\n"); exit(1); } /* Extra descriptors can be shared between alternate settings but * libusb may attach them to one setting. Therefore go through all. * Note that desc_index is per alternate setting, hits will not be * counted from one to another */ for (alt = 0; alt < cfg->interface[intf].num_altsetting; alt++) { extra = cfg->interface[intf].altsetting[alt].extra; extra_len = cfg->interface[intf].altsetting[alt].extra_length; if (extra_len > 1) ret = find_descriptor(extra, extra_len, desc_type, desc_index, resbuf, res_len); if (ret > 1) break; } libusb_free_config_descriptor(cfg); if (ret < 2 && verbose) printf("Did not find cached descriptor\n"); return ret; }
static void probe_configuration(libusb_device *dev, struct libusb_device_descriptor *desc) { struct usb_dfu_func_descriptor func_dfu; libusb_device_handle *devh; struct dfu_if *pdfu; struct libusb_config_descriptor *cfg; const struct libusb_interface_descriptor *intf; const struct libusb_interface *uif; char alt_name[MAX_DESC_STR_LEN + 1]; char serial_name[MAX_DESC_STR_LEN + 1]; int cfg_idx; int intf_idx; int alt_idx; int ret; int has_dfu; for (cfg_idx = 0; cfg_idx != desc->bNumConfigurations; cfg_idx++) { memset(&func_dfu, 0, sizeof(func_dfu)); has_dfu = 0; ret = libusb_get_config_descriptor(dev, cfg_idx, &cfg); if (ret != 0) return; if (match_config_index > -1 && match_config_index != cfg->bConfigurationValue) { libusb_free_config_descriptor(cfg); continue; } /* * In some cases, noticably FreeBSD if uid != 0, * the configuration descriptors are empty */ if (!cfg) return; ret = find_descriptor(cfg->extra, cfg->extra_length, USB_DT_DFU, &func_dfu, sizeof(func_dfu)); if (ret > -1) goto found_dfu; for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; intf_idx++) { uif = &cfg->interface[intf_idx]; if (!uif) break; for (alt_idx = 0; alt_idx < cfg->interface[intf_idx].num_altsetting; alt_idx++) { intf = &uif->altsetting[alt_idx]; if (intf->bInterfaceClass != 0xfe || intf->bInterfaceSubClass != 1) continue; ret = find_descriptor(intf->extra, intf->extra_length, USB_DT_DFU, &func_dfu, sizeof(func_dfu)); if (ret > -1) goto found_dfu; has_dfu = 1; } } if (has_dfu) { /* * Finally try to retrieve it requesting the * device directly This is not supported on * all devices for non-standard types */ if (libusb_open(dev, &devh) == 0) { ret = libusb_get_descriptor(devh, USB_DT_DFU, 0, (void *)&func_dfu, sizeof(func_dfu)); libusb_close(devh); if (ret > -1) goto found_dfu; } warnx("Device has DFU interface, " "but has no DFU functional descriptor"); /* fake version 1.0 */ func_dfu.bLength = 7; func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); goto found_dfu; } libusb_free_config_descriptor(cfg); continue; found_dfu: if (func_dfu.bLength == 7) { printf("Deducing device DFU version from functional descriptor " "length\n"); func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); } else if (func_dfu.bLength < 9) { printf("Error obtaining DFU functional descriptor\n"); printf("Please report this as a bug!\n"); printf("Warning: Assuming DFU version 1.0\n"); func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0100); printf("Warning: Transfer size can not be detected\n"); func_dfu.wTransferSize = 0; } for (intf_idx = 0; intf_idx < cfg->bNumInterfaces; intf_idx++) { if (match_iface_index > -1 && match_iface_index != intf_idx) continue; uif = &cfg->interface[intf_idx]; if (!uif) break; for (alt_idx = 0; alt_idx < uif->num_altsetting; alt_idx++) { int dfu_mode; intf = &uif->altsetting[alt_idx]; if (intf->bInterfaceClass != 0xfe || intf->bInterfaceSubClass != 1) continue; dfu_mode = (intf->bInterfaceProtocol == 2); /* e.g. DSO Nano has bInterfaceProtocol 0 instead of 2 */ if (func_dfu.bcdDFUVersion == 0x011a && intf->bInterfaceProtocol == 0) dfu_mode = 1; /* LPC DFU bootloader has bInterfaceProtocol 1 (Runtime) instead of 2 */ if (desc->idVendor == 0x1fc9 && desc->idProduct == 0x000c && intf->bInterfaceProtocol == 1) dfu_mode = 1; if (dfu_mode && match_iface_alt_index > -1 && match_iface_alt_index != alt_idx) continue; if (dfu_mode) { if ((match_vendor_dfu >= 0 && match_vendor_dfu != desc->idVendor) || (match_product_dfu >= 0 && match_product_dfu != desc->idProduct)) { continue; } } else { if ((match_vendor >= 0 && match_vendor != desc->idVendor) || (match_product >= 0 && match_product != desc->idProduct)) { continue; } } if (libusb_open(dev, &devh)) { warnx("Cannot open DFU device %04x:%04x", desc->idVendor, desc->idProduct); break; } if (intf->iInterface != 0) ret = libusb_get_string_descriptor_ascii(devh, intf->iInterface, (void *)alt_name, MAX_DESC_STR_LEN); else ret = -1; if (ret < 1) strcpy(alt_name, "UNKNOWN"); if (desc->iSerialNumber != 0) ret = libusb_get_string_descriptor_ascii(devh, desc->iSerialNumber, (void *)serial_name, MAX_DESC_STR_LEN); else ret = -1; if (ret < 1) strcpy(serial_name, "UNKNOWN"); libusb_close(devh); if (dfu_mode && match_iface_alt_name != NULL && strcmp(alt_name, match_iface_alt_name)) continue; if (dfu_mode) { if (match_serial_dfu != NULL && strcmp(match_serial_dfu, serial_name)) continue; } else { if (match_serial != NULL && strcmp(match_serial, serial_name)) continue; } pdfu = dfu_malloc(sizeof(*pdfu)); memset(pdfu, 0, sizeof(*pdfu)); pdfu->func_dfu = func_dfu; pdfu->dev = libusb_ref_device(dev); pdfu->quirks = get_quirks(desc->idVendor, desc->idProduct, desc->bcdDevice); pdfu->vendor = desc->idVendor; pdfu->product = desc->idProduct; pdfu->bcdDevice = desc->bcdDevice; pdfu->configuration = cfg->bConfigurationValue; pdfu->interface = intf->bInterfaceNumber; pdfu->altsetting = intf->bAlternateSetting; pdfu->devnum = libusb_get_device_address(dev); pdfu->busnum = libusb_get_bus_number(dev); pdfu->alt_name = strdup(alt_name); if (pdfu->alt_name == NULL) errx(EX_SOFTWARE, "Out of memory"); pdfu->serial_name = strdup(serial_name); if (pdfu->serial_name == NULL) errx(EX_SOFTWARE, "Out of memory"); if (dfu_mode) pdfu->flags |= DFU_IFF_DFU; if (pdfu->quirks & QUIRK_FORCE_DFU11) { pdfu->func_dfu.bcdDFUVersion = libusb_cpu_to_le16(0x0110); } pdfu->bMaxPacketSize0 = desc->bMaxPacketSize0; /* queue into list */ pdfu->next = dfu_root; dfu_root = pdfu; } } libusb_free_config_descriptor(cfg); } }