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

📄 usb.c

📁 看到最近大家都关心 usbhost 的实现, 论坛上能找到的代码仅是一些简单的 demo , 完整的源码级的协议层是找不到的 我就贡献一把, 将我前一段时间移植成功的 USBHost 代码奉上 注
💻 C
📖 第 1 页 / 共 3 页
字号:
    { usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial)); }

    /* now prode if the device is a hub */
    usb_hub_probe(dev,0);
    return 0;
}


/* 创建设备目录  */
void usb_scan_devices(void)
{int i;
struct usb_device *dev;
    
    /* 首先标记所有设备为未知设备 */
    for(i=0; i<USB_MAX_DEVICE; i++) 
    { memset(&usb_dev[i], 0, sizeof(struct usb_device));
      usb_dev[i].devnum = -1;
    }
    
    usb_device_clear_all();

    /* 设备0 作为根hub设备一直存在*/    
    dev = usb_alloc_new_device();
    
    usb_new_device(dev);

    /* insert "driver" if possible */
}


/****************************************************************************
 * HUB "Driver"
 * Probes device for being a hub and configurate it
 */


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 */
    for (i = 0; i < dev->maxchild; i++) 
    {
        usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);

        os_dly_wait(hub->desc.bPwrOn2PwrGood * 2 / 10);
    }
}


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++];
    }
    
    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;
    
    /* 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);
      os_dly_wait(20);
      
      if(usb_get_port_status(dev, port + 1, &portsts) < 0) 
      { return -1;  /* get_port_status failed status %lX\n",dev->status); */
      }
      
      portstatus = swap_16(portsts.wPortStatus);
      portchange = swap_16(portsts.wPortChange);
      
      if((portchange & USB_PORT_STAT_C_CONNECTION) ||
         !(portstatus & USB_PORT_STAT_CONNECTION))
      { return -1;  }

      if (portstatus & USB_PORT_STAT_ENABLE) 
      { break;
      }
      os_dly_wait(20);
    }
    
    if (tries == MAX_TRIES) 
    { /* Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES);
         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_device_remove(struct usb_device *dev)
{unsigned char i;
    for(i=0; i<USB_MAXCHILDREN; i++)
    { if(dev->children[i])
      { usb_device_remove(dev->children[i]); }
    }
    
    memset(dev, 0, sizeof(struct usb_device));
    dev->devnum = -1;
}

struct usb_device * usb_device_find(int devnum)
{ unsigned char i;
struct usb_device *dev;

    for(i=0; i<USB_MAX_DEVICE; i++) 
    { dev = usb_get_dev_index(i);
      
      if(dev == NULL)
      { continue;     }

      if(dev->devnum == devnum)
      { return dev;   }
    }
    return NULL;
}

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) 
    { return;   /* get_port_status failed */
    }
    
    portstatus = swap_16(portsts.wPortStatus);
    //portchange = swap_16(portsts.wPortChange);
       
    /* 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])) 
    { /* Return now if nothing is connected */
      
      usb_device_remove(dev->children[port]);

      if (!(portstatus & USB_PORT_STAT_CONNECTION))  return;
    }
    os_dly_wait(20);
    
    /* Reset the port */
    if(hub_port_reset(dev, port, &portstatus) < 0)
    { return;   /* cannot reset port %i!?\n", port + 1); */
    }
    os_dly_wait(20);
    
    /* 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 */
      /* 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) 
    { 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)
    { return -1;  /* usb_hub_configure: failed to get hub descriptor - too long: %d\n", descriptor->bLength */
    }
    
    if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) 
    { return -1;  /* usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\n",dev->status  */
    }

    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;
   
    switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) {
    case 0x00:      /* ganged power switching! */
      break;
    case 0x01:      /* individual port power switching! */
      break;
    case 0x02:
    case 0x03:
      break;        /* unknown reserved power switching mode! */
    }

    if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)
    { /* part of a compound device! */    
    }
    else
    { /* standalone hub */
    }

    switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) {
    case 0x00:    /* global over-current protection! */
      break;
    case 0x08:    /* individual port over-current protection! */
      break;
    case 0x10:
    case 0x18:
      break;      /* no over-current protection! */
    }
    
    /* power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2); */
    /* 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_configure: failed to get Status - too long: %d\n", descriptor->bLength); */
      return -1;
    }
    if (usb_get_hub_status(dev, buffer) < 0) 
    { /* 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) 
      { continue;   /* get_port_status failed! */
      }
      portstatus = swap_16(portsts.wPortStatus);
      portchange = swap_16(portsts.wPortChange);
      
      /* Port %d Status %X Change %X\n",i+1,portstatus,portchange); */
      
      if (portchange & USB_PORT_STAT_C_CONNECTION) 
      { 
        usb_hub_port_connect_change(dev, i);
      }
      
      if (portchange & USB_PORT_STAT_C_ENABLE) 
      { 
        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_port_connect_change(dev, i);
        }
      }

      if (portstatus & USB_PORT_STAT_SUSPEND) 
      { 
        usb_clear_port_feature(dev, i + 1,  USB_PORT_FEAT_SUSPEND);
      }
      
      if (portchange & USB_PORT_STAT_C_OVERCURRENT) 
      { 
        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_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;
    
    iface = &dev->config.if_desc[ifnum];
    /* Is it a hub? */
    if (iface->bInterfaceClass != USB_CLASS_HUB)
    { return 0; }
    
    /* 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; }
    
    /* Multiple endpoints? What kind of mutant ninja-hub is this? */
    if (iface->bNumEndpoints != 1)
    { return 0; }
    
    ep = &iface->ep_desc[0];
    /* Output endpoint? Curiousier and curiousier.. */
    if (!(ep->bEndpointAddress & USB_DIR_IN))
    { return 0; }
    
    /* If it's not an interrupt endpoint, we'd better punt! */
    if ((ep->bmAttributes & 3) != 3)
    { return 0; }
    
    
    /* We found a hub */
    ret = usb_hub_configure(dev);
    return ret;
}


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

⌨️ 快捷键说明

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