/* * Class: ch_ntb_usb_LibusbJava * Method: usb_get_descriptor * Signature: (JBBI)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_ch_ntb_usb_LibusbJava_usb_1get_1descriptor (JNIEnv *env, jclass obj, jlong dev_handle, jbyte type, jbyte index, jint size) { clearLibusbJavaError(); char *string = (char *) malloc(size * sizeof(char)); int retVal = usb_get_descriptor((usb_dev_handle *) dev_handle, (unsigned) type, (unsigned) index, string, size); if (retVal > 0) return (*env)->NewStringUTF(env, string); return 0; }
int musb_get_device(MUSB_INTERFACE *usb_interface) { #ifdef HAVE_LIBUSB struct usb_device_descriptor d; usb_get_descriptor(usb_interface->dev, USB_DT_DEVICE, 0, &d, sizeof(d)); return d.bcdDevice; #elif HAVE_LIBUSB10 struct libusb_device_descriptor d; libusb_get_descriptor(usb_interface->dev, LIBUSB_DT_DEVICE, 0, (unsigned char *)&d, sizeof(d)); return d.bcdDevice; #else return 0; #endif }
//----------------------------------------------------------------- // get_descriptor: //----------------------------------------------------------------- static void get_descriptor(struct device_request *request) { unsigned char bDescriptorType = HI_BYTE(request->wValue); unsigned char bDescriptorIndex = LO_BYTE( request->wValue ); unsigned short wLength = request->wLength; unsigned char bCount = 0; unsigned char *desc_ptr; desc_ptr = usb_get_descriptor(bDescriptorType, bDescriptorIndex, wLength, &bCount); if (desc_ptr) usb_control_send(desc_ptr, bCount); else usbhw_control_endpoint_stall(); }
/* * usb_get_device_descriptor - (re)reads the device descriptor (usbcore) * @dev: the device whose device descriptor is being updated * @size: how much of the descriptor to read * Context: !in_interrupt () * * Updates the copy of the device descriptor stored in the device structure, * which dedicates space for this purpose. * * Not exported, only for use by the core. If drivers really want to read * the device descriptor directly, they can call usb_get_descriptor() with * type = USB_DT_DEVICE and index = 0. * * This call is synchronous, and may not be used in an interrupt context. * * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) { struct usb_device_descriptor *desc; int ret; if (size > sizeof(*desc)) return -EINVAL; desc = kmalloc(sizeof(*desc), GFP_NOIO); if (!desc) return -ENOMEM; ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size); if (ret >= 0) memcpy(&dev->descriptor, desc, size); kfree(desc); return ret; }
static int get_desc(struct drive_info *drive) { struct usb_device_descriptor descriptor; usb_dev_handle *udev; udev=usb_open(drive->usbdev); if(!udev) return 1; if(usb_get_descriptor(udev,USB_DT_DEVICE,0,&descriptor,sizeof(descriptor))!=sizeof(descriptor)) { usb_close(udev); return 1; } if(usb_get_string_simple(udev,descriptor.iProduct,drive->desc,256)<=0) { usb_close(udev); return 1; } usb_close(udev); return 0; }
static int l_usb_get_descriptor(lua_State *L) { struct usb_dev_handle * dev_handle = lua_touserdata(L, 1); int type = lua_tonumber(L, 2); int index = lua_tonumber (L, 3); int size = lua_tonumber (L, 4); if (size==0) {size=255;} //default value char buf[size]; int ret = usb_get_descriptor(dev_handle, (unsigned char)type, (unsigned char)index, buf, size); if( ret < 0 ) { lua_pushnil (L); lua_pushnumber (L, ret); return 2; /* number of results */ } else{ lua_pushlstring (L, buf, ret); return 1; /* number of results */ } }
/* USB::DevHandle#usb_get_descriptor(type, index, buf) */ static VALUE rusb_get_descriptor( VALUE v, VALUE vtype, VALUE vindex, VALUE vbuf) { usb_dev_handle *p = get_usb_devhandle(v); int type = NUM2INT(vtype); int index = NUM2INT(vindex); char *buf; int buflen; int ret; StringValue(vbuf); rb_str_modify(vbuf); buf = RSTRING_PTR(vbuf); buflen = RSTRING_LEN(vbuf); ret = usb_get_descriptor(p, type, index, buf, buflen); check_usb_error("usb_get_descriptor", ret); return INT2NUM(ret); }
/** * usb_get_device_descriptor - (re)reads the device descriptor * @dev: the device whose device descriptor is being updated * @size: how much of the descriptor to read * Context: !in_interrupt () * * Updates the copy of the device descriptor stored in the device structure, * which dedicates space for this purpose. Note that several fields are * converted to the host CPU's byte order: the USB version (bcdUSB), and * vendors product and version fields (idVendor, idProduct, and bcdDevice). * That lets device drivers compare against non-byteswapped constants. * * Not exported, only for use by the core. If drivers really want to read * the device descriptor directly, they can call usb_get_descriptor() with * type = USB_DT_DEVICE and index = 0. * * This call is synchronous, and may not be used in an interrupt context. * * Returns the number of bytes received on success, or else the status code * returned by the underlying usb_control_msg() call. */ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size) { struct usb_device_descriptor *desc; int ret; if (size > sizeof(*desc)) return -EINVAL; desc = kmalloc(sizeof(*desc), GFP_NOIO); if (!desc) return -ENOMEM; ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size); if (ret >= 0) { le16_to_cpus(&desc->bcdUSB); le16_to_cpus(&desc->idVendor); le16_to_cpus(&desc->idProduct); le16_to_cpus(&desc->bcdDevice); memcpy(&dev->descriptor, desc, size); } msleep(1); kfree(desc); return ret; }
//! usb_process_request. //! //! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! @note list of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bmRequest; bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } else goto user_read; break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } else goto user_read; break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } else goto user_read; break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } else goto user_read; break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } else goto user_read; break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } else goto user_read; break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } else goto user_read; break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } else goto user_read; break; case SET_INTERFACE: if (bmRequestType == 0x01) {usb_set_interface();} break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request user_read: usb_user_read_request(bmRequestType, bmRequest); break; } Usb_select_endpoint(EP_CONTROL); // If the receive setup flag hasn't been cleared // by this point then we can assume that we didn't // support this request and should stall. if(Is_usb_receive_setup()) Usb_enable_stall_handshake(); // Clear some flags. Usb_ack_receive_setup(); Usb_ack_receive_out(); Usb_ack_in_ready(); }
void usb_fetch_and_parse_descriptors(usb_dev_handle *udev) { struct usb_device *dev = udev->device; int i; if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { if (usb_debug >= 1) fprintf(stderr, "Too many configurations (%d > %d)\n", dev->descriptor.bNumConfigurations, USB_MAXCONFIG); return; } if (dev->descriptor.bNumConfigurations < 1) { if (usb_debug >= 1) fprintf(stderr, "Not enough configurations (%d < %d)\n", dev->descriptor.bNumConfigurations, 1); return; } dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); if (!dev->config) { if (usb_debug >= 1) fprintf(stderr, "Unable to allocate memory for config descriptor\n"); return; } memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { unsigned char buffer[8], *bigbuffer; struct usb_config_descriptor config; int res; /* Get the first 8 bytes so we can figure out what the total length is */ res = usb_get_descriptor(udev, USB_DT_CONFIG, (unsigned char)i, buffer, 8); if (res < 8) { if (usb_debug >= 1) { if (res < 0) fprintf(stderr, "Unable to get descriptor (%d)\n", res); else fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, res); } goto err; } usb_parse_descriptor(buffer, "bbw", &config); bigbuffer = malloc(config.wTotalLength); if (!bigbuffer) { if (usb_debug >= 1) fprintf(stderr, "Unable to allocate memory for descriptors\n"); goto err; } res = usb_get_descriptor(udev, USB_DT_CONFIG, (unsigned char)i, bigbuffer, config.wTotalLength); if (res < config.wTotalLength) { if (usb_debug >= 1) { if (res < 0) fprintf(stderr, "Unable to get descriptor (%d)\n", res); else fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, res); } free(bigbuffer); goto err; } res = usb_parse_configuration(&dev->config[i], bigbuffer); if (usb_debug >= 2) { if (res > 0) fprintf(stderr, "Descriptor data still left\n"); else if (res < 0) fprintf(stderr, "Unable to parse descriptors\n"); } free(bigbuffer); } return; err: free(dev->config); dev->config = NULL; }
/* This function reads the Microsoft OS Descriptor and looks inside to * find if it is a MTP device. This is the similar to the way that * Windows Media Player 10 uses. * It is documented to some degree on various internet pages. */ static int gp_libusb1_match_mtp_device(struct libusb_device *dev,int *configno, int *interfaceno, int *altsettingno) { /* Marcus: Avoid this probing altogether, its too unstable on some devices */ return 0; #if 0 char buf[1000], cmd; int ret,i,i1,i2, xifaces,xnocamifaces; usb_dev_handle *devh; /* All of them are "vendor specific" device class */ #if 0 if ((desc.bDeviceClass!=0xff) && (desc.bDeviceClass!=0)) return 0; #endif if (dev->config) { xifaces = xnocamifaces = 0; for (i = 0; i < desc.bNumConfigurations; i++) { unsigned int j; for (j = 0; j < dev->config[i].bNumInterfaces; j++) { int k; xifaces++; for (k = 0; k < dev->config[i].interface[j].num_altsetting; k++) { struct usb_interface_descriptor *intf = &dev->config[i].interface[j].altsetting[k]; if ( (intf->bInterfaceClass == LIBUSB_CLASS_HID) || (intf->bInterfaceClass == LIBUSB_CLASS_PRINTER) || (intf->bInterfaceClass == LIBUSB_CLASS_AUDIO) || (intf->bInterfaceClass == LIBUSB_CLASS_HUB) || (intf->bInterfaceClass == LIBUSB_CLASS_COMM) || (intf->bInterfaceClass == 0xe0) /* wireless/bluetooth*/ ) xnocamifaces++; } } } } if (xifaces == xnocamifaces) /* only non-camera ifaces */ return 0; devh = usb_open (dev); if (!devh) return 0; /* * Loop over the device configurations and interfaces. Nokia MTP-capable * handsets (possibly others) typically have the string "MTP" in their * MTP interface descriptions, that's how they can be detected, before * we try the more esoteric "OS descriptors" (below). */ if (dev->config) { for (i = 0; i < desc.bNumConfigurations; i++) { unsigned int j; for (j = 0; j < dev->config[i].bNumInterfaces; j++) { int k; for (k = 0; k < dev->config[i].interface[j].num_altsetting; k++) { buf[0] = '\0'; ret = usb_get_string_simple(devh, dev->config[i].interface[j].altsetting[k].iInterface, (char *) buf, 1024); if (ret < 3) continue; if (strcmp((char *) buf, "MTP") == 0) { GP_LOG_D ("Configuration %d, interface %d, altsetting %d:\n", i, j, k); GP_LOG_D (" Interface description contains the string \"MTP\"\n"); GP_LOG_D (" Device recognized as MTP, no further probing.\n"); goto found; } } } } } /* get string descriptor at 0xEE */ ret = usb_get_descriptor (devh, 0x03, 0xee, buf, sizeof(buf)); if (ret > 0) GP_LOG_DATA (buf, ret, "get_MS_OSD"); if (ret < 10) goto errout; if (!((buf[2] == 'M') && (buf[4]=='S') && (buf[6]=='F') && (buf[8]=='T'))) goto errout; cmd = buf[16]; ret = usb_control_msg (devh, USB_ENDPOINT_IN|USB_RECIP_DEVICE|LIBUSB_REQUEST_TYPE_VENDOR, cmd, 0, 4, buf, sizeof(buf), 1000); if (ret == -1) { GP_LOG_E ("control message says %d\n", ret); goto errout; } if (buf[0] != 0x28) { GP_LOG_E ("ret is %d, buf[0] is %x\n", ret, buf[0]); goto errout; } if (ret > 0) GP_LOG_DATA (buf, ret, "get_MS_ExtDesc"); if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) { GP_LOG_E ("buf at 0x12 is %02x%02x%02x\n", buf[0x12], buf[0x13], buf[0x14]); goto errout; } ret = usb_control_msg (devh, USB_ENDPOINT_IN|USB_RECIP_DEVICE|LIBUSB_REQUEST_TYPE_VENDOR, cmd, 0, 5, buf, sizeof(buf), 1000); if (ret == -1) goto errout; if (buf[0] != 0x28) { GP_LOG_E ("ret is %d, buf[0] is %x\n", ret, buf[0]); goto errout; } if (ret > 0) GP_LOG_DATA (buf, ret, "get_MS_ExtProp"); if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) { GP_LOG_E ("buf at 0x12 is %02x%02x%02x\n", buf[0x12], buf[0x13], buf[0x14]); goto errout; } found: usb_close (devh); /* Now chose a nice interface for us to use ... Just take the first. */ if (desc.bNumConfigurations > 1) GP_LOG_E ("The device has %d configurations!\n", desc.bNumConfigurations); for (i = 0; i < desc.bNumConfigurations; i++) { struct usb_config_descriptor *config = &dev->config[i]; if (config->bNumInterfaces > 1) GP_LOG_E ("The configuration has %d interfaces!\n", config->bNumInterfaces); for (i1 = 0; i1 < config->bNumInterfaces; i1++) { struct usb_interface *interface = &config->interface[i1]; if (interface->num_altsetting > 1) GP_LOG_E ("The interface has %d altsettings!\n", interface->num_altsetting); for (i2 = 0; i2 < interface->num_altsetting; i2++) { *configno = i; *interfaceno = i1; *altsettingno = i2; return 1; } } } return 1; errout: usb_close (devh); return 0; #endif }
/* * Get the USB config descriptors, cache and parse'em * * hub-only!! ... and only in reset path, or usb_new_device() * (used by real hubs and virtual root hubs) * * NOTE: if this is a WUSB device and is not authorized, we skip the * whole thing. A non-authorized USB device has no * configurations. */ int usb_get_configuration(struct usb_device *dev) { struct device *ddev = &dev->dev; int ncfg = dev->descriptor.bNumConfigurations; int result = 0; unsigned int cfgno, length; unsigned char *buffer; unsigned char *bigbuffer; struct usb_config_descriptor *desc; cfgno = 0; if (dev->authorized == 0) /* Not really an error */ goto out_not_authorized; result = -ENOMEM; if (ncfg > USB_MAXCONFIG) { dev_warn(ddev, "too many configurations: %d, " "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG); dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG; } if (ncfg < 1) { dev_err(ddev, "no configurations\n"); return -EINVAL; } length = ncfg * sizeof(struct usb_host_config); dev->config = kzalloc(length, GFP_KERNEL); if (!dev->config) goto err2; length = ncfg * sizeof(char *); dev->rawdescriptors = kzalloc(length, GFP_KERNEL); if (!dev->rawdescriptors) goto err2; buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); if (!buffer) goto err2; desc = (struct usb_config_descriptor *)buffer; result = 0; for (; cfgno < ncfg; cfgno++) { /* We grab just the first descriptor so we know how long * the whole configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, USB_DT_CONFIG_SIZE); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s: %d\n", cfgno, "start", result); dev_err(ddev, "chopping to %d config(s)\n", cfgno); dev->descriptor.bNumConfigurations = cfgno; break; } else if (result < 4) { dev_err(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, USB_DT_CONFIG_SIZE, result); result = -EINVAL; goto err; } length = max((int) le16_to_cpu(desc->wTotalLength), USB_DT_CONFIG_SIZE); /* Now that we know the length, get the whole thing */ bigbuffer = kmalloc(length, GFP_KERNEL); if (!bigbuffer) { result = -ENOMEM; goto err; } result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s\n", cfgno, "all"); kfree(bigbuffer); goto err; } if (result < length) { dev_warn(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, length, result); length = result; } #if defined(__VMKLNX__) dev->rawdescriptors[cfgno] = (char *)bigbuffer; #else dev->rawdescriptors[cfgno] = bigbuffer; #endif result = usb_parse_configuration(&dev->dev, cfgno, &dev->config[cfgno], bigbuffer, length); if (result < 0) { ++cfgno; goto err; } } result = 0; err: kfree(buffer); out_not_authorized: dev->descriptor.bNumConfigurations = cfgno; err2: if (result == -ENOMEM) dev_err(ddev, "out of memory\n"); return result; }
static int probe_device_descriptor(struct usb_device *dev, FILE *dumpfile) { usb_dev_handle *devh; unsigned char buf[1024], cmd; int i; int ret; if (dev->descriptor.bDeviceClass == USB_CLASS_HUB) { return 0; } devh = usb_open(dev); if (devh == NULL) { return 0; } if (dev->config) { for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { uint8_t j; for (j = 0; j < dev->config[i].bNumInterfaces; j++) { int k; for (k = 0; k < dev->config[i].interface[j].num_altsetting; k++) { struct usb_interface_descriptor *intf = &dev->config[i].interface[j].altsetting[k]; buf[0] = '\0'; ret = usb_get_string_simple(devh, dev->config[i].interface[j].altsetting[k].iInterface, (char *) buf, 1024); if (ret < 3) continue; if (strcmp((char *) buf, "MTP") == 0) { if (dumpfile != NULL) { fprintf(dumpfile, "Configuration %d, interface %d, altsetting %d:\n", i, j, k); fprintf(dumpfile, " Interface description contains the string \"MTP\"\n"); fprintf(dumpfile, " Device recognized as MTP, no further probing.\n"); } usb_close(devh); return 1; } #ifdef LIBUSB_HAS_GET_DRIVER_NP { char devname[0x10]; devname[0] = '\0'; ret = usb_get_driver_np(devh, dev->config[i].interface[j].altsetting[k].iInterface, devname, sizeof(devname)); if (devname[0] != '\0' && strcmp(devname, "usb-storage")) { printf("avoid probing device using kernel interface \"%s\"\n", devname); return 0; } } #endif } } } } else { if (dev->descriptor.bNumConfigurations) printf("dev->config is NULL in probe_device_descriptor yet dev->descriptor.bNumConfigurations > 0\n"); } ret = usb_get_descriptor(devh, 0x03, 0xee, buf, sizeof(buf)); if (dumpfile != NULL && ret > 0) { fprintf(dumpfile, "Microsoft device descriptor 0xee:\n"); data_dump_ascii(dumpfile, buf, ret, 16); } if (ret < 10) { usb_close(devh); return 0; } if (!((buf[2] == 'M') && (buf[4] == 'S') && (buf[6] == 'F') && (buf[8] == 'T'))) { usb_close(devh); return 0; } cmd = buf[16]; ret = usb_control_msg (devh, USB_ENDPOINT_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, cmd, 0, 4, (char *) buf, sizeof(buf), USB_TIMEOUT_DEFAULT); if (dumpfile != NULL && ret > 0) { fprintf(dumpfile, "Microsoft device response to control message 1, CMD 0x%02x:\n", cmd); data_dump_ascii(dumpfile, buf, ret, 16); } if (ret <= 0x15) { usb_close(devh); return 0; } if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) { usb_close(devh); return 0; } ret = usb_control_msg (devh, USB_ENDPOINT_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, cmd, 0, 5, (char *) buf, sizeof(buf), USB_TIMEOUT_DEFAULT); if (dumpfile != NULL && ret > 0) { fprintf(dumpfile, "Microsoft device response to control message 2, CMD 0x%02x:\n", cmd); data_dump_ascii(dumpfile, buf, ret, 16); } if (ret == -1) { fprintf(stderr, "Potential MTP Device with VendorID:%04x and " "ProductID:%04x encountered an error responding to " "control message 2.\n" "Problems may arrise but continuing\n", dev->descriptor.idVendor, dev->descriptor.idProduct); } else if (ret <= 0x15) { fprintf(stderr, "Potential MTP Device with VendorID:%04x and " "ProductID:%04x responded to control message 2 with a " "response that was too short. Problems may arrise but " "continuing\n", dev->descriptor.idVendor, dev->descriptor.idProduct); } else if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) { fprintf(stderr, "Potential MTP Device with VendorID:%04x and " "ProductID:%04x encountered an error responding to " "control message 2\n" "Problems may arrise but continuing\n", dev->descriptor.idVendor, dev->descriptor.idProduct); } usb_close(devh); return 1; }
/* Get BOS descriptor set */ int usb_get_bos_descriptor(struct usb_device *dev) { struct device *ddev = &dev->dev; struct usb_bos_descriptor *bos; struct usb_dev_cap_header *cap; unsigned char *buffer; int length, total_len, num, i; int ret; bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); if (!bos) return -ENOMEM; /* Get BOS descriptor */ ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE); if (ret < USB_DT_BOS_SIZE) { dev_err(ddev, "unable to get BOS descriptor\n"); if (ret >= 0) ret = -ENOMSG; kfree(bos); return ret; } length = bos->bLength; total_len = le16_to_cpu(bos->wTotalLength); num = bos->bNumDeviceCaps; kfree(bos); if (total_len < length) return -EINVAL; dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL); if (!dev->bos) return -ENOMEM; /* Now let's get the whole BOS descriptor set */ buffer = kzalloc(total_len, GFP_KERNEL); if (!buffer) { ret = -ENOMEM; goto err; } dev->bos->desc = (struct usb_bos_descriptor *)buffer; ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len); if (ret < total_len) { dev_err(ddev, "unable to get BOS descriptor set\n"); if (ret >= 0) ret = -ENOMSG; goto err; } total_len -= length; for (i = 0; i < num; i++) { buffer += length; cap = (struct usb_dev_cap_header *)buffer; length = cap->bLength; if (total_len < length) break; total_len -= length; if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { dev_warn(ddev, "descriptor type invalid, skip\n"); continue; } switch (cap->bDevCapabilityType) { case USB_CAP_TYPE_WIRELESS_USB: /* Wireless USB cap descriptor is handled by wusb */ break; case USB_CAP_TYPE_EXT: dev->bos->ext_cap = (struct usb_ext_cap_descriptor *)buffer; break; case USB_SS_CAP_TYPE: dev->bos->ss_cap = (struct usb_ss_cap_descriptor *)buffer; break; case CONTAINER_ID_TYPE: dev->bos->ss_id = (struct usb_ss_container_id_descriptor *)buffer; break; default: break; } } return 0; err: usb_release_bos_descriptor(dev); return ret; }
/* XXX: exclude high speed devices or implement EHCI */ USBDevice *usb_host_device_open(const char *devname) { USBHostDevice *dev; struct usb_dev_handle *udev = NULL; struct usb_device *device = NULL; struct usb_config_descriptor config_desc; int config_descr_len, nb_interfaces; int bus_num, addr, interface, ret; char product_name[32] ; if ((ret = usb_host_find_device(&bus_num, &addr, devname, &device)) < 0) return NULL; if (!device) return NULL; udev = usb_open(device); if (!udev) { #ifdef DEBUG printf("couldn't open usb device at %d.%d\n", bus_num, addr); #endif return NULL; } /* read the 1st config descriptor */ config_descr_len = usb_get_descriptor(udev, 2, 0, &config_desc, sizeof(config_desc)); if (config_descr_len <= 0) { printf("read config_desc: %s", usb_strerror()); goto fail; } if (config_descr_len > sizeof(config_desc)) { printf("config_desc size mismatch\n"); goto fail; } nb_interfaces = config_desc.bNumInterfaces; usb_set_configuration(udev, config_desc.bConfigurationValue); for (interface = 0; interface < nb_interfaces; interface++) { /* might as well */ #ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP usb_detach_kernel_driver_np(udev, interface); #endif ret = usb_claim_interface(udev, interface); if (ret < 0) { printf("usb_claim_interface: %s", usb_strerror()); fail: if (udev) usb_close(udev); return NULL; } } #ifdef DEBUG printf("host USB device %d.%d grabbed\n", bus_num, addr); #endif dev = qemu_mallocz(sizeof(USBHostDevice)); if (!dev) goto fail; /* not accurate - might be better off reporting only low/full */ switch (device->descriptor.bcdUSB) { case 0x0110: dev->dev.speed = USB_SPEED_FULL; break; case 0x0200: dev->dev.speed = USB_SPEED_HIGH; break; case 0x0100: dev->dev.speed = USB_SPEED_LOW; break; default: dev->dev.speed = USB_SPEED_FULL; } dev->udev = udev; dev->num_interfaces = nb_interfaces; dev->dev.handle_packet = usb_generic_handle_packet; dev->dev.handle_reset = usb_host_handle_reset; dev->dev.handle_control = usb_host_handle_control; dev->dev.handle_data = usb_host_handle_data; dev->dev.handle_destroy = usb_host_handle_destroy; /* get product string if available */ usb_get_string_simple(udev, device->descriptor.iProduct, product_name, sizeof(product_name)); if (product_name[0] == '\0') snprintf(dev->dev.devname, sizeof(dev->dev.devname), "host:%s", devname); else pstrcpy(dev->dev.devname, sizeof(dev->dev.devname), product_name); return (USBDevice *)dev; }
int download(AbstractFile* file, unsigned int transfer_size, int final_reset) { struct dfu_if _rt_dif, _dif, *dif = &_dif; int num_devs; int num_ifs; enum mode mode = MODE_NONE; struct dfu_status status; struct usb_dfu_func_descriptor func_dfu; char *alt_name = NULL; /* query alt name if non-NULL */ int ret; printf("dfu-util - (C) 2007 by OpenMoko Inc. Hacked by the iPhone Dev Team\n" "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n"); memset(dif, 0, sizeof(*dif)); dif->flags = DFU_IFF_VENDOR | DFU_IFF_PRODUCT; dif->vendor = 0x05ac; dif->product = 0x1222; dif->product_mask = 0xfff0; usb_init(); //usb_set_debug(255); usb_find_busses(); usb_find_devices(); mode = MODE_DOWNLOAD; if (mode == MODE_NONE) { fprintf(stderr, "You need to specify one of -D or -U\n"); help(); exit(2); } if (!file) { fprintf(stderr, "You need to specify a filename to -D -r -U\n"); help(); exit(2); } dfu_init(5000); num_devs = count_dfu_devices(dif); if (num_devs == 0) { fprintf(stderr, "No DFU capable USB device found\n"); exit(1); } else if (num_devs > 1) { /* We cannot safely support more than one DFU capable device * with same vendor/product ID, since during DFU we need to do * a USB bus reset, after which the target device will get a * new address */ fprintf(stderr, "More than one DFU capable USB device found, " "you might try `--list' and then disconnect all but one " "device\n"); exit(3); } if (!get_first_dfu_device(dif)) exit(3); /* We have exactly one device. It's usb_device is now in dif->dev */ printf("Opening USB Device 0x%04x:0x%04x...\n", dif->vendor, dif->product); dif->dev_handle = usb_open(dif->dev); if (!dif->dev_handle) { fprintf(stderr, "Cannot open device: %s\n", usb_strerror()); exit(1); } /* try to find first DFU interface of device */ memcpy(&_rt_dif, dif, sizeof(_rt_dif)); if (!get_first_dfu_if(&_rt_dif)) exit(1); if (alt_name) { int n; n = find_dfu_if(dif->dev, &alt_by_name, alt_name); if (!n) { fprintf(stderr, "No such Alternate Setting: \"%s\"\n", alt_name); exit(1); } if (n < 0) { fprintf(stderr, "Error %d in name lookup\n", n); exit(1); } dif->altsetting = n-1; } print_dfu_if(dif, NULL); num_ifs = count_dfu_interfaces(dif->dev); if (num_ifs < 0) { fprintf(stderr, "No DFU Interface after RESET?!?\n"); exit(1); } else if (num_ifs == 1) { if (!get_first_dfu_if(dif)) { fprintf(stderr, "Can't find the single available DFU IF\n"); exit(1); } } else if (num_ifs > 1 && !dif->flags & (DFU_IFF_IFACE|DFU_IFF_ALT)) { fprintf(stderr, "We have %u DFU Interfaces/Altsettings, " "you have to specify one via --intf / --alt options\n", num_ifs); exit(1); } dif->configuration = 1; printf("Setting Configuration %u...\n", dif->configuration); if (usb_set_configuration(dif->dev_handle, dif->configuration) < 0) { fprintf(stderr, "Cannot set configuration: %s\n", usb_strerror()); } printf("Claiming USB DFU Interface...\n"); if (usb_claim_interface(dif->dev_handle, dif->interface) < 0) { fprintf(stderr, "Cannot claim interface: %s\n", usb_strerror()); } printf("Setting Alternate Setting ...\n"); if (usb_set_altinterface(dif->dev_handle, dif->altsetting) < 0) { fprintf(stderr, "Cannot set alternate interface: %s\n", usb_strerror()); } status_again: printf("Determining device status: "); if (dfu_get_status(dif->dev_handle, dif->interface, &status ) < 0) { fprintf(stderr, "error get_status: %s\n", usb_strerror()); exit(1); } printf("state = %s, status = %d\n", dfu_state_to_string(status.bState), status.bStatus); switch (status.bState) { case DFU_STATE_appIDLE: case DFU_STATE_appDETACH: fprintf(stderr, "Device still in Runtime Mode!\n"); exit(1); break; case DFU_STATE_dfuERROR: printf("dfuERROR, clearing status\n"); if (dfu_clear_status(dif->dev_handle, dif->interface) < 0) { fprintf(stderr, "error clear_status: %s\n", usb_strerror()); exit(1); } goto status_again; break; case DFU_STATE_dfuDNLOAD_IDLE: case DFU_STATE_dfuUPLOAD_IDLE: printf("aborting previous incomplete transfer\n"); if (dfu_abort(dif->dev_handle, dif->interface) < 0) { fprintf(stderr, "can't send DFU_ABORT: %s\n", usb_strerror()); exit(1); } goto status_again; break; case DFU_STATE_dfuIDLE: printf("dfuIDLE, continuing\n"); break; } if (!transfer_size) { /* Obtain DFU functional descriptor */ ret = usb_get_descriptor(dif->dev_handle, 0x21, dif->interface, &func_dfu, sizeof(func_dfu)); if (ret < 0) { fprintf(stderr, "Error obtaining DFU functional " "descriptor: %s\n", usb_strerror()); transfer_size = 0x800; } else { func_dfu.wTransferSize = LE2CPU16(func_dfu.wTransferSize); transfer_size = func_dfu.wTransferSize; } } printf("Transfer Size = 0x%04x\n", transfer_size); if (DFU_STATUS_OK != status.bStatus ) { printf("WARNING: DFU Status: '%s'\n", dfu_status_to_string(status.bStatus)); /* Clear our status & try again. */ dfu_clear_status(dif->dev_handle, dif->interface); dfu_get_status(dif->dev_handle, dif->interface, &status); if (DFU_STATUS_OK != status.bStatus) { fprintf(stderr, "Error: %d\n", status.bStatus); exit(1); } } switch (mode) { case MODE_DOWNLOAD: if (sam7dfu_do_dnload(dif->dev_handle, dif->interface, transfer_size, file) < 0) { usb_release_interface(dif->dev_handle, dif->interface); return 1; } break; default: fprintf(stderr, "Unsupported mode: %u\n", mode); exit(1); } if (final_reset) { if (dfu_detach(dif->dev_handle, dif->interface, 1000) < 0) { fprintf(stderr, "can't detach: %s\n", usb_strerror()); } printf("Resetting USB to switch back to runtime mode\n"); ret = usb_reset(dif->dev_handle); if (ret < 0 && ret != -ENODEV) { fprintf(stderr, "error resetting after download: %s\n", usb_strerror()); } } if(usb_release_interface(dif->dev_handle, dif->interface) < 0) { fprintf(stderr, "error: releasing %s\n", usb_strerror()); } if(usb_close(dif->dev_handle) < 0) { fprintf(stderr, "error: closing %s\n", usb_strerror()); } return 0; }
//! This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! If the received request is not supported or a non-standard USB request, the function //! will call the custom decoding function in usb_specific_request module. //! //! @note List of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bRequest; Usb_reset_endpoint_fifo_access(EP_CONTROL); bmRequestType = Usb_read_endpoint_data(EP_CONTROL, 8); bRequest = Usb_read_endpoint_data(EP_CONTROL, 8); switch (bRequest) { case GET_DESCRIPTOR: if (bmRequestType == 0x80) usb_get_descriptor(); else goto unsupported_request; break; case GET_CONFIGURATION: if (bmRequestType == 0x80) usb_get_configuration(); else goto unsupported_request; break; case SET_ADDRESS: if (bmRequestType == 0x00) usb_set_address(); else goto unsupported_request; break; case SET_CONFIGURATION: if (bmRequestType == 0x00) usb_set_configuration(); else goto unsupported_request; break; case CLEAR_FEATURE: if (bmRequestType <= 0x02) usb_clear_feature(); else goto unsupported_request; break; case SET_FEATURE: if (bmRequestType <= 0x02) usb_set_feature(); else goto unsupported_request; break; case GET_STATUS: if (0x7F < bmRequestType && bmRequestType <= 0x82) usb_get_status(); else goto unsupported_request; break; case GET_INTERFACE: if (bmRequestType == 0x81) { if(!usb_get_interface()) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); } } else goto unsupported_request; break; case SET_INTERFACE: if (bmRequestType == 0x01) usb_set_interface(); else goto unsupported_request; break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< unsupported request => call to user read request unsupported_request: if (!usb_user_read_request(bmRequestType, bRequest)) { Usb_enable_stall_handshake(EP_CONTROL); Usb_ack_setup_received_free(); } break; } }
/* * WARNING - If a driver calls usb_reset_device, you should simulate a * disconnect() and probe() for other interfaces you doesn't claim. This * is left up to the driver writer right now. This insures other drivers * have a chance to re-setup their interface. * * Take a look at proc_resetdevice in devio.c for some sample code to * do this. */ int usb_reset_device(struct usb_device *dev) { struct usb_device *parent = dev->parent; struct usb_device_descriptor descriptor; int i, ret, port = -1; DBG_HOST_HUB("### >>> Enter hub.c file --> usb_reset_device function \n"); if (!parent) { err("attempting to reset root hub!"); return -EINVAL; } for (i = 0; i < parent->maxchild; i++) if (parent->children[i] == dev) { port = i; break; } if (port < 0) return -ENOENT; down(&usb_address0_sem); /* Send a reset to the device */ if (usb_hub_port_reset(parent, port, dev, HUB_SHORT_RESET_TIME)) { usb_hub_port_disable(parent, port); up(&usb_address0_sem); return(-ENODEV); } /* Reprogram the Address */ ret = usb_set_address(dev); if (ret < 0) { err("USB device not accepting new address (error=%d)", ret); usb_hub_port_disable(parent, port); up(&usb_address0_sem); return ret; } /* Let the SET_ADDRESS settle */ wait_ms(10); up(&usb_address0_sem); /* * Now we fetch the configuration descriptors for the device and * see if anything has changed. If it has, we dump the current * parsed descriptors and reparse from scratch. Then we leave * the device alone for the caller to finish setting up. * * If nothing changed, we reprogram the configuration and then * the alternate settings. */ ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor, sizeof(descriptor)); if (ret < 0) return ret; le16_to_cpus(&descriptor.bcdUSB); le16_to_cpus(&descriptor.idVendor); le16_to_cpus(&descriptor.idProduct); le16_to_cpus(&descriptor.bcdDevice); if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) { usb_destroy_configuration(dev); ret = usb_get_device_descriptor(dev); if (ret < sizeof(dev->descriptor)) { if (ret < 0) err("unable to get device descriptor (error=%d)", ret); else err("USB device descriptor short read (expected %Zi, got %i)", sizeof(dev->descriptor), ret); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return -EIO; } ret = usb_get_configuration(dev); if (ret < 0) { err("unable to get configuration (error=%d)", ret); usb_destroy_configuration(dev); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dev->actconfig = dev->config; usb_set_maxpacket(dev); return 1; } ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue); if (ret < 0) { err("failed to set active configuration (error=%d)", ret); return ret; } for (i = 0; i < dev->actconfig->bNumInterfaces; i++) { struct usb_interface *intf = &dev->actconfig->interface[i]; struct usb_interface_descriptor *as = &intf->altsetting[intf->act_altsetting]; ret = usb_set_interface(dev, as->bInterfaceNumber, as->bAlternateSetting); if (ret < 0) { err("failed to set active alternate setting for interface %d (error=%d)", i, ret); return ret; } } return 0; }
int main(int argc, char **argv) { struct usb_vendprod vendprod; struct dfu_if _rt_dif, _dif, *dif = &_dif; int num_devs; int num_ifs; unsigned int transfer_size = 0; enum mode mode = MODE_NONE; struct dfu_status status; int quirks_auto_detect = 1; dfu_quirks manual_quirks; dfu_handle handle; char *filename = NULL; char *alt_name = NULL; /* query alt name if non-NULL */ char *end; int final_reset = 0; int page_size = getpagesize(); int ret; printf("dfu-util - (C) 2007-2008 by OpenMoko Inc.\n" "This program is Free Software and has ABSOLUTELY NO WARRANTY\n\n"); dfu_quirks_clear(&manual_quirks); memset(dif, 0, sizeof(*dif)); usb_init(); //usb_set_debug(255); usb_find_busses(); usb_find_devices(); while (1) { int c, option_index = 0; c = getopt_long(argc, argv, "hVvld:p:c:i:a:t:U:D:C:S:RQNq:", opts, &option_index); if (c == -1) break; switch (c) { case 'h': help(); exit(0); break; case 'V': print_version(); exit(0); break; case 'v': verbose = 1; break; case 'l': list_dfu_interfaces(); exit(0); break; case 'd': /* Parse device */ if (parse_vendprod(&vendprod, optarg) < 0) { fprintf(stderr, "unable to parse `%s'\n", optarg); exit(2); } dif->vendor = vendprod.vendor; dif->product = vendprod.product; dif->flags |= (DFU_IFF_VENDOR | DFU_IFF_PRODUCT); break; case 'p': /* Parse device path */ dif->path = optarg; dif->flags |= DFU_IFF_PATH; ret = resolve_device_path(dif); if (ret < 0) { fprintf(stderr, "unable to parse `%s'\n", optarg); exit(2); } if (!ret) { fprintf(stderr, "cannot find `%s'\n", optarg); exit(1); } break; case 'c': /* Configuration */ dif->configuration = atoi(optarg); dif->flags |= DFU_IFF_CONFIG; break; case 'i': /* Interface */ dif->interface = atoi(optarg); dif->flags |= DFU_IFF_IFACE; break; case 'a': /* Interface Alternate Setting */ dif->altsetting = strtoul(optarg, &end, 0); if (*end) alt_name = optarg; dif->flags |= DFU_IFF_ALT; break; case 't': transfer_size = atoi(optarg); break; case 'U': mode = MODE_UPLOAD; filename = optarg; break; case 'D': mode = MODE_DOWNLOAD; filename = optarg; break; case 'C': mode = MODE_COMPARE; /* TODO: verify firmware */ filename = optarg; break; case 'S': filename = optarg; add_file_suffix(filename); exit(0); break; case 'R': final_reset = 1; break; case 'Q': dfu_quirks_print(); exit(0); break; case 'N': quirks_auto_detect = 0; break; case 'q': quirks_auto_detect = 0; dfu_quirk_set(&manual_quirks, atoi(optarg)); break; default: help(); exit(2); } } if (mode == MODE_NONE) { fprintf(stderr, "You need to specify one of -D or -U\n"); help(); exit(2); } if (!filename) { fprintf(stderr, "You need to specify a filename to -D -r -U\n"); help(); exit(2); } dfu_init(&handle, 5000); num_devs = count_dfu_devices(dif); if (num_devs == 0) { fprintf(stderr, "No DFU capable USB device found\n"); exit(1); } else if (num_devs > 1) { /* We cannot safely support more than one DFU capable device * with same vendor/product ID, since during DFU we need to do * a USB bus reset, after which the target device will get a * new address */ fprintf(stderr, "More than one DFU capable USB device found, " "you might try `--list' and then disconnect all but one " "device\n"); exit(3); } if (!get_first_dfu_device(dif)) exit(3); /* We have exactly one device. It's usb_device is now in dif->dev */ printf("Opening USB Device 0x%04x:0x%04x...\n", dif->vendor, dif->product); dif->dev_handle = usb_open(dif->dev); if (!dif->dev_handle) { fprintf(stderr, "Cannot open device: %s\n", usb_strerror()); exit(1); } /* try to find first DFU interface of device */ memcpy(&_rt_dif, dif, sizeof(_rt_dif)); if (!get_first_dfu_if(&_rt_dif)) exit(1); handle.device = _rt_dif.dev_handle; handle.interface = _rt_dif.interface; /* automatic quirk detection */ if(quirks_auto_detect) { /* TODO: let the detection be influenced by bcdDFU, bcdDevice */ handle.quirk_flags = dfu_quirks_detect(0, dif->vendor, dif->product, 0); } /* merge with manual quirks */ dfu_quirks_insert(&handle.quirk_flags, &manual_quirks); if(!dfu_quirks_is_empty(&handle.quirk_flags)) { printf("Selected quirks: "); dfu_quirks_print_set(&handle.quirk_flags); printf("\n"); } if (!_rt_dif.flags & DFU_IFF_DFU) { /* In the 'first round' during runtime mode, there can only be one * DFU Interface descriptor according to the DFU Spec. */ /* FIXME: check if the selected device really has only one */ printf("Claiming USB DFU Runtime Interface %d...\n", _rt_dif.interface); if (usb_claim_interface(_rt_dif.dev_handle, _rt_dif.interface) < 0) { fprintf(stderr, "Cannot claim interface: %s\n", usb_strerror()); exit(1); } /* DFU 1.0, Table 4.1: in runtime-mode, alternate interface setting must be zero. therefore we can assume, '0' is correct. the reason we use usb_set_altinterface() here: switch devices to the interface set using usb_claim_interface() above - for some reason this isn't done there. is the only libusb API which issues the SET_INTERFACE USB standard request is usb_set_altinterface() */ if (usb_set_altinterface(_rt_dif.dev_handle, 0) < 0) { fprintf(stderr, "Cannot set alternate interface %d: %s\n", 0, usb_strerror()); exit(1); } printf("Determining device state: "); int state = -1; if ( (state = dfu_get_state(&handle)) < 0) { exit(1); } printf("state = %s\n", dfu_state_to_string(state)); dfu_sm_set_state_unchecked(&handle, state); printf("Determining device status: "); if (dfu_get_status(&handle, &status ) < 0) { exit(1); } printf("state = %s, status = %d = \"%s\"\n", dfu_state_to_string(status.bState), status.bStatus, dfu_status_to_string(status.bStatus) ); switch (status.bState) { case DFU_STATE_appIDLE: case DFU_STATE_appDETACH: printf("Device really in Runtime Mode, send DFU " "detach request...\n"); if(status.bState == DFU_STATE_appDETACH) { printf("Device is already in state %s, skipping DFU_DETACH request\n", dfu_state_to_string(status.bState)); } else { if (dfu_detach(&handle, 1000) < 0) { exit(1); break; } } /* handle bitWillDetach (DFU 1.1) */ if(handle.dfu_ver == DFU_VERSION_1_1 && handle.func_dfu.bmAttributes & USB_DFU_WILL_DETACH) { /* TODO: test this with a real DFU 1.1 device */ printf("Waiting for USB device's own detach (bitWillDetach=1)...\n"); dfu_sm_set_state_checked(&handle, DFU_STATE_dfuIDLE); } else { printf("Resetting USB...\n"); ret = dfu_usb_reset(&handle); if (ret < 0 && ret != -ENODEV) { /* do nothing; error msg is output in dfu_usb_reset. */ } } sleep(2); break; case DFU_STATE_dfuERROR: printf("dfuERROR, clearing status\n"); if (dfu_clear_status(&handle) < 0) { exit(1); break; } break; default: fprintf(stderr, "WARNING: Runtime device already " "in DFU state ?!?\n"); goto dfustate; break; } /* now we need to re-scan the bus and locate our device */ if (usb_find_devices() < 2) printf("not at least 2 device changes found ?!?\n"); if (dif->flags & DFU_IFF_PATH) { ret = resolve_device_path(dif); if (ret < 0) { fprintf(stderr, "internal error: cannot re-parse `%s'\n", dif->path); abort(); } if (!ret) { fprintf(stderr, "Can't resolve path after RESET?\n"); exit(1); } } num_devs = count_dfu_devices(dif); if (num_devs == 0) { fprintf(stderr, "Lost device after RESET?\n"); exit(1); } else if (num_devs > 1) { fprintf(stderr, "More than one DFU capable USB " "device found, you might try `--list' and " "then disconnect all but one device\n"); exit(1); } if (!get_first_dfu_device(dif)) exit(3); printf("Opening USB Device...\n"); dif->dev_handle = usb_open(dif->dev); if (!dif->dev_handle) { fprintf(stderr, "Cannot open device: %s\n", usb_strerror()); exit(1); } } else { /* we're already in DFU mode, so we can skip the detach/reset * procedure */ } dfustate: if (alt_name) { int n; n = find_dfu_if(dif->dev, &alt_by_name, alt_name); if (!n) { fprintf(stderr, "No such Alternate Setting: \"%s\"\n", alt_name); exit(1); } if (n < 0) { fprintf(stderr, "Error %d in name lookup\n", n); exit(1); } dif->altsetting = n-1; } print_dfu_if(dif, NULL); num_ifs = count_dfu_interfaces(dif->dev); if (num_ifs < 0) { fprintf(stderr, "No DFU Interface after RESET?!?\n"); exit(1); } else if (num_ifs == 1) { if (!get_first_dfu_if(dif)) { fprintf(stderr, "Can't find the single available " "DFU IF\n"); exit(1); } } else if (num_ifs > 1 && (!dif->flags) & (DFU_IFF_IFACE|DFU_IFF_ALT)) { fprintf(stderr, "We have %u DFU Interfaces/Altsettings, " "you have to specify one via --intf / --alt options\n", num_ifs); exit(1); } #if 0 printf("Setting Configuration %u...\n", dif->configuration); if (usb_set_configuration(dif->dev_handle, dif->configuration) < 0) { fprintf(stderr, "Cannot set configuration: %s\n", usb_strerror()); exit(1); } #endif printf("Claiming USB DFU Interface...\n"); if (usb_claim_interface(dif->dev_handle, dif->interface) < 0) { fprintf(stderr, "Cannot claim interface: %s\n", usb_strerror()); exit(1); } printf("Setting Alternate Setting ...\n"); if (usb_set_altinterface(dif->dev_handle, dif->altsetting) < 0) { fprintf(stderr, "Cannot set alternate interface: %s\n", usb_strerror()); exit(1); } /* update the handle to point to the dfu-mode descriptor */ handle.device = dif->dev_handle; handle.interface = dif->interface; status_again: printf("Determining device status: "); if (dfu_get_status(&handle, &status ) < 0) { fprintf(stderr, "error get_status: %s\n", usb_strerror()); exit(1); } printf("state = %s, status = %d\n", dfu_state_to_string(status.bState), status.bStatus); /* force the statemachine into current status */ dfu_sm_set_state_unchecked(&handle, status.bState); switch (status.bState) { case DFU_STATE_appIDLE: case DFU_STATE_appDETACH: fprintf(stderr, "Device still in Runtime Mode!\n"); exit(1); break; case DFU_STATE_dfuERROR: printf("dfuERROR, clearing status\n"); if (dfu_clear_status(&handle) < 0) { fprintf(stderr, "error clear_status: %s\n", usb_strerror()); exit(1); } goto status_again; break; case DFU_STATE_dfuDNLOAD_IDLE: case DFU_STATE_dfuUPLOAD_IDLE: printf("aborting previous incomplete transfer\n"); if (dfu_abort(&handle) < 0) { fprintf(stderr, "can't send DFU_ABORT: %s\n", usb_strerror()); exit(1); } goto status_again; break; case DFU_STATE_dfuIDLE: printf("dfuIDLE, continuing\n"); break; } /* Obtain DFU functional descriptor */ ret = usb_get_descriptor(dif->dev_handle, 0x21, dif->interface, &(handle.func_dfu), sizeof(handle.func_dfu)); if (ret < 0) { fprintf(stderr, "Error obtaining DFU functional " "descriptor: %s\n", usb_strerror()); if(dfu_quirk_is_set(&handle.quirk_flags, QUIRK_IGNORE_INVALID_FUNCTIONAL_DESCRIPTOR)) { handle.func_dfu.bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_CAN_UPLOAD | USB_DFU_MANIFEST_TOL; handle.func_dfu.wTransferSize = cpu_to_le16(transfer_size); if(!transfer_size) transfer_size = page_size; handle.func_dfu.bcdDFUVersion = USB_DFU_VER_1_0; fprintf(stderr, " Still, try to continue with default flags/manual settings.\n"); } else { exit(1); } } else { transfer_size = le16_to_cpu(handle.func_dfu.wTransferSize); } /* why is this limited to page_size, a host-dependent value? (sgiessl) */ if (transfer_size > page_size) transfer_size = page_size; /* quirk overwriting DFU version */ if(dfu_quirk_is_set(&handle.quirk_flags, QUIRK_FORCE_DFU_VERSION_1_0)) { handle.func_dfu.bcdDFUVersion = USB_DFU_VER_1_0; } else if(dfu_quirk_is_set(&handle.quirk_flags, QUIRK_FORCE_DFU_VERSION_1_1)) { handle.func_dfu.bcdDFUVersion = USB_DFU_VER_1_1; } /* read DFU version */ switch(handle.func_dfu.bcdDFUVersion) { case USB_DFU_VER_1_1: handle.dfu_ver = DFU_VERSION_1_1; break; default: printf("WARNING: device specifies unknown DFU version 0x%.2x, defaulting to DFU 1.0\n", handle.func_dfu.bcdDFUVersion); /* fall through intended */ case USB_DFU_VER_1_0: handle.dfu_ver = DFU_VERSION_1_0; break; } printf("Transfer Size = 0x%04x\n", transfer_size); printf("Device functional descriptor: %s\n", dfu_func_descriptor_to_string(&handle.func_dfu)); if (DFU_STATUS_OK != status.bStatus ) { printf("WARNING: DFU Status: '%s'\n", dfu_status_to_string(status.bStatus)); /* Clear our status & try again. */ dfu_clear_status(&handle); dfu_get_status(&handle, &status); if (DFU_STATUS_OK != status.bStatus) { fprintf(stderr, "Error: %d\n", status.bStatus); exit(1); } } switch (mode) { case MODE_UPLOAD: if (sam7dfu_do_upload(&handle, transfer_size, filename) < 0) exit(1); break; case MODE_DOWNLOAD: if (sam7dfu_do_dnload(&handle, transfer_size, filename) < 0) exit(1); break; default: fprintf(stderr, "Unsupported mode: %u\n", mode); exit(1); } if (final_reset) { if(dfu_quirk_is_set(&handle.quirk_flags, QUIRK_OPENMOKO_DETACH_BEFORE_FINAL_RESET)) { /* DFU_DETACH is only allowed in appIDLE, so this is non-standard (as of DFU 1.0, and 1.1). */ printf("Initiating reset by sending DFU_DETACH (QUIRK_OPENMOKO_DETACH_BEFORE_FINAL_RESET)\n"); if (dfu_detach(&handle, 1000) < 0) { fprintf(stderr, "can't detach: %s\n", usb_strerror()); } } printf("Resetting USB to switch back to runtime mode\n"); ret = usb_reset(dif->dev_handle); if (ret < 0 && ret != -ENODEV) { fprintf(stderr, "error resetting after download: %s\n", usb_strerror()); } } exit(0); }
static int udl_parse_vendor_descriptor(struct drm_device *dev, struct usb_device *usbdev) { struct udl_device *udl = dev->dev_private; char *desc; char *buf; char *desc_end; u8 total_len = 0; buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); if (!buf) return false; desc = buf; total_len = usb_get_descriptor(usbdev, 0x5f, /* vendor specific */ 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); if (total_len > 5) { DRM_INFO("vendor descriptor length:%x data:%11ph\n", total_len, desc); if ((desc[0] != total_len) || /* descriptor length */ (desc[1] != 0x5f) || /* vendor descriptor type */ (desc[2] != 0x01) || /* version (2 bytes) */ (desc[3] != 0x00) || (desc[4] != total_len - 2)) /* length after type */ goto unrecognized; desc_end = desc + total_len; desc += 5; /* the fixed header we've already parsed */ while (desc < desc_end) { u8 length; u16 key; key = le16_to_cpu(*((u16 *) desc)); desc += sizeof(u16); length = *desc; desc++; switch (key) { case 0x0200: { /* max_area */ u32 max_area; max_area = le32_to_cpu(*((u32 *)desc)); DRM_DEBUG("DL chip limited to %d pixel modes\n", max_area); udl->sku_pixel_limit = max_area; break; } default: break; } desc += length; } } goto success; unrecognized: /* allow udlfb to load for now even if firmware unrecognized */ DRM_ERROR("Unrecognized vendor firmware descriptor\n"); success: kfree(buf); return true; }
// hub-only!! ... and only in reset path, or usb_new_device() // (used by real hubs and virtual root hubs) int usb_get_configuration(struct usb_device *dev) { int result; unsigned int cfgno, length; unsigned char *buffer; unsigned char *bigbuffer; struct usb_config_descriptor *desc; if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { warn("too many configurations"); return -EINVAL; } if (dev->descriptor.bNumConfigurations < 1) { warn("not enough configurations"); return -EINVAL; } dev->config = (struct usb_host_config *) kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_host_config), GFP_KERNEL); if (!dev->config) { err("out of memory"); return -ENOMEM; } memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_host_config)); dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * dev->descriptor.bNumConfigurations, GFP_KERNEL); if (!dev->rawdescriptors) { err("out of memory"); return -ENOMEM; } buffer = kmalloc(8, GFP_KERNEL); if (!buffer) { err("unable to allocate memory for configuration descriptors"); return -ENOMEM; } desc = (struct usb_config_descriptor *)buffer; for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++) { /* We grab the first 8 bytes so we know how long the whole */ /* configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8); if (result < 8) { if (result < 0) err("unable to get descriptor"); else { err("config descriptor too short (expected %i, got %i)", 8, result); result = -EINVAL; } goto err; } /* Get the full buffer */ length = le16_to_cpu(desc->wTotalLength); bigbuffer = kmalloc(length, GFP_KERNEL); if (!bigbuffer) { err("unable to allocate memory for configuration descriptors"); result = -ENOMEM; goto err; } /* Now that we know the length, get the whole thing */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { err("couldn't get all of config descriptors"); kfree(bigbuffer); goto err; } if (result < length) { err("config descriptor too short (expected %i, got %i)", length, result); result = -EINVAL; kfree(bigbuffer); goto err; } dev->rawdescriptors[cfgno] = bigbuffer; result = usb_parse_configuration(&dev->config[cfgno], bigbuffer); if (result > 0) dbg("descriptor data left"); else if (result < 0) { result = -EINVAL; goto err; } } kfree(buffer); return 0; err: kfree(buffer); dev->descriptor.bNumConfigurations = cfgno; return result; }
//! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! void usb_process_request(void) { U8 bmRequestType; U8 bmRequest; Usb_ack_control_out(); bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case SETUP_GET_DESCRIPTOR: if (USB_SETUP_GET_STAND_DEVICE == bmRequestType) { if( usb_get_descriptor() ) return; } break; case SETUP_GET_CONFIGURATION: if (USB_SETUP_GET_STAND_DEVICE == bmRequestType) { usb_get_configuration(); return; } break; case SETUP_SET_ADDRESS: if (USB_SETUP_SET_STAND_DEVICE == bmRequestType) { usb_set_address(); return; } break; case SETUP_SET_CONFIGURATION: if (USB_SETUP_SET_STAND_DEVICE == bmRequestType) { if( usb_set_configuration() ) return; } break; case SETUP_CLEAR_FEATURE: if (usb_clear_feature(bmRequestType)) return; break; case SETUP_SET_FEATURE: if (usb_set_feature(bmRequestType)) return; break; case SETUP_GET_STATUS: if (usb_get_status(bmRequestType)) return; break; case SETUP_GET_INTERFACE: if (USB_SETUP_GET_STAND_INTERFACE == bmRequestType) { if( usb_get_interface() ) return; } break; case SETUP_SET_INTERFACE: if (bmRequestType == USB_SETUP_SET_STAND_INTERFACE) { if( usb_set_interface() ) return; } break; default: break; } // un-supported like standard request => call to user read request if( !usb_user_read_request(bmRequestType, bmRequest) ) { // Request unknow in the specific request list from interface // keep that order (set StallRq/clear RxSetup) or a // OUT request following the SETUP may be acknowledged Usb_enable_stall_handshake(); Usb_ack_receive_setup(); endpoint_status[(EP_CONTROL & MSK_EP_DIR)] = 0x01; } }
// hub-only!! ... and only in reset path, or usb_new_device() // (used by real hubs and virtual root hubs) int usb_get_configuration(struct usb_device *dev) { struct device *ddev = &dev->dev; int ncfg = dev->descriptor.bNumConfigurations; int result = -ENOMEM; unsigned int cfgno, length; unsigned char *buffer; unsigned char *bigbuffer; struct usb_config_descriptor *desc; if (ncfg > USB_MAXCONFIG) { dev_warn(ddev, "too many configurations: %d, " "using maximum allowed: %d\n", ncfg, USB_MAXCONFIG); dev->descriptor.bNumConfigurations = ncfg = USB_MAXCONFIG; } if (ncfg < 1) { #if 0 dev_err(ddev, "no configurations\n"); return -EINVAL; #else dev_err(ddev, "no configurations, try to get configurations [cfyeh]\n"); ncfg = 1; #endif } length = ncfg * sizeof(struct usb_host_config); dev->config = kmalloc(length, GFP_KERNEL); if (!dev->config) goto err2; memset(dev->config, 0, length); length = ncfg * sizeof(char *); dev->rawdescriptors = kmalloc(length, GFP_KERNEL); if (!dev->rawdescriptors) goto err2; memset(dev->rawdescriptors, 0, length); #ifdef USB_512B_ALIGNMENT buffer = kmalloc(USB_512B_ALIGNMENT_SIZE, GFP_KERNEL); #else buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); #endif /* USB_512B_ALIGNMENT */ if (!buffer) goto err2; desc = (struct usb_config_descriptor *)buffer; for (cfgno = 0; cfgno < ncfg; cfgno++) { /* We grab just the first descriptor so we know how long * the whole configuration is */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, USB_DT_CONFIG_SIZE); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s\n", cfgno, "start"); goto err; } else if (result < 4) { dev_err(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, USB_DT_CONFIG_SIZE, result); result = -EINVAL; goto err; } length = max((int) le16_to_cpu(desc->wTotalLength), USB_DT_CONFIG_SIZE); /* Now that we know the length, get the whole thing */ #ifdef USB_512B_ALIGNMENT if(length > USB_512B_ALIGNMENT_SIZE) bigbuffer = kmalloc(length, GFP_KERNEL); else bigbuffer = kmalloc(USB_512B_ALIGNMENT_SIZE, GFP_KERNEL); #else bigbuffer = kmalloc(length, GFP_KERNEL); #endif /* USB_512B_ALIGNMENT */ if (!bigbuffer) { result = -ENOMEM; goto err; } result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s\n", cfgno, "all"); kfree(bigbuffer); goto err; } if (result < length) { dev_warn(ddev, "config index %d descriptor too short " "(expected %i, got %i)\n", cfgno, length, result); length = result; } dev->rawdescriptors[cfgno] = bigbuffer; result = usb_parse_configuration(&dev->dev, cfgno, &dev->config[cfgno], bigbuffer, length); if (result < 0) { ++cfgno; goto err; } } result = 0; err: kfree(buffer); dev->descriptor.bNumConfigurations = cfgno; err2: if (result == -ENOMEM) dev_err(ddev, "out of memory\n"); return result; }
static int udl_parse_vendor_descriptor(struct drm_device *dev, struct usb_device *usbdev) { struct udl_device *udl = dev->dev_private; char *desc; char *buf; char *desc_end; u8 total_len = 0; buf = kzalloc(MAX_VENDOR_DESCRIPTOR_SIZE, GFP_KERNEL); if (!buf) return false; desc = buf; total_len = usb_get_descriptor(usbdev, 0x5f, 0, desc, MAX_VENDOR_DESCRIPTOR_SIZE); if (total_len > 5) { DRM_INFO("vendor descriptor length:%x data:%02x %02x %02x %02x" \ "%02x %02x %02x %02x %02x %02x %02x\n", total_len, desc[0], desc[1], desc[2], desc[3], desc[4], desc[5], desc[6], desc[7], desc[8], desc[9], desc[10]); if ((desc[0] != total_len) || (desc[1] != 0x5f) || (desc[2] != 0x01) || (desc[3] != 0x00) || (desc[4] != total_len - 2)) goto unrecognized; desc_end = desc + total_len; desc += 5; while (desc < desc_end) { u8 length; u16 key; key = *((u16 *) desc); desc += sizeof(u16); length = *desc; desc++; switch (key) { case 0x0200: { u32 max_area; max_area = le32_to_cpu(*((u32 *)desc)); DRM_DEBUG("DL chip limited to %d pixel modes\n", max_area); udl->sku_pixel_limit = max_area; break; } default: break; } desc += length; } } goto success; unrecognized: DRM_ERROR("Unrecognized vendor firmware descriptor\n"); success: kfree(buf); return true; }
/* FIXME: prototype for adding security */ int wusb_dev_sec_add(struct wusbhc *wusbhc, struct usb_device *usb_dev, struct wusb_dev *wusb_dev) { int result, bytes, secd_size; struct device *dev = &usb_dev->dev; struct usb_security_descriptor *secd; const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL; const void *itr, *top; char buf[64]; secd = kmalloc(sizeof(*secd), GFP_KERNEL); if (secd == NULL) { result = -ENOMEM; goto out; } result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, 0, secd, sizeof(*secd)); if (result < sizeof(*secd)) { dev_err(dev, "Can't read security descriptor or " "not enough data: %d\n", result); goto out; } secd_size = le16_to_cpu(secd->wTotalLength); secd = krealloc(secd, secd_size, GFP_KERNEL); if (secd == NULL) { dev_err(dev, "Can't allocate space for security descriptors\n"); goto out; } result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, 0, secd, secd_size); if (result < secd_size) { dev_err(dev, "Can't read security descriptor or " "not enough data: %d\n", result); goto out; } bytes = 0; itr = &secd[1]; top = (void *)secd + result; while (itr < top) { etd = itr; if (top - itr < sizeof(*etd)) { dev_err(dev, "BUG: bad device security descriptor; " "not enough data (%zu vs %zu bytes left)\n", top - itr, sizeof(*etd)); break; } if (etd->bLength < sizeof(*etd)) { dev_err(dev, "BUG: bad device encryption descriptor; " "descriptor is too short " "(%u vs %zu needed)\n", etd->bLength, sizeof(*etd)); break; } itr += etd->bLength; bytes += snprintf(buf + bytes, sizeof(buf) - bytes, "%s (0x%02x/%02x) ", wusb_et_name(etd->bEncryptionType), etd->bEncryptionValue, etd->bAuthKeyIndex); if (etd->bEncryptionType == USB_ENC_TYPE_CCM_1) ccm1_etd = etd; } /* This code only supports CCM1 as of now. */ /* FIXME: user has to choose which sec mode to use? * In theory we want CCM */ if (ccm1_etd == NULL) { dev_err(dev, "WUSB device doesn't support CCM1 encryption, " "can't use!\n"); result = -EINVAL; goto out; } wusb_dev->ccm1_etd = *ccm1_etd; dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n", buf, wusb_et_name(ccm1_etd->bEncryptionType), ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex); result = 0; out: kfree(secd); return result; }
//! usb_process_request. //! //! @brief This function reads the SETUP request sent to the default control endpoint //! and calls the appropriate function. When exiting of the usb_read_request //! function, the device is ready to manage the next request. //! //! @param none //! //! @return none //! @note list of supported requests: //! GET_DESCRIPTOR //! GET_CONFIGURATION //! SET_ADDRESS //! SET_CONFIGURATION //! CLEAR_FEATURE //! SET_FEATURE //! GET_STATUS //! void usb_process_request(void) { U8 bmRequest; bmRequestType = Usb_read_byte(); bmRequest = Usb_read_byte(); switch (bmRequest) { case GET_DESCRIPTOR: if (0x80 == bmRequestType) { usb_get_descriptor(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_CONFIGURATION: if (0x80 == bmRequestType) { usb_get_configuration(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_ADDRESS: if (0x00 == bmRequestType) { usb_set_address(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_CONFIGURATION: if (0x00 == bmRequestType) { usb_set_configuration(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case CLEAR_FEATURE: if (0x02 >= bmRequestType) { usb_clear_feature(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_FEATURE: if (0x02 >= bmRequestType) { usb_set_feature(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_STATUS: if ((0x7F < bmRequestType) & (0x82 >= bmRequestType)) { usb_get_status(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case GET_INTERFACE: if (bmRequestType == 0x81) { usb_get_interface(); } else { usb_user_read_request(bmRequestType, bmRequest); } break; case SET_INTERFACE: if (bmRequestType == 0x01) {usb_set_interface();} break; case SET_DESCRIPTOR: case SYNCH_FRAME: default: //!< un-supported request => call to user read request if(usb_user_read_request(bmRequestType, bmRequest) == FALSE) { Usb_enable_stall_handshake(); Usb_ack_receive_setup(); return; } break; } }
int main(int argc, char **argv) { int ret, vendor, product; struct usb_device *dev; char buf[65535], *endptr; #if 0 usb_urb *isourb; struct timeval isotv; char isobuf[32768]; #endif usb_init(); // usb_set_debug(255); usb_find_busses(); usb_find_devices(); /* if (argc!=3) { printf("usage: %s vendorID productID\n", argv[0]); printf("ID numbers of currently attached devices:\n"); list_devices(); exit(1); } vendor = strtol(argv[1], &endptr, 16); if (*endptr != '\0') { printf("invalid vendor id\n"); exit(1); } product = strtol(argv[2], &endptr, 16); if (*endptr != '\0') { printf("invalid product id\n"); exit(1); } */ printf("Hladam HUAWEI E220 a prepnem na modem - bbo 06\n"); vendor = 0x12d1; product = 0x1003; dev = find_device(vendor, product); assert(dev); devh = usb_open(dev); assert(devh); signal(SIGTERM, release_usb_device); /* ret = usb_get_driver_np(devh, 0, buf, sizeof(buf)); printf("usb_get_driver_np returned %d\n", ret); if (ret == 0) { printf("interface 0 already claimed by driver \"%s\", attempting to detach it\n", buf); ret = usb_detach_kernel_driver_np(devh, 0); printf("usb_detach_kernel_driver_np returned %d\n", ret); } ret = usb_claim_interface(devh, 0); if (ret != 0) { printf("claim failed with error %d\n", ret); exit(1); } ret = usb_set_altinterface(devh, 0); assert(ret >= 0); */ // BBO typ 1 = DEVICE ret = usb_get_descriptor(devh, 0x0000001, 0x0000000, buf, 0x0000012); //printf("1 get descriptor returned %d, bytes: ", ret); //print_bytes(buf, ret); //printf("\n"); usleep(1*1000); // BBO typ 2 = CONFIGURATION ret = usb_get_descriptor(devh, 0x0000002, 0x0000000, buf, 0x0000009); //printf("2 get descriptor returned %d, bytes: ", ret); //print_bytes(buf, ret); //printf("\n"); usleep(1*1000); // BBO typ 2 = CONFIGURATION ret = usb_get_descriptor(devh, 0x0000002, 0x0000000, buf, 0x0000020); //printf("3 get descriptor returned %d, bytes: ", ret); //print_bytes(buf, ret); //printf("\n"); usleep(1*1000); /* ret = usb_release_interface(devh, 0); if (ret != 0) printf("failed to release interface before set_configuration: %d\n", ret); ret = usb_set_configuration(devh, 0x0000001); printf("4 set configuration returned %d\n", ret); ret = usb_claim_interface(devh, 0); if (ret != 0) printf("claim after set_configuration failed with error %d\n", ret); ret = usb_set_altinterface(devh, 0); printf("4 set alternate setting returned %d\n", ret); usleep(50*1000); ret = usb_set_altinterface(devh, 0); printf("5 set alternate setting returned %d\n", ret); usleep(62*1000); */ ret = usb_control_msg(devh, USB_TYPE_STANDARD + USB_RECIP_DEVICE, USB_REQ_SET_FEATURE, 00000001, 0, buf, 0, 1000); printf("4 set feature request returned %d\n", ret); /* ret = usb_release_interface(devh, 0); assert(ret == 0); */ ret = usb_close(devh); assert(ret == 0); printf("Prepnute-OK, Mas ttyUSB0 ttyUSB1 (cez usbserial vendor=0x12d1 product=0x1004)\n"); printf("pozri /proc/bus/usb/devices\n"); return 0; }
static int ch9_postconfig(struct usbtest_dev *dev) { struct usb_interface *iface = dev->intf; struct usb_device *udev = interface_to_usbdev(iface); int i, alt, retval; for (i = 0; i < iface->num_altsetting; i++) { alt = iface->altsetting[i].desc.bAlternateSetting; if (alt < 0 || alt >= iface->num_altsetting) { dev_err(&iface->dev, "invalid alt [%d].bAltSetting = %d\n", i, alt); } if (realworld && iface->num_altsetting == 1) continue; retval = set_altsetting(dev, alt); if (retval) { dev_err(&iface->dev, "can't set_interface = %d, %d\n", alt, retval); return retval; } retval = get_altsetting(dev); if (retval != alt) { dev_err(&iface->dev, "get alt should be %d, was %d\n", alt, retval); return (retval < 0) ? retval : -EDOM; } } if (!realworld || udev->descriptor.bNumConfigurations != 1) { int expected = udev->actconfig->desc.bConfigurationValue; retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), USB_REQ_GET_CONFIGURATION, USB_DIR_IN | USB_RECIP_DEVICE, 0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT); if (retval != 1 || dev->buf[0] != expected) { dev_err(&iface->dev, "get config --> %d %d (1 %d)\n", retval, dev->buf[0], expected); return (retval < 0) ? retval : -EDOM; } } retval = usb_get_descriptor(udev, USB_DT_DEVICE, 0, dev->buf, sizeof udev->descriptor); if (retval != sizeof udev->descriptor) { dev_err(&iface->dev, "dev descriptor --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } for (i = 0; i < udev->descriptor.bNumConfigurations; i++) { retval = usb_get_descriptor(udev, USB_DT_CONFIG, i, dev->buf, TBUF_SIZE); if (!is_good_config(dev, retval)) { dev_err(&iface->dev, "config [%d] descriptor --> %d\n", i, retval); return (retval < 0) ? retval : -EDOM; } } if (le16_to_cpu(udev->descriptor.bcdUSB) == 0x0200) { struct usb_qualifier_descriptor *d = NULL; retval = usb_get_descriptor(udev, USB_DT_DEVICE_QUALIFIER, 0, dev->buf, sizeof(struct usb_qualifier_descriptor)); if (retval == -EPIPE) { if (udev->speed == USB_SPEED_HIGH) { dev_err(&iface->dev, "hs dev qualifier --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } } else if (retval != sizeof(struct usb_qualifier_descriptor)) { dev_err(&iface->dev, "dev qualifier --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } else d = (struct usb_qualifier_descriptor *) dev->buf; if (d) { unsigned max = d->bNumConfigurations; for (i = 0; i < max; i++) { retval = usb_get_descriptor(udev, USB_DT_OTHER_SPEED_CONFIG, i, dev->buf, TBUF_SIZE); if (!is_good_config(dev, retval)) { dev_err(&iface->dev, "other speed config --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } } } } retval = usb_get_status(udev, USB_RECIP_DEVICE, 0, dev->buf); if (retval != 2) { dev_err(&iface->dev, "get dev status --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } retval = usb_get_status(udev, USB_RECIP_INTERFACE, iface->altsetting[0].desc.bInterfaceNumber, dev->buf); if (retval != 2) { dev_err(&iface->dev, "get interface status --> %d\n", retval); return (retval < 0) ? retval : -EDOM; } return 0; }