📄 usb.c
字号:
if (ep[e].wMaxPacketSize > dev->epmaxpacketin [b]) dev->epmaxpacketin [b] = ep[e].wMaxPacketSize; } } }}/* * endp: endpoint number in bits 0-3; * direction flag in bit 7 (1 = IN, 0 = OUT) */int usb_clear_halt(struct usb_device *dev, int pipe){ int result; __u16 status;#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) unsigned char *buffer;#endif int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);/* if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp))) return 0;*/ result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT); /* don't clear if failed */ if (result < 0) return result;#if defined(CONFIG_USB_UHCI124) || defined(CONFIG_USB_UHCI124_MODULE) result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp, &status, sizeof(status), HZ * SET_TIMEOUT);#else buffer = kmalloc(sizeof(status), GFP_KERNEL); if (!buffer) { err("unable to allocate memory for configuration descriptors"); return -ENOMEM; } result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp, buffer, sizeof(status), HZ * SET_TIMEOUT); memcpy(&status, buffer, sizeof(status)); kfree(buffer);#endif if (result < 0) return result; if (le16_to_cpu(status) & 1) return -EPIPE; /* still halted */ usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); /* toggle is reset on clear */ usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0); return 0;}int usb_set_interface(struct usb_device *dev, int interface, int alternate){ struct usb_interface *iface; int ret; iface = usb_ifnum_to_if(dev, interface); if (!iface) { warn("selecting invalid interface %d", interface); return -EINVAL; }#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) /* 9.4.10 says devices don't need this, if the interface only has one alternate setting */ if (iface->num_altsetting == 1) { warn("ignoring set_interface for dev %d, iface %d, alt %d", dev->devnum, interface, alternate); return 0; }#endif if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, interface, NULL, 0, HZ * 5)) < 0) return ret; iface->act_altsetting = alternate; dev->toggle[0] = 0; /* 9.1.1.5 says to do this */ dev->toggle[1] = 0; usb_set_maxpacket(dev); return 0;}int usb_set_configuration(struct usb_device *dev, int configuration){ int i, ret; struct usb_config_descriptor *cp = NULL; for (i=0; i<dev->descriptor.bNumConfigurations; i++) { if (dev->config[i].bConfigurationValue == configuration) { cp = &dev->config[i]; break; } } if (!cp) { warn("selecting invalid configuration %d", configuration); return -EINVAL; } if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * SET_TIMEOUT)) < 0) return ret; dev->actconfig = cp; dev->toggle[0] = 0; dev->toggle[1] = 0; usb_set_maxpacket(dev); return 0;}int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size){ return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, (type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);}int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size){ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (type << 8) + id, ifnum, buf, size, HZ);}int usb_get_configuration(struct usb_device *dev){#if defined(CONFIG_USB_UHCI124) || defined(CONFIG_USB_UHCI124_MODULE)#define CFG_LEN 59static __u8 msDevCfg[CFG_LEN] = {0x09,0x02,0x3B,0x00,0x02,0x01,0x01,0xA0, 0x32,0x09,0x04,0x00,0x00,0x01,0x03,0x01, 0x01,0x01,0x09,0x21,0x10,0x01,0x00,0x01, 0x22,0x36,0x00,0x07,0x05,0x81,0x03,0x08, 0x00,0x0A,0x09,0x04,0x01,0x00,0x01,0x03, 0x00,0x00,0x01,0x09,0x21,0x10,0x01,0x00, 0x01,0x22,0x32,0x00,0x07,0x05,0x82,0x03, 0x03,0x00,0x0A};static __u8 justyDevCfg[CFG_LEN] = {0x09,0x02,0x3B,0x00,0x02,0x01,0x00,0xA0, 0x32,0x09,0x04,0x00,0x00,0x01,0x03,0x01, 0x01,0x04,0x09,0x21,0x00,0x01,0x21,0x01, 0x22,0x40,0x00,0x07,0x05,0x81,0x03,0x08, 0x00,0x0A,0x09,0x04,0x01,0x00,0x01,0x03, 0x01,0x02,0x05,0x09,0x21,0x00,0x01,0x21, 0x01,0x22,0x32,0x00,0x07,0x05,0x82,0x03, 0x03,0x00,0x0A};#endif int result; unsigned int cfgno, length; unsigned char *bigbuffer;#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) unsigned char *buffer; struct usb_config_descriptor *desc;#else unsigned char buffer[8]; struct usb_config_descriptor *desc = (struct usb_config_descriptor *)buffer;#endif 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_config_descriptor *) kmalloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor), GFP_KERNEL); if (!dev->config) { err("out of memory"); return -ENOMEM; } memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); dev->rawdescriptors = (char **)kmalloc(sizeof(char *) * dev->descriptor.bNumConfigurations, GFP_KERNEL); if (!dev->rawdescriptors) { err("out of memory"); return -ENOMEM; }#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) buffer = kmalloc(8, GFP_KERNEL); if (!buffer) { err("unable to allocate memory for configuration descriptors"); return -ENOMEM; } desc = (struct usb_config_descriptor *)buffer;#endif 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) {#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) err("config descriptor too short (expected %i, got %i)", length, result); result = -EINVAL; kfree(bigbuffer); goto err;#else printk("INFO: new device strings:" " vendor=%d, product=%d, device=%d\n", dev->descriptor.idVendor, dev->descriptor.idProduct, dev->descriptor.bcdDevice); if (dev->descriptor.idVendor == 1118 && dev->descriptor.idProduct == 29) {/* MS */ memcpy( bigbuffer, msDevCfg, length ); result = length; } else if (dev->descriptor.idVendor == 1266 && dev->descriptor.idProduct == 1) {/* Justy */ memcpy( bigbuffer, justyDevCfg, length ); result = length; } else { err("config descriptor too short" " (expected %i, got %i)", length, result); result = -EINVAL; kfree(bigbuffer); goto err; }#endif } 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; } }#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) kfree(buffer);#endif return 0;err:#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) kfree(buffer);#endif dev->descriptor.bNumConfigurations = cfgno; return result;}/* * usb_string: * returns string length (> 0) or error (< 0) */int usb_string(struct usb_device *dev, int index, char *buf, size_t size){ unsigned char *tbuf; int err; unsigned int u, idx; if (size <= 0 || !buf || !index) return -EINVAL; buf[0] = 0; tbuf = kmalloc(256, GFP_KERNEL); if (!tbuf) return -ENOMEM; /* get langid for strings if it's not yet known */ if (!dev->have_langid) { err = usb_get_string(dev, 0, 0, tbuf, 4); if (err < 0) { err("error getting string descriptor 0 (error=%d)", err); goto errout; } else if (tbuf[0] < 4) { err("string descriptor 0 too short"); err = -EINVAL; goto errout; } else { dev->have_langid = -1; dev->string_langid = tbuf[2] | (tbuf[3]<< 8); /* always use the first langid listed */ dbg("USB device number %d default language ID 0x%x", dev->devnum, dev->string_langid); } } /* * Just ask for a maximum length string and then take the length * that was returned. */ err = usb_get_string(dev, dev->string_langid, index, tbuf, 255); if (err < 0) goto errout; size--; /* leave room for trailing NULL char in output buffer */ for (idx = 0, u = 2; u < err; u += 2) { if (idx >= size) break; if (tbuf[u+1]) /* high byte */ buf[idx++] = '?'; /* non-ASCII character */ else buf[idx++] = tbuf[u]; } buf[idx] = 0; err = idx; errout: kfree(tbuf); return err;}/* * By the time we get here, the device has gotten a new device ID * and is in the default state. We need to identify the thing and * get the ball rolling.. * * Returns 0 for success, != 0 for error. */int usb_new_device(struct usb_device *dev){ int err; /* USB v1.1 5.5.3 */ /* We read the first 8 bytes from the device descriptor to get to */ /* the bMaxPacketSize0 field. Then we set the maximum packet size */ /* for the control pipe, and retrieve the rest */ dev->epmaxpacketin [0] = 8; dev->epmaxpacketout[0] = 8; err = usb_set_address(dev); if (err < 0) { err("USB device not accepting new address=%d (error=%d)", dev->devnum, err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } wait_ms(10); /* Let the SET_ADDRESS settle */ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); if (err < 8) { if (err < 0) err("USB device not responding, giving up (error=%d)", err); else err("USB device descriptor short read (expected %i, got %i)", 8, err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; err = usb_get_device_descriptor(dev);#if !defined(CONFIG_USB_UHCI124) && !defined(CONFIG_USB_UHCI124_MODULE) if (err < (signed)sizeof(dev->descriptor)) {#else if (err < 18) {#endif if (err < 0) err("unable to get device descriptor (error=%d)", err); else err("USB device descriptor short read (expected %Zi, got %i)", sizeof(dev->descriptor), err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } err = usb_get_configuration(dev); if (err < 0) { err("unable to get device %d configuration (error=%d)", dev->devnum, err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } /* we set the default configuration here */ err = usb_set_configuration(dev, dev->config[0].bConfigurationValue); if (err) { err("failed to set device %d default configuration (error=%d)", dev->devnum, err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d", dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);#ifdef DEBUG if (dev->descriptor.iManufacturer) usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer); if (dev->descriptor.iProduct) usb_show_string(dev, "Product", dev->descriptor.iProduct); if (dev->descriptor.iSerialNumber) usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);#endif /* now that the basic setup is over, add a /proc/bus/usb entry */ usbdevfs_add_device(dev); /* find drivers willing to handle this device */ usb_find_drivers(dev); /* userspace may load modules and/or configure further */ call_policy ("add", dev); return 0;}static int usb_open(struct inode * inode, struct file * file){ int minor = MINOR(inode->i_rdev); struct usb_driver *c = usb_minors[minor/16]; int err = -ENODEV; struct file_operations *old_fops, *new_fops = NULL; /* * No load-on-demand? Randy, could you ACK that it's really not * supposed to be done? -- AV */ if (!c || !(new_fop
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -