📄 usb.c
字号:
result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
/* don't clear if failed */
if (result < 0) return result;
/*
* NOTE: we do not get status and verify reset was successful
* as some devices are reported to lock up upon this check..
*/
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;
}
/**********************************************************************
* get_descriptor type
*/
int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
{
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), USB_REQ_GET_DESCRIPTOR,
USB_DIR_IN, (type << 8) + index, 0, buf, size, USB_CNTL_TIMEOUT);
}
/**********************************************************************
* gets configuration cfgno and store it in the buffer
*/
int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno)
{
int result;
unsigned int len;
struct usb_config_descriptor *config;
config = (struct usb_config_descriptor *)&buffer[0];
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
if (result < 8)
{ if (result < 0)
{ /* unable to get descriptor, error %lX\n",dev->status); */
}
else
{ /* config descriptor too short (expected %i, got %i)\n",8,result); */
}
return -1;
}
len = swap_16(config->wTotalLength);
if(len > USB_BUFSIZ)
{ /* usb_get_configuration_no: failed to get descriptor - too long: %d\n", len); */
return -1;
}
result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, len);
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)
{
return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, 0, (dev->devnum),0, NULL,0, USB_CNTL_TIMEOUT);
}
/********************************************************************
* 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) return -1; // selecting invalid interface %d";
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE,
USB_RECIP_INTERFACE, alternate, interface, NULL, 0, USB_CNTL_TIMEOUT * 5);
if(ret < 0)
{ return ret; }
return 0;
}
/********************************************************************
* set configuration number to configuration
*/
int usb_set_configuration(struct usb_device *dev, int configuration)
{int res;
/* 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)
{
int err;
unsigned int u, idx;
unsigned char *sbuf;
if (size <= 0 || !buf || !index) return -1;
sbuf = malloc(USB_BUFSIZ);
if(sbuf == NULL) return -1;
buf[0] = 0;
/* get langid for strings if it's not yet known */
if (!dev->have_langid)
{
err = usb_string_sub(dev, 0, 0, sbuf);
if (err < 0)
{ free(sbuf);
return -1; /* error getting string descriptor 0 (error=%x)\n",dev->status); */
}
else if (sbuf[0] < 4)
{ free(sbuf);
return -1; /* string descriptor 0 too short\n"); */
}
else
{
dev->have_langid = -1;
dev->string_langid = sbuf[2] | (sbuf[3]<< 8);
/* always use the first langid listed */
}
}
err = usb_string_sub(dev, dev->string_langid, index, sbuf);
if (err < 0)
{ free(sbuf);
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 (sbuf[u+1]) /* high byte */
{ buf[idx++] = '?'; }/* non-ASCII character */
else
{ buf[idx++] = sbuf[u]; }
}
buf[idx] = 0;
err = idx;
free(sbuf);
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 dev_index, i;
/* New Device %d\n",dev_index); */
for(dev_index=0; dev_index<USB_MAX_DEVICE; dev_index++)
{ if((usb_dev[dev_index].devnum == 0) || (usb_dev[dev_index].devnum == -1))
{ break; }
}
if(dev_index >= USB_MAX_DEVICE)
{ return NULL; /* ERROR, too many USB Devices, max=%d\n",USB_MAX_DEVICE); */
}
usb_dev[dev_index].devnum = dev_index + 1; /* 缺省地址为0, 实际地址从 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; /* 清除父设备 */
return &usb_dev[dev_index];
}
/*
* 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.
*/
#define NEW_DEVICE_RETRYS 4
#define SET_ADDRESS_RETRYS 2
int usb_new_device(struct usb_device *dev)
{
int addr, err;
int tmp;
unsigned char *sbuf;
dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */
dev->maxpacketsize = 0; /* Default to 8 byte max packet size */
dev->epmaxpacketin [0] = 8; /* 低速设备为8, 高速设备为64 */
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)
{ return 1; }/* USB device not responding, giving up (status=%lX)\n",dev->status); */
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); /* 设置 USB 设备地址 */
if (err < 0)
{ return -1; }/* device not accepting address %d, error %d\n", dev->devnum, err */
os_dly_wait(1); /* 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) { } /* unable to get device descriptor (error=%d)\n",err); */
else { } /* 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 */
sbuf = malloc(USB_BUFSIZ);
if(sbuf == NULL) return -1;
memset(sbuf, 0, USB_BUFSIZ);
usb_get_configuration_no(dev, sbuf, 0);
usb_parse_config(dev, sbuf, 0);
usb_set_maxpacket(dev);
free(sbuf);
/* we set the default configuration here */
if(usb_set_configuration(dev, dev->config.bConfigurationValue))
{ return -1; /* failed to set default configuration len %d, status %lX\n",dev->act_len,dev->status); */
}
memset(dev->mf, 0, sizeof(dev->mf));
memset(dev->prod, 0, sizeof(dev->prod));
memset(dev->serial, 0, sizeof(dev->serial));
if (dev->descriptor.iManufacturer)
{ usb_string(dev, dev->descriptor.iManufacturer, dev->mf, sizeof(dev->mf)); }
if (dev->descriptor.iProduct)
{ usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod)); }
if (dev->descriptor.iSerialNumber)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -