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

📄 usb.c

📁 基于s3c2440的U盘读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -