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

📄 usb.c

📁 基于s3c2440的U盘读写程序
💻 C
📖 第 1 页 / 共 3 页
字号:
    // s_UartPrint("NEW_step 12\n");
    /* we set the default configuration here */
    if (usb_set_configuration(dev, dev->config.bConfigurationValue)) 
    {
        s_UartPrint("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));
    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)
    usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial));
    USB_PRINTF("Manufacturer %s\n", dev->mf);
    USB_PRINTF("Product      %s\n", dev->prod);
    USB_PRINTF("SerialNumber %s\n", dev->serial);
    /* now prode if the device is a hub */
    usb_hub_probe(dev,0);
    return 0;
}


/* build device Tree  */
void usb_scan_devices(void)
{
    int i;
    struct usb_device *dev;
    /* first make all devices unknown */
    for(i=0;i<USB_MAX_DEVICE;i++) 
    {        
        memset(&usb_dev[i],0,sizeof(struct usb_device));
        usb_dev[i].devnum=-1;
    }
    dev_index=0;
    /* device 0 is always present (root hub, so let it analyze) */
    //s_UartPrint("scan_step 1\n");
    dev=usb_alloc_new_device();
    s_UartPrint("scan_step 2\n");
	s_UartPrint("dev=%d",dev);
    usb_new_device(dev);
    //s_UartPrint("scan_step 3\n");
    //s_UartPrint("%d USB Device(s) found\n",dev_index);
    /* insert "driver" if possible */
}


/****************************************************************************
 * HUB "Driver"
 * Probes device for being a hub and configurate it
 */
#undef	USB_HUB_DEBUG
//#define   USB_HUB_DEBUG
#ifdef	USB_HUB_DEBUG
#define	USB_HUB_PRINTF	s_UartPrint
#else
void USB_HUB_PRINTF(char *fmt,...){}
#endif
static struct usb_hub_device hub_dev[USB_MAX_HUB];
static int usb_hub_index;
int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
{
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
    USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT);
}


int usb_clear_hub_feature(struct usb_device *dev, int feature)
{
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, USB_CNTL_TIMEOUT);
}


int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT);
}


int usb_set_port_feature(struct usb_device *dev, int port, int feature)
{
    return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
    USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT);
}


int usb_get_hub_status(struct usb_device *dev, void *data)
{
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
    data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
}


int usb_get_port_status(struct usb_device *dev, int port, void *data)
{
    return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
    USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
    data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
}


static void usb_hub_power_on(struct usb_hub_device *hub)
{
    int i;
    struct usb_device *dev;
    dev=hub->pusb_dev;
    /* Enable power to the ports */
    USB_HUB_PRINTF("enabling power on all ports\n");
    for (i = 0; i < dev->maxchild; i++) 
    {
        usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
        USB_HUB_PRINTF("port %d returns %lX\n",i+1,dev->status);
        wait_ms(hub->desc.bPwrOn2PwrGood * 2);
    }
}


void usb_hub_reset(void)
{
    usb_hub_index=0;
}


struct usb_hub_device *usb_hub_allocate(void)
{
    if(usb_hub_index<USB_MAX_HUB) 
    {
        return &hub_dev[usb_hub_index++];
    }
    s_UartPrint("ERROR: USB_MAX_HUB (%d) reached\n",USB_MAX_HUB);
    return NULL;
}


#define MAX_TRIES 5
static int hub_port_reset(struct usb_device *dev, int port,
unsigned short *portstat)
{
    int tries;
    struct usb_port_status portsts;
    unsigned short portstatus, portchange;
    USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
    for(tries=0;tries<MAX_TRIES;tries++) 
    {
        usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
        wait_ms(200);
        if (usb_get_port_status(dev, port + 1, &portsts)<0) 
        {
            USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status);
            return -1;
        }
        portstatus = swap_16(portsts.wPortStatus);
        portchange = swap_16(portsts.wPortChange);
        USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus ,portchange,
        portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
        USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d  USB_PORT_STAT_ENABLE %d\n",
        (portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0,
        (portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0,
        (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0);
        if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
        !(portstatus & USB_PORT_STAT_CONNECTION))
        return -1;
        if (portstatus & USB_PORT_STAT_ENABLE) 
        {
            break;
        }
        wait_ms(200);
    }
    if (tries==MAX_TRIES) 
    {
        USB_HUB_PRINTF("Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES);
        USB_HUB_PRINTF("Maybe the USB cable is bad?\n");
        return -1;
    }
    usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET);
    *portstat = portstatus;
    return 0;
}


void usb_hub_port_connect_change(struct usb_device *dev, int port)
{
    struct usb_device *usb;
    struct usb_port_status portsts;
    unsigned short portstatus, portchange;
    /* Check status */
    if (usb_get_port_status(dev, port + 1, &portsts)<0) 
    {
        USB_HUB_PRINTF("get_port_status failed\n");
        return;
    }
    portstatus = swap_16(portsts.wPortStatus);
    portchange = swap_16(portsts.wPortChange);
    USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange,
    portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
    /* Clear the connection change status */
    usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
    /* Disconnect any existing devices under this port */
    if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
    (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) 
    {
        USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");
        /* Return now if nothing is connected */
        if (!(portstatus & USB_PORT_STAT_CONNECTION))
        return;
    }
    wait_ms(200);
    /* Reset the port */
    if (hub_port_reset(dev, port, &portstatus) < 0) 
    {
        USB_HUB_PRINTF("cannot reset port %i!?\n", port + 1);
        return;
    }
    wait_ms(200);
    /* Allocate a new device struct for it */
    usb=usb_alloc_new_device();
    usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
    dev->children[port] = usb;
    usb->parent=dev;
    /* Run it through the hoops (find a driver, etc) */
    if (usb_new_device(usb)) 
    {
        /* Woops, disable the port */
        USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);
        usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
    }
}


int usb_hub_configure(struct usb_device *dev)
{
    unsigned char buffer[USB_BUFSIZ], *bitmap;
    struct usb_hub_descriptor *descriptor;
    struct usb_hub_status *hubsts;
    int i;
    struct usb_hub_device *hub;
    /* "allocate" Hub device */
    hub=usb_hub_allocate();
    if(hub==NULL)
    return -1;
    hub->pusb_dev=dev;
    /* Get the the hub descriptor */
    if (usb_get_hub_descriptor(dev, buffer, 4) < 0) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor, giving up %lX\n",dev->status);
        return -1;
    }
    descriptor = (struct usb_hub_descriptor *)buffer;
    /* silence compiler warning if USB_BUFSIZ is > 256 [= sizeof(char)] */
    i = descriptor->bLength;
    if (i > USB_BUFSIZ) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor - too long: %d\n",
        descriptor->bLength);
        return -1;
    }
    if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\n",dev->status);
        return -1;
    }
    memcpy((unsigned char *)&hub->desc,buffer,descriptor->bLength);
    /* adjust 16bit values */
    hub->desc.wHubCharacteristics=swap_16(descriptor->wHubCharacteristics);
    /* set the bitmap */
    bitmap=(unsigned char *)&hub->desc.DeviceRemovable[0];
    memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* devices not removable by default */
    bitmap=(unsigned char *)&hub->desc.PortPowerCtrlMask[0];
    memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */
    for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) 
    {
        hub->desc.DeviceRemovable[i]=descriptor->DeviceRemovable[i];
    }
    for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) 
    {
        hub->desc.DeviceRemovable[i]=descriptor->PortPowerCtrlMask[i];
    }
    dev->maxchild = descriptor->bNbrPorts;
    USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);
    switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) 
    {
    case 0x00:
        USB_HUB_PRINTF("ganged power switching\n");
        break;
    case 0x01:
        USB_HUB_PRINTF("individual port power switching\n");
        break;
    case 0x02:
    case 0x03:
        USB_HUB_PRINTF("unknown reserved power switching mode\n");
        break;
    }
    if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)
    USB_HUB_PRINTF("part of a compound device\n");
    else
    USB_HUB_PRINTF("standalone hub\n");
    switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) 
    {
    case 0x00:
        USB_HUB_PRINTF("global over-current protection\n");
        break;
    case 0x08:
        USB_HUB_PRINTF("individual port over-current protection\n");
        break;
    case 0x10:
    case 0x18:
        USB_HUB_PRINTF("no over-current protection\n");
        break;
    }
    USB_HUB_PRINTF("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2);
    USB_HUB_PRINTF("hub controller current requirement: %dmA\n", descriptor->bHubContrCurrent);
    for (i = 0; i < dev->maxchild; i++)
    USB_HUB_PRINTF("port %d is%s removable\n", i + 1,
    hub->desc.DeviceRemovable[(i + 1)/8] & (1 << ((i + 1)%8)) ? " not" : "");
    if (sizeof(struct usb_hub_status) > USB_BUFSIZ) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get Status - too long: %d\n",
        descriptor->bLength);
        return -1;
    }
    if (usb_get_hub_status(dev, buffer) < 0) 
    {
        USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",dev->status);
        return -1;
    }
    hubsts = (struct usb_hub_status *)buffer;
    USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n",
    swap_16(hubsts->wHubStatus),swap_16(hubsts->wHubChange));
    USB_HUB_PRINTF("local power source is %s\n",
    (swap_16(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
    USB_HUB_PRINTF("%sover-current condition exists\n",
    (swap_16(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no ");
    usb_hub_power_on(hub);
    for (i = 0; i < dev->maxchild; i++) 
    {
        struct usb_port_status portsts;
        unsigned short portstatus, portchange;
        if (usb_get_port_status(dev, i + 1, &portsts) < 0) 
        {
            USB_HUB_PRINTF("get_port_status failed\n");
            continue;
        }
        portstatus = swap_16(portsts.wPortStatus);
        portchange = swap_16(portsts.wPortChange);
        USB_HUB_PRINTF("Port %d Status %X Change %X\n",i+1,portstatus,portchange);
        if (portchange & USB_PORT_STAT_C_CONNECTION) 
        {
            USB_HUB_PRINTF("port %d connection change\n", i + 1);
            usb_hub_port_connect_change(dev, i);
        }
        if (portchange & USB_PORT_STAT_C_ENABLE) 
        {
            USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus);
            usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
            /* EM interference sometimes causes bad shielded USB devices to
            			 * be shutdown by the hub, this hack enables them again.
            			 * Works at least with mouse driver */
            if (!(portstatus & USB_PORT_STAT_ENABLE) &&
            (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) 
            {
                USB_HUB_PRINTF("already running port %i disabled by hub (EMI?), re-enabling...\n",
                i + 1);
                usb_hub_port_connect_change(dev, i);
            }
        }
        if (portstatus & USB_PORT_STAT_SUSPEND) 
        {
            USB_HUB_PRINTF("port %d suspend change\n", i + 1);
            usb_clear_port_feature(dev, i + 1,  USB_PORT_FEAT_SUSPEND);
        }
        if (portchange & USB_PORT_STAT_C_OVERCURRENT) 
        {
            USB_HUB_PRINTF("port %d over-current change\n", i + 1);
            usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
            usb_hub_power_on(hub);
        }
        if (portchange & USB_PORT_STAT_C_RESET) 
        {
            USB_HUB_PRINTF("port %d reset change\n", i + 1);
            usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
        }
    } 
    /* end for i all ports */
    return 0;
}


int usb_hub_probe(struct usb_device *dev, int ifnum)
{
    struct usb_interface_descriptor *iface;
    struct usb_endpoint_descriptor *ep;
    int ret;
    //s_UartPrint("hub_probe_step1\n");
    iface = &dev->config.if_desc[ifnum];
    /* Is it a hub? */
    if (iface->bInterfaceClass != USB_CLASS_HUB)
    return 0;
    //s_UartPrint("hub_probe_step2\n");
    /* Some hubs have a subclass of 1, which AFAICT according to the */
    /*  specs is not defined, but it works */
    if ((iface->bInterfaceSubClass != 0) &&
    (iface->bInterfaceSubClass != 1))
    return 0;
    //s_UartPrint("hub_probe_step3\n");
    /* Multiple endpoints? What kind of mutant ninja-hub is this? */
    if (iface->bNumEndpoints != 1)
    return 0;
    //s_UartPrint("hub_probe_step4\n");
    ep = &iface->ep_desc[0];
    /* Output endpoint? Curiousier and curiousier.. */
    if (!(ep->bEndpointAddress & USB_DIR_IN))
    return 0;
    //s_UartPrint("hub_probe_step5\n");
    /* If it's not an interrupt endpoint, we'd better punt! */
    if ((ep->bmAttributes & 3) != 3)
    return 0;
    /* We found a hub */
    //s_UartPrint("hub_probe_step6\n");
    USB_HUB_PRINTF("USB hub found\n");
    ret=usb_hub_configure(dev);
    return ret;
}


//#endif /* (CONFIG_COMMANDS & CFG_CMD_USB) */
/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -