📄 usb.c
字号:
USB_PRINTF("usb_get_configuration_no: failed to get descriptor - too long: %d\n", tmp); return -1; } result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp); USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",cfgno,result,tmp); return result;}/******************************************************************** * set address of a device to the value in dev->devnum. * This can only be done by addressing the device via the default address (0) */int usb_set_address(struct usb_device *dev){ int res; USB_PRINTF("set address %d\n",dev->devnum); res=usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, 0, (dev->devnum),0, NULL,0, USB_CNTL_TIMEOUT); return res;}/******************************************************************** * set interface number to interface */int usb_set_interface(struct usb_device *dev, int interface, int alternate){ struct usb_interface_descriptor *if_face = NULL; int ret, i; for (i = 0; i < dev->config.bNumInterfaces; i++) { if (dev->config.if_desc[i].bInterfaceNumber == interface) { if_face = &dev->config.if_desc[i]; break; } } if (!if_face) { printf("selecting invalid interface %d", interface); return -1; } /* * We should return now for devices with only one alternate setting. * According to 9.4.10 of the Universal Serial Bus Specification Revision 2.0 * such devices can return with a STALL. This results in some USB sticks * timeouting during initialization and then being unusable in U-Boot. */ if (if_face->num_altsetting == 1) return 0; if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate, interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0) return ret; return 0;}/******************************************************************** * set configuration number to configuration */int usb_set_configuration(struct usb_device *dev, int configuration){ int res; USB_PRINTF("set configuration %d\n",configuration); /* set setup command */ res=usb_control_msg(dev, usb_sndctrlpipe(dev,0), USB_REQ_SET_CONFIGURATION, 0, configuration,0, NULL,0, USB_CNTL_TIMEOUT); if(res==0) { dev->toggle[0] = 0; dev->toggle[1] = 0; return 0; } else return -1;}/******************************************************************** * set protocol to protocol */int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol){ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE, protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT);}/******************************************************************** * set idle */int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id){ return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT);}/******************************************************************** * get report */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, USB_CNTL_TIMEOUT);}/******************************************************************** * get class descriptor */int usb_get_class_descriptor(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_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);}/******************************************************************** * get string index in buffer */int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size){ int i; int result; for (i = 0; i < 3; ++i) { /* some devices are flaky */ result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, (USB_DT_STRING << 8) + index, langid, buf, size, USB_CNTL_TIMEOUT); if (result > 0) break; } return result;}static void usb_try_string_workarounds(unsigned char *buf, int *length){ int newlength, oldlength = *length; for (newlength = 2; newlength + 1 < oldlength; newlength += 2) if (!isprint(buf[newlength]) || buf[newlength + 1]) break; if (newlength > 2) { buf[0] = newlength; *length = newlength; }}static int usb_string_sub(struct usb_device *dev, unsigned int langid, unsigned int index, unsigned char *buf){ int rc; /* Try to read the string descriptor by asking for the maximum * possible number of bytes */ rc = usb_get_string(dev, langid, index, buf, 255); /* If that failed try to read the descriptor length, then * ask for just that many bytes */ if (rc < 2) { rc = usb_get_string(dev, langid, index, buf, 2); if (rc == 2) rc = usb_get_string(dev, langid, index, buf, buf[0]); } if (rc >= 2) { if (!buf[0] && !buf[1]) usb_try_string_workarounds(buf, &rc); /* There might be extra junk at the end of the descriptor */ if (buf[0] < rc) rc = buf[0]; rc = rc - (rc & 1); /* force a multiple of two */ } if (rc < 2) rc = -1; return rc;}/******************************************************************** * usb_string: * Get string index and translate it to ascii. * returns string length (> 0) or error (< 0) */int usb_string(struct usb_device *dev, int index, char *buf, size_t size){ unsigned char mybuf[USB_BUFSIZ]; unsigned char *tbuf; int err; unsigned int u, idx; if (size <= 0 || !buf || !index) return -1; buf[0] = 0; tbuf=&mybuf[0]; /* get langid for strings if it's not yet known */ if (!dev->have_langid) { err = usb_string_sub(dev, 0, 0, tbuf); if (err < 0) { USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status); return -1; } else if (tbuf[0] < 4) { USB_PRINTF("string descriptor 0 too short\n"); return -1; } else { dev->have_langid = -1; dev->string_langid = tbuf[2] | (tbuf[3]<< 8); /* always use the first langid listed */ USB_PRINTF("USB device number %d default language ID 0x%x\n", dev->devnum, dev->string_langid); } } err = usb_string_sub(dev, dev->string_langid, index, tbuf); if (err < 0) return err; 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; return err;}/******************************************************************** * USB device handling: * the USB device are static allocated [USB_MAX_DEVICE]. *//* returns a pointer to the device with the index [index]. * if the device is not assigned (dev->devnum==-1) returns NULL */struct usb_device * usb_get_dev_index(int index){ if(usb_dev[index].devnum==-1) return NULL; else return &usb_dev[index];}/* returns a pointer of a new device structure or NULL, if * no device struct is available */struct usb_device * usb_alloc_new_device(void){ int i; USB_PRINTF("New Device %d\n",dev_index); if(dev_index==USB_MAX_DEVICE) { printf("ERROR, too many USB Devices, max=%d\n",USB_MAX_DEVICE); return NULL; } usb_dev[dev_index].devnum=dev_index+1; /* default Address is 0, real addresses start with 1 */ usb_dev[dev_index].maxchild=0; for(i=0;i<USB_MAXCHILDREN;i++) usb_dev[dev_index].children[i]=NULL; usb_dev[dev_index].parent=NULL; dev_index++; return &usb_dev[dev_index-1];}/* * 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; unsigned char tmpbuf[USB_BUFSIZ]; dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */ 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;#undef NEW_INIT_SEQ#ifdef NEW_INIT_SEQ /* this is a Windows scheme of initialization sequence, with double * reset of the device. Some equipment is said to work only with such * init sequence; this patch is based on the work by Alan Stern: * http://sourceforge.net/mailarchive/forum.php?thread_id=5729457&forum_id=5398 */ int j; struct usb_device_descriptor *desc; int port = -1; struct usb_device *parent = dev->parent; unsigned short portstatus; /* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is * only 18 bytes long, this will terminate with a short packet. But if * the maxpacket size is 8 or 16 the device may be waiting to transmit * some more. */ desc = (struct usb_device_descriptor *)tmpbuf; desc->bMaxPacketSize0 = 0; for (j = 0; j < 3; ++j) { err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); if (err < 0) { USB_PRINTF("usb_new_device: 64 byte descr\n"); break; } } dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; /* find the port number we're at */ if (parent) { for (j = 0; j < parent->maxchild; j++) { if (parent->children[j] == dev) { port = j; break; } } if (port < 0) { printf("usb_new_device: cannot locate device's port..\n"); return 1; } /* reset the port for the second time */ err = hub_port_reset(dev->parent, port, &portstatus); if (err < 0) { printf("\n Couldn't reset port %i\n", port); return 1; } }#else /* and this is the old and known way of initializing devices */ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8); if (err < 8) { printf("\n USB device not responding, giving up (status=%lX)\n",dev->status); return 1; }#endif 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); /* set address */ if (err < 0) { printf("\n USB device not accepting new address (error=%lX)\n", dev->status); return 1; } wait_ms(10); /* Let the SET_ADDRESS settle */ tmp = sizeof(dev->descriptor); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor)); if (err < tmp) { if (err < 0) printf("unable to get device descriptor (error=%d)\n",err); else printf("USB device descriptor short read (expected %i, got %i)\n",tmp,err); return 1; } /* correct le values */ dev->descriptor.bcdUSB=swap_16(dev->descriptor.bcdUSB); dev->descriptor.idVendor=swap_16(dev->descriptor.idVendor); dev->descriptor.idProduct=swap_16(dev->descriptor.idProduct); dev->descriptor.bcdDevice=swap_16(dev->descriptor.bcdDevice); /* only support for one config for now */ usb_get_configuration_no(dev,&tmpbuf[0],0); usb_parse_config(dev,&tmpbuf[0],0); usb_set_maxpacket(dev); /* we set the default configuration here */ if (usb_set_configuration(dev, dev->config.bConfigurationValue)) { printf("failed to set default configuration len %d, status %lX\n",dev->act_len,dev->status); return -1; } USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber); memset(dev->mf, 0, sizeof(dev->mf)); memset(dev->prod, 0, sizeof(dev->prod)); memset(dev->serial, 0, sizeof(dev->serial));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -