📄 usb.c
字号:
iface = usb_ifnum_to_if(dev, interface); if (!iface) { warn("selecting invalid interface %d", interface); return -EINVAL; } 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){ int result; unsigned int cfgno, length; unsigned char buffer[8]; unsigned char *bigbuffer; struct usb_config_descriptor *desc = (struct usb_config_descriptor *)buffer; 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; } 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, &dev->config[cfgno], bigbuffer); if (result > 0) dbg("descriptor data left"); else if (result < 0) { result = -EINVAL; goto err; } } return 0;err: 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 (err < sizeof(dev->descriptor)) { if (err < 0) err("unable to get device descriptor (error=%d)", err); else err("USB device descriptor short read (expected %i, 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; usb_free_dev(dev); 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_fops = fops_get(c->fops))) return err; old_fops = file->f_op; file->f_op = new_fops; /* Curiouser and curiouser... NULL ->open() as "no device" ? */ if (file->f_op->open) err = file->f_op->open(inode,file); if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); } fops_put(old_fops); return err;}static struct file_operations usb_fops = { owner: THIS_MODULE, open: usb_open,};int usb_major_init(void){ if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) { err("unable to get major %d for usb devices", USB_MAJOR); return -EBUSY; } usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL); return 0;}void usb_major_cleanup(void){ devfs_unregister(usb_devfs_handle); devfs_unregister_chrdev(USB_MAJOR, "usb");}#ifdef CONFIG_PROC_FSstruct list_head *usb_driver_get_list(void){ return &usb_driver_list;}struct list_head *usb_bus_get_list(void){ return &usb_bus_list;}#endif/* * Init */static int __init usb_init(void){ usb_major_init(); usbdevfs_init(); usb_hub_init(); return 0;}/* * Cleanup */static void __exit usb_exit(void){ usb_major_cleanup(); usbdevfs_cleanup(); usb_hub_cleanup();}module_init(usb_init);module_exit(usb_exit);/* * USB may be built into the kernel or be built as modules. * If the USB core [and maybe a host controller driver] is built * into the kernel, and other device drivers are built as modules, * then these symbols need to be exported for the modules to use. */EXPORT_SYMBOL(usb_ifnum_to_if);EXPORT_SYMBOL(usb_epnum_to_ep_desc);EXPORT_SYMBOL(usb_register);EXPORT_SYMBOL(usb_deregister);EXPORT_SYMBOL(usb_scan_devices);EXPORT_SYMBOL(usb_alloc_bus);EXPORT_SYMBOL(usb_free_bus);EXPORT_SYMBOL(usb_register_bus);EXPORT_SYMBOL(usb_deregister_bus);EXPORT_SYMBOL(usb_alloc_dev);EXPORT_SYMBOL(usb_free_dev);EXPORT_SYMBOL(usb_inc_dev_use);EXPORT_SYMBOL(usb_driver_claim_interface);EXPORT_SYMBOL(usb_interface_claimed);EXPORT_SYMBOL(usb_driver_release_interface);EXPORT_SYMBOL(usb_match_id);EXPORT_SYMBOL(usb_root_hub_string);EXPORT_SYMBOL(usb_new_device);EXPORT_SYMBOL(usb_reset_device);EXPORT_SYMBOL(usb_connect);EXPORT_SYMBOL(usb_disconnect);EXPORT_SYMBOL(usb_check_bandwidth);EXPORT_SYMBOL(usb_claim_bandwidth);EXPORT_SYMBOL(usb_release_bandwidth);EXPORT_SYMBOL(usb_set_address);EXPORT_SYMBOL(usb_get_descriptor);EXPORT_SYMBOL(usb_get_class_descriptor);EXPORT_SYMBOL(__usb_get_extra_descriptor);EXPORT_SYMBOL(usb_get_device_descriptor);EXPORT_SYMBOL(usb_get_string);EXPORT_SYMBOL(usb_string);EXPORT_SYMBOL(usb_get_protocol);EXPORT_SYMBOL(usb_set_protocol);EXPORT_SYMBOL(usb_get_report);EXPORT_SYMBOL(usb_set_report);EXPORT_SYMBOL(usb_set_idle);EXPORT_SYMBOL(usb_clear_halt);EXPORT_SYMBOL(usb_set_interface);EXPORT_SYMBOL(usb_get_configuration);EXPORT_SYMBOL(usb_set_configuration);EXPORT_SYMBOL(usb_get_current_frame_number);EXPORT_SYMBOL(usb_alloc_urb);EXPORT_SYMBOL(usb_free_urb);EXPORT_SYMBOL(usb_submit_urb);EXPORT_SYMBOL(usb_unlink_urb);EXPORT_SYMBOL(usb_control_msg);EXPORT_SYMBOL(usb_bulk_msg);EXPORT_SYMBOL(usb_devfs_handle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -