USB驱动(一、概念介绍及USB总线驱动程序代码分析)

USB驱动程序分为两个层次
(1) USB总线驱动=》系统自带的;
USB总线驱动程序负责:
识别USB设备,给USB设备找到对应的驱动程序。
USB总线驱动程序作用:
a.识别USB设备;
b.查找并安装对应的设备驱动程序;
c.提供USB读写函数。不了解数据含义。
USB总线驱动程序可以通过调用libUSB(libUSB封装了端口函数)跳过USB设备驱动程序,来访问USB设备。
(2) 设备驱动=》需要我们自己编写;
设备驱动知道数据含义。
PC和USB设备都遵守一定的规范。
USB设备接入电脑后,USB总线驱动程序会发出某些命令来获取设备信息(描述符);
USB设备必须返回“描述符”给PC。
USB接口只有4条线:5V,GND,D+,D-。
每一个USB设备接入PC时,USB总线驱动程序都会给他分配一个编号;
接在USB总线上的每一个USB设备都有自己的编号(地址);
PC机想访问某个USB设备时,发出的命令都含有对应的编号(地址)。
新接入的USB 设备的默认编号是0,在未分配新编号前,PC使用0编号和它通信。
为了快速识别硬件,在USB主机上的D+和D-一般都会接15k的下拉电阻,而在USB从机上的D+和D-都会接1.5K的上拉电阻。
这里写图片描述
这里写图片描述
这里写图片描述
USB主机控制器,USB总线驱动程序是来支持USB主机控制器,也可以看做是USB总线驱动程序是USB主机控制器驱动程序,USB主机控制器下接有USB设备,设备驱动程序用来支持USB设备,为了能够访问USB设备,设备驱动程序必须调用USB总线驱动程序提供的函数,把那些命令、包,发给USB主机控制器,由USB主机控制器产生的信号发给USB设备。
USB驱动程序框架
插入和拔出USB设备后,会看到输出信息:
usb 1-1 :new full speed USB device using s3c2410-ohci and address 2
在系统的内核中查找
USB device using (grep “USB device using” * -nR),
发现在device /usb/core/hub.c :2186:
“%s %s speed %sUSB device using %s and address %d\n”,

每一个USB主机控制器内部都自带一个USB hub,可以认为hub为特殊的USB控制器。
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述
这里写图片描述

static void hub_irq(struct urb *urb)
{
......
kick_khubd(hub);
......
}/*主机控制器产生的中断,不是USB设备产生的中断*/
static void kick_khubd(struct usb_hub *hub)
{
    unsigned long   flags;

    /* Suppress autosuspend until khubd runs */
    to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;

    spin_lock_irqsave(&hub_event_lock, flags);
    if (list_empty(&hub->event_list)) {
        list_add_tail(&hub->event_list, &hub_event_list);
        wake_up(&khubd_wait);/*唤醒队列*/
    }
    spin_unlock_irqrestore(&hub_event_lock, flags);
}
static int hub_thread(void *__unused)
{
    do {
        hub_events();
        wait_event_interruptible(khubd_wait,
                !list_empty(&hub_event_list) ||
                kthread_should_stop());/*hub 线程一般是在这个队列里面休眠,*/
        try_to_freeze();
    } while (!kthread_should_stop() || !list_empty(&hub_event_list));

    pr_debug("%s: khubd exiting\n", usbcore_name);
    return 0;
}
static void hub_events(void)
.......
if (connect_change)
                hub_port_connect_change(hub, i,
                        portstatus, portchange);
                        ........
static void hub_port_connect_change(struct usb_hub *hub, int port1,
                    u16 portstatus, u16 portchange)
{
......
udev = usb_alloc_dev(hdev, hdev->bus, port1);
......
/* set the address */
        choose_address(udev);/*给新设备分配地址*/
......
status = hub_port_init(hub, udev, port1, i);
......
status = usb_new_device(udev);
......
}

在linux/device/usb/core/Usb.c下

usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
{
......
dev->dev.bus = &usb_bus_type;
......
}

在F:\linux-2.6.22.6\drivers\usb\core\driver.c下

struct bus_type usb_bus_type = {
    .name =     "usb",
    .match =    usb_device_match,
    .uevent =   usb_uevent,
    .suspend =  usb_suspend,
    .resume =   usb_resume,
};

在F:\linux-2.6.22.6\drivers\usb\core\driver.c下

static int usb_device_match(struct device *dev, struct device_driver *drv)
{
.......
id = usb_match_dynamic_id(intf, usb_drv);
/*在usb_driver里面会有一个probe函数*/

.......
}
    hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        int retry_counter)
        {
        .....
    dev_info (&udev->dev,
          "%s %s speed %sUSB device using %s and address %d\n",
          (udev->config) ? "reset" : "new", speed, type,
          udev->bus->controller->driver->name, udev->devnum);
......
retval = hub_set_address(udev);/*把编号(或地址)告诉给USB设备*/
......
retval = usb_get_device_descriptor(udev, 8);
/*获取设备描述符,此时获得的是8个字节的,linux/include/linux/usb/ch9.h下usb_device_descriptor结构体中 */
......

    retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
......
          }

在linux/include/linux/usb/ch9.h下


/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor {
    __u8  bLength;
    __u8  bDescriptorType;

    __le16 bcdUSB;
    __u8  bDeviceClass;
    __u8  bDeviceSubClass;
    __u8  bDeviceProtocol;
    __u8  bMaxPacketSize0;
    __le16 idVendor;
    __le16 idProduct;
    __le16 bcdDevice;
    __u8  iManufacturer;
    __u8  iProduct;
    __u8  iSerialNumber;
    __u8  bNumConfigurations;
} __attribute__ ((packed));
int usb_new_device(struct usb_device *udev)
{
......
err = usb_get_configuration(udev);/*把所有的配置读取出来并解析*/
......
err = device_add(&udev->dev);
......
}

在linux/device/usb/core/Config.c下

int usb_get_configuration(struct usb_device *dev)
{
......
result = usb_parse_configuration(&dev->dev, cfgno,
            &dev->config[cfgno], bigbuffer, length);
            /*解析配置信息*/
            .......
}
  • 4
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值