📄 usb.c
字号:
if (result < 8)
{
if (result < 0)
s_UartPrint("unable to get descriptor, error %lX\n",dev->status);
else
s_UartPrint("config descriptor too short (expected %i, got %i)\n",8,result);
return -1;
}
tmp=swap_16(config->wTotalLength);
if (tmp > USB_BUFSIZ)
{
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)
{
s_UartPrint("selecting invalid interface %d", interface);
return -1;
}
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)
{
s_UartPrint("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)
{
s_UartPrint("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)
{
s_UartPrint("\n Couldn't reset port %i\n", port);
return 1;
}
}
#else
/* and this is the old and known way of initializing devices */
//s_UartPrint("NEW_step 1\n");
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
if (err < 8)
{
s_UartPrint("\n USB device not responding, giving up (status=%lX)\n",dev->status);
return 1;
}
//s_UartPrint("NEW_step 3 err=%d\n",err);
#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;
//s_UartPrint("NEW_step 4\n");
err = usb_set_address(dev); /* set address */
//s_UartPrint("NEW_step 5\n");
if (err < 0)
{
s_UartPrint("\n USB device not accepting new address (error=%lX)\n", dev->status);
s_UartPrint("NEW_step 6\n");
return 1;
}
wait_ms(10); /* Let the SET_ADDRESS settle */
tmp = sizeof(dev->descriptor);
//tmp=8;
//s_UartPrint("NEW_step 7\n");
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor));
if (err < tmp)
{
if (err < 0)
s_UartPrint("unable to get device descriptor (error=%d)\n",err);
else
s_UartPrint("USB device descriptor short read (expected %i, got %i)\n",tmp,err);
s_UartPrint("NEW_step 8\n");
return 1;
}
//dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
//dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
/* 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);
//s_UartPrint("NEW_step 9 size=%d\n",sizeof(dev->descriptor));
USB_PRINTF("bLength %x\n", dev->descriptor.bLength);
USB_PRINTF("bDescriptorType %x\n", dev->descriptor.bDescriptorType);
USB_PRINTF("bcdUSB %x\n", dev->descriptor.bcdUSB);
USB_PRINTF("bDeviceClass %x\n", dev->descriptor.bDeviceClass);
USB_PRINTF("bDeviceSubClass %x\n", dev->descriptor.bDeviceSubClass);
USB_PRINTF("bDeviceProtocol %x\n", dev->descriptor.bDeviceProtocol);
USB_PRINTF("bMaxPacketSize0 %x\n", dev->descriptor.bMaxPacketSize0);
USB_PRINTF("idVendor %x\n", dev->descriptor.idVendor);
USB_PRINTF("idProduct %x\n", dev->descriptor.idProduct);
USB_PRINTF("bcdDevice %x\n", dev->descriptor.bcdDevice);
USB_PRINTF("iManufacturer %x\n", dev->descriptor.iManufacturer);
USB_PRINTF("iProduct %x\n", dev->descriptor.iProduct);
USB_PRINTF("iSerialNumber %x\n", dev->descriptor.iSerialNumber);
USB_PRINTF("bNumConfigurations %x\n", dev->descriptor.bNumConfigurations);
/* only support for one config for now */
usb_get_configuration_no(dev,&tmpbuf[0],0);
//s_UartPrint("NEW_step 10\n");
usb_parse_config(dev,&tmpbuf[0],0);
//s_UartPrint("NEW_step 11\n");
usb_set_maxpacket(dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -