📄 usb.c
字号:
} } } }}/* * 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; 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; 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); if (result < 0) return result; if (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 = NULL; int ret, i; for (i=0; i<dev->actconfig->bNumInterfaces; i++) { if (dev->actconfig->interface[i].altsetting->bInterfaceNumber == interface) { iface = &dev->actconfig->interface[i]; break; } } 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; 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 -1; } 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; unsigned char buffer[8]; unsigned char *bigbuffer; unsigned int tmp; struct usb_config_descriptor *desc = (struct usb_config_descriptor *)buffer; if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG) { warn("too many configurations"); return -1; } if (dev->descriptor.bNumConfigurations < 1) { warn("not enough configurations"); return -1; } 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 -1; } memset(dev->config, 0, dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor)); 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); goto err; } /* Get the full buffer */ le16_to_cpus(&desc->wTotalLength); bigbuffer = kmalloc(desc->wTotalLength, GFP_KERNEL); if (!bigbuffer) { err("unable to allocate memory for configuration descriptors"); result=-ENOMEM; goto err; } tmp=desc->wTotalLength; /* Now that we know the length, get the whole thing */ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, desc->wTotalLength); if (result < 0) { err("couldn't get all of config descriptors"); kfree(bigbuffer); goto err; } if (result < tmp) { err("config descriptor too short (expected %i, got %i)",tmp,result); kfree(bigbuffer); goto err; } result = usb_parse_configuration(dev, &dev->config[cfgno], bigbuffer); kfree(bigbuffer); if (result > 0) dbg("descriptor data left"); else if (result < 0) { result=-1; 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 */ info("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 addr, err; int tmp; info("USB new device connect, assigned device number %d", dev->devnum); dev->maxpacketsize = 0; /* Default to 8 byte max packet size */ dev->epmaxpacketin [0] = 8; dev->epmaxpacketout[0] = 8; /* We still haven't set the Address yet */ addr = dev->devnum; dev->devnum = 0; 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(addr, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; switch (dev->descriptor.bMaxPacketSize0) { case 8: dev->maxpacketsize = 0; break; case 16: dev->maxpacketsize = 1; break; case 32: dev->maxpacketsize = 2; break; case 64: dev->maxpacketsize = 3; break; } dev->devnum = addr; err = usb_set_address(dev); if (err < 0) { err("USB device not accepting new address (error=%d)", err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } wait_ms(10); /* Let the SET_ADDRESS settle */ tmp = sizeof(dev->descriptor); err = usb_get_device_descriptor(dev); if (err < tmp) { if (err < 0) err("unable to get device descriptor (error=%d)",err); else err("USB device descriptor short read (expected %i, got %i)",tmp,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 configuration (error=%d)", err); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; return 1; } dev->actconfig = dev->config; usb_set_maxpacket(dev); /* we set the default configuration here */ if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { err("failed to set default configuration"); return -1; } info("new device strings: Mfr=%d, Product=%d, SerialNumber=%d", dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); 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); /* 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); 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]; file->f_op = NULL; if (c && (file->f_op = c->fops) && file->f_op->open) return file->f_op->open(inode,file); else return -ENODEV;}static struct file_operations usb_fops = { open: usb_open,};int usb_major_init(void){ if (register_chrdev(USB_MAJOR,"usb",&usb_fops)) { err("unable to get major %d for usb devices", USB_MAJOR); return -EBUSY; } return 0;}void usb_major_cleanup(void){ 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/* * 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_register);EXPORT_SYMBOL(usb_deregister);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_init_root_hub);EXPORT_SYMBOL(usb_new_device);EXPORT_SYMBOL(usb_connect);EXPORT_SYMBOL(usb_disconnect);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_request_irq);EXPORT_SYMBOL(usb_release_irq);EXPORT_SYMBOL(usb_bulk_msg);EXPORT_SYMBOL(usb_request_bulk);EXPORT_SYMBOL(usb_terminate_bulk);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -