?? usb-linux.c
字號(hào):
/* returns 1 on problem encountered or 0 for success */static int usb_linux_update_endp_table(USBHostDevice *s){ uint8_t *descriptors; uint8_t devep, type, configuration, alt_interface; struct usb_ctrltransfer ct; int interface, ret, length, i; ct.bRequestType = USB_DIR_IN; ct.bRequest = USB_REQ_GET_CONFIGURATION; ct.wValue = 0; ct.wIndex = 0; ct.wLength = 1; ct.data = &configuration; ct.timeout = 50; ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct); if (ret < 0) { perror("usb_linux_update_endp_table"); return 1; } /* in address state */ if (configuration == 0) return 1; /* get the desired configuration, interface, and endpoint descriptors * from device description */ descriptors = &s->descr[18]; length = s->descr_len - 18; i = 0; if (descriptors[i + 1] != USB_DT_CONFIG || descriptors[i + 5] != configuration) { printf("invalid descriptor data - configuration\n"); return 1; } i += descriptors[i]; while (i < length) { if (descriptors[i + 1] != USB_DT_INTERFACE || (descriptors[i + 1] == USB_DT_INTERFACE && descriptors[i + 4] == 0)) { i += descriptors[i]; continue; } interface = descriptors[i + 2]; ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE; ct.bRequest = USB_REQ_GET_INTERFACE; ct.wValue = 0; ct.wIndex = interface; ct.wLength = 1; ct.data = &alt_interface; ct.timeout = 50; ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct); if (ret < 0) { perror("usb_linux_update_endp_table"); return 1; } /* the current interface descriptor is the active interface * and has endpoints */ if (descriptors[i + 3] != alt_interface) { i += descriptors[i]; continue; } /* advance to the endpoints */ while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) i += descriptors[i]; if (i >= length) break; while (i < length) { if (descriptors[i + 1] != USB_DT_ENDPOINT) break; devep = descriptors[i + 2]; switch (descriptors[i + 3] & 0x3) { case 0x00: type = USBDEVFS_URB_TYPE_CONTROL; break; case 0x01: type = USBDEVFS_URB_TYPE_ISO; break; case 0x02: type = USBDEVFS_URB_TYPE_BULK; break; case 0x03: type = USBDEVFS_URB_TYPE_INTERRUPT; break; default: printf("usb_host: malformed endpoint type\n"); type = USBDEVFS_URB_TYPE_BULK; } s->endp_table[(devep & 0xf) - 1].type = type; i += descriptors[i]; } } return 0;}/* XXX: exclude high speed devices or implement EHCI */USBDevice *usb_host_device_open(const char *devname){ int fd = -1, ret; USBHostDevice *dev = NULL; struct usbdevfs_connectinfo ci; char buf[1024]; int bus_num, addr; char product_name[PRODUCT_NAME_SZ]; dev = qemu_mallocz(sizeof(USBHostDevice)); if (!dev) goto fail;#ifdef DEBUG_ISOCH printf("usb_host_device_open %s\n", devname);#endif if (usb_host_find_device(&bus_num, &addr, product_name, sizeof(product_name), devname) < 0) return NULL; snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d", bus_num, addr); fd = open(buf, O_RDWR | O_NONBLOCK); if (fd < 0) { perror(buf); return NULL; } /* read the device description */ dev->descr_len = read(fd, dev->descr, sizeof(dev->descr)); if (dev->descr_len <= 0) { perror("usb_host_device_open: reading device data failed"); goto fail; }#ifdef DEBUG { int x; printf("=== begin dumping device descriptor data ===\n"); for (x = 0; x < dev->descr_len; x++) printf("%02x ", dev->descr[x]); printf("\n=== end dumping device descriptor data ===\n"); }#endif dev->fd = fd; dev->configuration = 1; /* XXX - do something about initial configuration */ if (!usb_host_update_interfaces(dev, 1)) goto fail; ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci); if (ret < 0) { perror("usb_host_device_open: USBDEVFS_CONNECTINFO"); goto fail; }#ifdef DEBUG printf("host USB device %d.%d grabbed\n", bus_num, addr);#endif ret = usb_linux_update_endp_table(dev); if (ret) goto fail; if (ci.slow) dev->dev.speed = USB_SPEED_LOW; else dev->dev.speed = USB_SPEED_HIGH; 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; 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);#ifdef USE_ASYNCIO /* set up the signal handlers */ sigemptyset(&sigact.sa_mask); sigact.sa_sigaction = isoch_done; sigact.sa_flags = SA_SIGINFO; sigact.sa_restorer = 0; ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL); if (ret < 0) { perror("usb_host_device_open: sigaction failed"); goto fail; } if (pipe(dev->pipe_fds) < 0) { perror("usb_host_device_open: pipe creation failed"); goto fail; } fcntl(dev->pipe_fds[0], F_SETFL, O_NONBLOCK | O_ASYNC); fcntl(dev->pipe_fds[1], F_SETFL, O_NONBLOCK); qemu_set_fd_handler(dev->pipe_fds[0], urb_completion_pipe_read, NULL, dev);#endif dev->urbs_ready = 0; return (USBDevice *)dev;fail: if (dev) qemu_free(dev); close(fd); return NULL;}static int get_tag_value(char *buf, int buf_size, const char *str, const char *tag, const char *stopchars){ const char *p; char *q; p = strstr(str, tag); if (!p) return -1; p += strlen(tag); while (isspace(*p)) p++; q = buf; while (*p != '\0' && !strchr(stopchars, *p)) { if ((q - buf) < (buf_size - 1)) *q++ = *p; p++; } *q = '\0'; return q - buf;}static int usb_host_scan(void *opaque, USBScanFunc *func){ FILE *f; char line[1024]; char buf[1024]; int bus_num, addr, speed, device_count, class_id, product_id, vendor_id; int ret; char product_name[512]; f = fopen(USBDEVFS_PATH "/devices", "r"); if (!f) { term_printf("Could not open %s\n", USBDEVFS_PATH "/devices"); return 0; } device_count = 0; bus_num = addr = speed = class_id = product_id = vendor_id = 0; ret = 0; for(;;) { if (fgets(line, sizeof(line), f) == NULL) break; if (strlen(line) > 0) line[strlen(line) - 1] = '\0'; if (line[0] == 'T' && line[1] == ':') { if (device_count && (vendor_id || product_id)) { /* New device. Add the previously discovered device. */ ret = func(opaque, bus_num, addr, class_id, vendor_id, product_id, product_name, speed); if (ret) goto the_end; } if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) goto fail; bus_num = atoi(buf); if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) goto fail; addr = atoi(buf); if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) goto fail; if (!strcmp(buf, "480")) speed = USB_SPEED_HIGH; else if (!strcmp(buf, "1.5")) speed = USB_SPEED_LOW; else speed = USB_SPEED_FULL; product_name[0] = '\0'; class_id = 0xff; device_count++; product_id = 0; vendor_id = 0; } else if (line[0] == 'P' && line[1] == ':') { if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) goto fail; vendor_id = strtoul(buf, NULL, 16); if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) goto fail; product_id = strtoul(buf, NULL, 16); } else if (line[0] == 'S' && line[1] == ':') { if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) goto fail; pstrcpy(product_name, sizeof(product_name), buf); } else if (line[0] == 'D' && line[1] == ':') { if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) goto fail; class_id = strtoul(buf, NULL, 16); } fail: ; } if (device_count && (vendor_id || product_id)) { /* Add the last device. */ ret = func(opaque, bus_num, addr, class_id, vendor_id, product_id, product_name, speed); } the_end: fclose(f); return ret;}typedef struct FindDeviceState { int vendor_id; int product_id; int bus_num; int addr; char product_name[PRODUCT_NAME_SZ];} FindDeviceState;static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, int class_id, int vendor_id, int product_id, const char *product_name, int speed){ FindDeviceState *s = opaque; if ((vendor_id == s->vendor_id && product_id == s->product_id) || (bus_num == s->bus_num && addr == s->addr)) { pstrcpy(s->product_name, PRODUCT_NAME_SZ, product_name); s->bus_num = bus_num; s->addr = addr; return 1; } else { return 0; }}/* the syntax is : 'bus.addr' (decimal numbers) or 'vendor_id:product_id' (hexa numbers) */static int usb_host_find_device(int *pbus_num, int *paddr, char *product_name, int product_name_size, const char *devname){ const char *p; int ret; FindDeviceState fs; p = strchr(devname, '.'); if (p) { *pbus_num = strtoul(devname, NULL, 0); *paddr = strtoul(p + 1, NULL, 0); fs.bus_num = *pbus_num; fs.addr = *paddr; ret = usb_host_scan(&fs, usb_host_find_device_scan); if (ret) pstrcpy(product_name, product_name_size, fs.product_name); return 0; } p = strchr(devname, ':'); if (p) { fs.vendor_id = strtoul(devname, NULL, 16); fs.product_id = strtoul(p + 1, NULL, 16); ret = usb_host_scan(&fs, usb_host_find_device_scan); if (ret) { *pbus_num = fs.bus_num; *paddr = fs.addr; pstrcpy(product_name, product_name_size, fs.product_name); return 0; } } return -1;}/**********************//* USB host device info */struct usb_class_info { int class; const char *class_name;};static const struct usb_class_info usb_class_info[] = { { USB_CLASS_AUDIO, "Audio"}, { USB_CLASS_COMM, "Communication"}, { USB_CLASS_HID, "HID"}, { USB_CLASS_HUB, "Hub" }, { USB_CLASS_PHYSICAL, "Physical" }, { USB_CLASS_PRINTER, "Printer" }, { USB_CLASS_MASS_STORAGE, "Storage" }, { USB_CLASS_CDC_DATA, "Data" }, { USB_CLASS_APP_SPEC, "Application Specific" }, { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, { USB_CLASS_STILL_IMAGE, "Still Image" }, { USB_CLASS_CSCID, "Smart Card" }, { USB_CLASS_CONTENT_SEC, "Content Security" }, { -1, NULL }};static const char *usb_class_str(uint8_t class){ const struct usb_class_info *p; for(p = usb_class_info; p->class != -1; p++) { if (p->class == class) break; } return p->class_name;}static void usb_info_device(int bus_num, int addr, int class_id, int vendor_id, int product_id, const char *product_name, int speed){ const char *class_str, *speed_str; switch(speed) { case USB_SPEED_LOW: speed_str = "1.5"; break; case USB_SPEED_FULL: speed_str = "12"; break; case USB_SPEED_HIGH: speed_str = "480"; break; default: speed_str = "?"; break; } term_printf(" Device %d.%d, speed %s Mb/s\n", bus_num, addr, speed_str); class_str = usb_class_str(class_id); if (class_str) term_printf(" %s:", class_str); else term_printf(" Class %02x:", class_id); term_printf(" USB device %04x:%04x", vendor_id, product_id); if (product_name[0] != '\0') term_printf(", %s", product_name); term_printf("\n");}static int usb_host_info_device(void *opaque, int bus_num, int addr, int class_id, int vendor_id, int product_id, const char *product_name, int speed){ usb_info_device(bus_num, addr, class_id, vendor_id, product_id, product_name, speed); return 0;}void usb_host_info(void){ usb_host_scan(NULL, usb_host_info_device);}#elsevoid usb_host_info(void){ term_printf("USB host devices not supported\n");}/* XXX: modify configure to compile the right host driver */USBDevice *usb_host_device_open(const char *devname){ return NULL;}#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -