11-Linux usb system(driver)

题图:gratisography

Linux usb system(driver)

USB的应用用来用广泛了,键盘、鼠标、打印机、摄像头、网卡...而且传输的速度也越来越快,USB2.0的480MB/s,到USB3.0已经是USB2.0的十倍了。Linux中USB的内容实在是太多了,有兴趣的可以查看《Linux那些事兒之我是USB》这本书,这边对USB的驱动进行简要的说明和总结。

还是先看一下框架图,如下:

USB框架

由图可知USB驱动的各个层次:

  • USB主机控制器,位于/drivers/usb/host/下面,USB主机控制器接口标准有OHCI/UHCI/EHCI/XHCI等,对于嵌入式设备一般使用OHCI和XHCI。
  • USB Core位于/drivers/usb/core/下,该层由内核实现,里面包含了最主要的功能,为设备驱动和主机控制器提供编程接口,各种功能组件的描述操作,设备热拔插、总线数据传输等。
  • 设备驱动是按USB接口来实现,一个interface对应一个driver,一般通用的USB设备,如U盘、USB鼠标等都不需要再进行驱动编写,需要编写的是特定厂商、特定芯片的驱动。
  • 在设备驱动的上面还有一层,用来对应特定的功能驱动,该部分在设备驱动probe的时候实现。如USB网卡,则需要Net层的驱动;USB视频接口,则需要video层的驱动;USB键盘接口,则需要 input_dev层的驱动。

1.控制器驱动

控制器驱动使用的还是platform总线进行的,platform_device位于arch或dts里,如下:

static struct resource comcerto_usb3_resource[] = {
        [0] = {
                .start  = COMCERTO_AXI_USB3P0_BASE,
                .end    = COMCERTO_AXI_USB3P0_BASE + SZ_8M - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
                .start  = IRQ_USB3,
                .end    = IRQ_USB3,
                .flags  = IORESOURCE_IRQ,
        },
};

static u64 comcerto_usb3_dmamask = 0xfffff000;

struct platform_device comcerto_device_usb3 = {
        .name           = "xhci-hcd",
        .id             = -1,
        .resource       = comcerto_usb3_resource,
        .num_resources  = ARRAY_SIZE(comcerto_usb3_resource),
        .dev            = {
                .dma_mask               = &comcerto_usb3_dmamask,
                .coherent_dma_mask      = DMA_BIT_MASK(32),
        },
};
#endif

platform_driver位于/drivers/usb/host/里面,但是要看使用的是哪一种接口OHCI/XHCI,然后在对应的接口平台里面进行platform_driver的注册,如下:

static struct platform_driver usb_xhci_driver = {
    .probe  = xhci_plat_probe,
    .remove = xhci_plat_remove,
    .driver = {
        .name = "xhci-hcd",
    },
};
MODULE_ALIAS("platform:xhci-hcd");

int xhci_register_plat(void)
{
    return platform_driver_register(&usb_xhci_driver);
}

void xhci_unregister_plat(void)
{
    platform_driver_unregister(&usb_xhci_driver);
}

probe函数会有很多关于hcd的操作,如usb_create_hcd()usb_add_hcd()usb_remove_hcd()等,hcd是主机控制器的驱动程序,它位于USB主机控制器与USB系统软件之间。内核使用usb_hcd结构体描述USB主机控制器驱动,一个USB控制器的实现者必须提供一个支持它自己的控制器的主机控制器驱动器(HCD)实现。

2.设备器驱动

USB设备驱动的注册和卸载使用usb_registerusb_deregister,如下是键盘的设备驱动:

static struct usb_driver usb_kbd_driver = {
    .name =     "usbkbd",
    .probe =    usb_kbd_probe,
    .disconnect =   usb_kbd_disconnect,
    .id_table = usb_kbd_id_table,
};

static int __init usb_kbd_init(void)
{
    int result = usb_register(&usb_kbd_driver);
    if (result == 0)
        printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
                DRIVER_DESC "\n");
    return result;
}

static void __exit usb_kbd_exit(void)
{
    usb_deregister(&usb_kbd_driver);
}

module_init(usb_kbd_init);
module_exit(usb_kbd_exit);

usb_driver最主要的就是probe()disconnect()两个函数。

disconnect()里面的处理比较简单,就是对应设备的卸载,这边说下probe()函数:

上面说过一个接口对应一个驱动,USB数据的传输是通过端点endpoint实现的,连接端点需要pipe通道,所以probe()函数的入口一定是usb_interface,函数里面需要对interface、endpoint、usb_rcvintpipe进行处理;

USB接口的上层也要有对应的接口设备,这边是键盘,输入input设备,所以需要input_dev设备的处理,使用input_register_device()进行注册,使用input_unregister_device()进行卸载。

这边大概看下usb_interface结构体,位于/include/linux/usb.h

struct usb_interface {
    /* array of alternate settings for this interface,
     * stored in no particular order */
    struct usb_host_interface *altsetting;

    struct usb_host_interface *cur_altsetting;  /* the currently
                     * active alternate setting */
    unsigned num_altsetting;    /* number of alternate settings */

    ...

    struct device dev;      /* interface specific device info */
    struct device *usb_dev;
    atomic_t pm_usage_cnt;      /* usage counter for autosuspend */
    struct work_struct reset_ws;    /* for resets in atomic context */
}

里面包含usb_host_interface结构体,位于/include/linux/usb.h

struct usb_host_interface {
    struct usb_interface_descriptor desc;

    /* array of desc.bNumEndpoint endpoints associated with this
     * interface setting.  these will be in no particular order.
     */
    struct usb_host_endpoint *endpoint;

    char *string;       /* iInterface string, if present */
    unsigned char *extra;   /* Extra descriptors */
    int extralen;
};

里面包含usb_interface_descriptorusb_host_endpoint结构体,位于/include/linux/usb.h

struct usb_host_endpoint {
    struct usb_endpoint_descriptor      desc;
    struct usb_ss_ep_comp_descriptor    ss_ep_comp;
    struct list_head        urb_list;
    void                *hcpriv;
    struct ep_device        *ep_dev;    /* For sysfs info */

    unsigned char *extra;   /* Extra descriptors */
    int extralen;
    int enabled;
};

里面包含usb_endpoint_descriptor结构体,所以一个设备驱动下面会包含interface和endpoint的所有信息。

usb_host_endpoint下面有一个成员urb_list,这边就又引入了urb一个知识点,这边先不做介绍,后期进行学习整理后在进行介绍。

几个常用USB设备的驱动所在位置:

  • U盘的驱动位于/drivers/usb/storage/下;
  • USB键盘和鼠标的驱动位于/drivers/hid/usbhid/下;
  • USB打印机的驱动位于/drivers/usb/class/usblp.c下;

Linux usb system(driver)的分析就到这边,有感悟时会持续会更新。

注:以上内容都是本人在学习过程积累的一些心得,难免会有参考到其他文章的一些知识,如有侵权,请及时通知我,我将及时删除或标注内容出处,如有错误之处也请指出,进行探讨学习。文章只是起一个引导作用,详细的数据解析内容还请查看Linux相关教程,感谢您的查阅。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容