⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -