当前位置: 首页 > article >正文

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);/*解析配置信息*/.......
}
http://www.lryc.cn/news/2414602.html

相关文章:

  • element日期选择器datepicker用法大全
  • UCOS-III 操作系统深度剖析与实战应用教程
  • Arrays.sort()的用法
  • 滚动条样式锦集
  • 2024年最新网络安全行业名词_失陷主机(1)
  • 前端入门之HTML与CSS
  • uaa认证服务流程
  • 认识headers
  • 揭秘Android Tombstone:崩溃位置的秘密研究-Crash Location
  • 使用ShellExecute函数实现以管理员身份运行程序
  • 常用配置文件-ini文件
  • JAVA静态变量是什么
  • 最短路径算法汇总
  • Java 快速入门指南
  • PLSQL Developer(安装、连接、汉化、注册图文教程)
  • 创建ROS消息(msg)和服务(srv)
  • 当你在浏览器输入www.xxx.com的时候会发生什么?
  • TLE两行轨道根数
  • QFAV——快速免费拼装你的视频会议
  • ubuntu 安装中文输入法(超简靠谱版)
  • 带宽是什么?
  • Java数字格式类 NumberFormat | DecimalFormat
  • rides介绍和安装
  • java web报表,jasperReport使用简介
  • git 某个分支代码回滚到某次push的步骤
  • 什么是线程安全和非线程安全
  • Java04方法
  • SFR解析算法 - SFR_Calculation (C语言)
  • Fiddler 4 安卓APP抓包教程
  • 施密特正交化(Gram-Schmidt Orthogonalization)