天天看點

Linux USB子系統

參考文章:

USB底層協定

相關資料如下:

//這裡資料成員并沒有完全列出
struct usb_device{                      //usb裝置
    struct device dev;
    char        devpath[];
    u8 portnum;
    struct usb_host_endpoint ep0;
    struct usb_host_endpoint *ep_in[];
    struct usb_host_endpoint *ep_out[];
    struct usb_bus *bus;
    struct usb_device *parent;
    struct list_head filelist;  
};
struct usb_host_endpoint{               //usb端點
    struct usb_endpoint_descriptor      desc;
    struct list_head        urb_list;
    void                *hcpriv;
}
struct usb_hcd{                         //usb主機控制器驅動
    struct usb_bus      self;           //usb主機控制器對應的usb總線
    struct kref         kref;           //引用計數
};
struct usb_bus{                         //usb總線
    struct device *controller;      /* host/master side hardware */
    int busnum; 
};
struct usb_ctrlrequest{             //usb 控制請求
    //bit7:data transaction 階段的方向bit6-bit5:request type bit1-bit0:請求針對是裝置,接口還是端點
     bRequestType;
     bRequest;
    le16 wValue;
    le16 wIndex;
    le16 wLength;
}attribute((packed));
           
static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus)
{
    return container_of(bus, struct usb_hcd, self);
}
//增加usb主機控制器的引用計數
struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
{
    if (hcd)
        kref_get (&hcd->kref);
    return hcd;
}
           
struct usb_device *usb_alloc_dev(struct usb_device *parent, \
                                            struct usb_bus *bus,        \
                                            unsigned portl)
{
    struct usb_device *dev;
    dev = kzalloc(sizeof(*dev),GFP_KERNEL);

    if(!usb_get_hcd(bus_to_hcd(bus))){};

    device_initialize(&dev->dev);
    dev->dev.bus = & usb_bus_type;//總線類型
    dev->dev.type = & usb_device_type;
    dev->dev.dma_mask = bus->controller->dma_mask;
    dev->state = USB_STATE_ATTACHED;

    INIT_LIST_HEAD(&dev->ep0.urb_list);
    dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
    dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
    dev->ep_in[] = dev->ep_out[] = &dev->ep0;

    if (unlikely(!parent)) {//根集線器與
        dev->devpath[] = '';
        dev->dev.parent = bus->controller;
        sprintf(dev->dev.bus_id,"usb%d",bus->busnum);
    }
    else{
        if (parent->devpath[] == '') {  //插在根集線器
            snprintf(dev->devpath, sizeof dev->devpath,
                "%d", port1);
        }else{
            snprintf(dev->devpath, sizeof dev->devpath,
                "%s.%d", parent->devpath, port1);
        }
        dev->dev.parent = &parent->dev;
        sprintf(dev->dev.bus_id[],"%d-%s",bus->busnum,dev->devpath);
    }
    dev->portnum = port1;
    dev->bus = bus;
    dev->parent = parent;
    INIT_LIST_HEAD(&dev->filelist);
    //電源管理暫時忽略
    return dev;
}
           

裝置連接配接上之後hub設定狀态(Powered),hub會發出reset信号,複位usb裝置使其進入Default狀态。這是hub會獲得裝置的速度與端點0的處理的最大資料長度,對于高速時64位元組,對于低速8 位元組全速是8,16,32,64中的一個。此時開始設定位址。給裝置發出SET_ADDRESS請求調用函數usb_control_msg

int usb_control_msg(struct usb_device *dev,unsigned pipe,__u8 request \
                        __u8 requesttype,__u16 value,__u16 index,\
                        void *data,__u16 size,int timeout)
{
    struct usb_ctrlrequest *dr;

    dr = kmalloc(sizeof(struct usb_ctrlrequest),GFP_NOIO);

    dr->bRequestType = requesttype;
    dr->bRequest = request;
    dr->wValue = cpu_to_le16(value);
    dr->wIndex = cpu_to_le16(index);
    dr->wLength = cpu_to_le16(size);

    ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);

    kfree(dr);

    return ret;
}
           

繼續閱讀