usb接口有大,小口之分
usb有主机(host,大口)/设备(otg, 小口)工作模式

usb主机可以主动去操作设备, 主机接口由4根线(vcc, gnd, d+, d-)
usb设备被主机操作, 有5根线(vcc, gnd, d+, d-, id), id线可用于区分设备接口

// otg接口即可作主机角色,也可以作设备的角色

usb接口可以像树型一样的进行扩展, 可用usb hub芯片(FE1.1S, GL850G)将一个usb的硬件接口分成4个硬件接口。

usb设备会在d+, d-这两根上设一个上拉, 当接到usb主机时,usb主机的d+/d-的电平会发生变化

usb的接口协议版本:
usb1.0
usb1.1
usb2.0
usb3.0

usb是高度标准化的接口, usb控制器与usb设备都会有一套标准规范, 以便两者可以互相兼容.
usb设备一般情况下都会有固件, 协同usb控制器的操作.所以有可能在usb设备接入后,需要设备驱动传输固件到设备里执行
/

usb主机控制器(host)和usb设备控制器(otg)的驱动通常由soc厂商负责驱动好, 我们负责的是设备驱动

usb core里面制定好usb主机控制器的驱动接口的实现, 和设备驱动调用控制器驱动的接口
usb主机控制器的版本:
uhci: usb1.x
ohci: usb1.1 (低速1.5Mbps, 全速12Mbps)
ehci: usb2.0 (480Mbps)
xhci: usb3.0
/
查看当前系统下有哪些usb设备及相关的信息:
可用lsusb命令查看, lsusb -vt

// 输出的内容里: bus表示控制器, port表示接在控制上的设备

当一个USB设备没有相应的设备驱动,接上系统时也会知道具体是什么设备,原因:
usb设备里会存放有idVendor, idProduct等信息, 当接入系统时, 内核里的usb子系统会调用usb主机控制器驱动把usb设备的信息读出来, 再根据idVendor, idProduct信息来查找并匹配设备驱动

//在usb设备驱动模型里,不再需要我们描述硬件相关资源的设备. usb子系统会在usb设备接入时自动创建相关的设备信息.

//
/// usb otg驱动 /// 使用设备控制器让我们整个板子做一个USB设备的角色
选择otg驱动:

    make menuconfigDevice Drivers  --->[*] USB support  ---> <*>   USB Gadget Support  ---><M>   USB Gadget Drivers //选择这步后,才可以选择下面的选项<M>     Mass Storage Gadget //通过开发板的设备接口接上PC,会出现u盘(也就是开发板作U盘的角色)<M>     Serial Gadget       //开发板作uart的角色<M>     Printer Gadget      //作打印机角色
保存退出,重编内核并使用新内核镜像启动。
在内核源码的根目录:
    make modules  make modules_install INSTALL_MOD_PATH=/板子网络文件系统的根目录板子上操作:cd /lib/modules/3.4.112/kernel/drivers/usb/gadget/此目录下有: g_mass_storage.ko  g_serial.ko g_webcam.ko可用modinfo查看驱动模块的参数。接上板子的usb的otg线,让板子mmcblk0p7作u盘modprobe g_mass_storage file=/dev/mmcblk0p7  removable=1 echo 2 > /sys/devices/platform/sunxi_usb_udc/otg_role  //让板子的otg接口作设备用.

usb主机接口的设备驱动
在linux内核里通常会有一个结构体来描述一个硬件设备的资源, pci和usb的设备不需我们来描述, usb子系统会在usb设备接入时自动创建对应的结构体信息, 所以我们只要实现设备的驱动就可以了

//usb的设备驱动由usb_driver对象来描述

struct usb_driver {const char *name;int (*probe) (struct usb_interface *intf,const struct usb_device_id *id);void (*disconnect) (struct usb_interface *intf); //相当于前面的remove函数const struct usb_device_id *id_table; //匹配用...
};//usb设备驱动与usb设备的匹配有三种选择:
struct usb_device_id {__u16       match_flags; //用于记录用哪种方法匹配__u16       idVendor; //指定按usb设备的id来匹配__u16       idProduct;...__u8        bDeviceClass; //按设备类型来匹配__u8        bDeviceSubClass;__u8        bDeviceProtocol;__u8        bInterfaceClass; //按接口类型来匹配__u8        bInterfaceSubClass;__u8        bInterfaceProtocol;...
};

struct usb_device 对象表示一个usb设备

一个USB设备里由配置,接口, 端点组成, 一个接口(interface)需要一个usb设备驱动

(endpoint)端点: 用于主机与设备间通信通道。 一个端点只能一个方向。 输入/输出端点

(interface)接口: 一个接口表示USB设备的一种功能, 如一个USB设备有多种功能,则会有多个接口。 端点属于某个接口

(config)配置: 用于设置在某一时刻时USB设备所用的功能,接口需要配置来实现功能。

设备通常有一个或多个配置.
配置常常有一个或多个接口
接口常常有一个或多个设置.
接口有零或多个端点.

///
usb的端点分成4种:
control: 通常用作配置设备或者读取设备信息

INTERRUPT: 中断端点传送小量的数据, 以固定的速率在每次 USB 主请求设备数据时. usb鼠标, 键盘BULK: 块端点传送大量的数据.普遍在打印机, 存储器, 和网络设备上    ISOCHRONOUS: 同步端点也传送大量数据, 但是这个数据常常不被保证它完成. 这些端点用在可以处理数据丢失的设备中, 并且更多依赖于保持持续的数据流. 实时数据收集, 例如音频和视频设备, 一直都使用这些端点

不同类型的设备使用的端点类型也可能不同,但每个USB设备都会有control端点.有些USB设备只有control端点

USB 端点在内核中使用结构 struct usb_host_endpoint 来描述. 这个结构包含真实的端
点信息在另一个结构中, 称为 struct usb_endpoint_descriptor
struct usb_endpoint_descriptor {....__u8  bEndpointAddress; //端点地址, 位掩码USB_DIR_OUT 和 USB_DIR_IN 可用来和这个成员比对__u8  bmAttributes; //这是端点的类型. 位掩码 USB_ENDPOINT_XFERTYPE_MASK 应当用来和这个值比对,来决定这个端点是否是 USB_ENDPOINT_XFER_ISOC, USB_ENDPOINT_XFER_BULK, 或者是类型 USB_ENDPOINT_XFER_INT__le16 wMaxPacketSize; //以字节计的这个端点可一次处理的最大大小__u8  bInterval; //如果这个端点是中断类型的, 这个值是为这个端点设置的间隔, 这个值以毫秒表示...
} __attribute__ ((packed));/////////////////////
USB 接口在内核中使用 struct usb_interface 结构来描述struct usb_interface {struct usb_host_interface *altsetting; //包含所有预备设置的接口结构的数组struct usb_host_interface *cur_altsetting;  //指向数组 altsetting 的一个指针, 表示这个接口当前的激活的设置unsigned num_altsetting;  //由 altsetting 指针指向数组的元素个数int minor;    ...
};///////////
struct usb_host_interface {struct usb_interface_descriptor desc; // desc.bNumEndpoints 表示端点个数struct usb_host_endpoint *endpoint; //端点数组首地址, endpoint[i].desc可取到struct usb_endpoint_descriptor对象的信息
};linux 描述 USB 配置使用结构 struct usb_host_config 和整个 USB 设备使用结构
struct usb_device. USB 设备驱动通常不会需要读写这些结构的任何值, 因此它们在这
里没有详细定义一个 USB 设备驱动通常不得不转换数据从给定的 struct usb_interface 结构到 struct
usb_device 结构, USB 核心需要给很多的函数调用. 为此, 提供有函数
interface_to_usbdev

实验获取usb设备的信息:

去掉内核的usb鼠标,键盘,蓝牙鼠标等的驱动
make menuconfigDevice Drivers  --->[ ] HID Devices  --->
保存后,重编内核,并使用新镜像启动系统。

test.c


#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>int myprobe(struct usb_interface *intf, const struct usb_device_id *id)
{struct usb_host_interface *hintf = intf->cur_altsetting;int n, i;struct usb_host_endpoint *endp;printk("num_alt = %d\n", intf->num_altsetting); n = hintf->desc.bNumEndpoints;endp = hintf->endpoint;printk("endpoints = %d\n", n);for (i = 0; i < n; i++){   printk("endpoint address: %x\n", endp[i].desc.bEndpointAddress);printk("direction : ");if (endp[i].desc.bEndpointAddress & USB_DIR_IN)printk("input\n");elseprintk("output\n");printk("type : ");switch (endp[i].desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK){case USB_ENDPOINT_XFER_ISOC:printk("isoc \n");break;case USB_ENDPOINT_XFER_BULK:printk("bulk \n");break;case USB_ENDPOINT_XFER_INT:printk("int interval = %d\n", endp[i].desc.bInterval);break;case USB_ENDPOINT_XFER_CONTROL:printk("control \n");break;}printk("maxpacketSize = %d\n", endp[i].desc.wMaxPacketSize);}printk("in %s, %d\n", __func__, __LINE__);return 0;
}void mydisconnect(struct usb_interface *intf)
{printk("in %s, %d\n", __func__, __LINE__);
}struct usb_device_id ids[] = {{USB_DEVICE(0x046d, 0xc05a)},  // idVendor=046d, idProduct=c05a  mouse{USB_DEVICE(0x413c, 0x2107)},  // idVendor=413c, idProduct=2107  keyboard{USB_DEVICE(0x0951, 0x1666)},  // idVendor=0951, idProduct=1666  u_disk{},
};struct usb_driver myusb = {.name = "myusb",.probe = myprobe,.disconnect = mydisconnect,.id_table = ids,
};module_usb_driver(myusb);
MODULE_LICENSE("GPL");

///处理usb设备的数据/
linux 内核中的 USB 代码和所有的 USB 设备通讯使用称为 urb 的东西( USB request block)
也就是说所有USB设备要通过USB控制器收发数据需使用urb

1)被一个 USB 设备驱动创建.
2)安排给一个特定 USB 设备的特定端点.
3)提交给 USB 核心, 被 USB 设备驱动.
4)提交给特定设备的被 USB 核心指定的 USB 主机控制器驱动, . // usb_submit_urb(urb, GFP_ATOMIC);
5)被 USB 主机控制器处理, 它做一个 USB 传送到设备.
6)当 urb 完成, USB 主机控制器驱动通知 USB 设备驱动.

struct urb {...struct usb_device *dev;     //指向这个 urb 要发送到的 struct usb_device 的指针unsigned int pipe;      //用于与设备端点通信的通道。不同类型的端点需要用不同的函数来的创建:// usb_sndctrlpipe(...),  usb_rcvctrlpipe, usb_sndbulkpipe, usb_rcvbulkpipe, usb_sndintpipe, usb_rcvintpipe...void *transfer_buffer;  //用于存放发送数据到设备(对一个 OUT urb)或者从设备中获取数据(对于一个 IN
urb)的缓冲区地址u32 transfer_buffer_length; //数据缓冲区的大小u32 actual_length;      //当urb完成后, 在数据缓冲区里实际存放数据的大小...int interval;         //中断端点设备的轮询间隔时间...void *context;        //存放设备数据的缓冲区, 像dev_set_drvdata(...)这样用的数据缓冲区usb_complete_t complete;    //urb传输完成后, 触发的处理函数的地址。函数原型void (*complete)(struct urb *urb)....
};

创建和销毁 urb的函数:

struct urb *usb_alloc_urb(int iso_packets, int mem_flags); //当不是同步端点时,iso_packets为0. mem_flags通常设为GFP_KERNEL.
void usb_free_urb(struct urb *urb);

urb结构体成员较多,内核提供一些函数以方便初始化urb:

//中断端点:
void usb_fill_int_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *transfer_buffer,int buffer_length, usb_complete_t complete,void *context, int interval);//块端点:
void usb_fill_bulk_urb(struct urb *urb, struct usb_device *dev,unsigned int pipe, void *transfer_buffer,int buffer_length, usb_complete_t complete,void *context);//控制端点:
void usb_fill_control_urb(struct urb *urb, struct usb_device *dev,unsigned int pipe, unsigned char *setup_packet,void *transfer_buffer, int buffer_length,usb_complete_t complete, void *context);//同步端点没有直接调用函数,只能一个成员一个成员来初始化:urb->dev = dev;urb->context = uvd;urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);urb->interval = 1;urb->transfer_flags = URB_ISO_ASAP;urb->transfer_buffer = cam->sts_buf[i];urb->complete = konicawc_isoc_irq;urb->number_of_packets = FRAMES_PER_DESC;urb->transfer_buffer_length = FRAMES_PER_DESC;

提交urb, 即让usb控制来传输数据, 当完成后就调用urb里的complete函数.

int usb_submit_urb(struct urb *urb, int mem_flags); // mem_flags通常设为GFP_ATOMIC

//
实验,获取中断端点设备的数据:
test.c


#include <linux/init.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/slab.h>struct urb *myurb;void mycomplete(struct urb *urb)
{int i;unsigned char *data = urb->context; for (i = 0; i < urb->actual_length; i++){printk("%02x ", data[i]);}printk("\n");usb_submit_urb(myurb, GFP_ATOMIC);
}int myprobe(struct usb_interface *intf, const struct usb_device_id *id)
{struct usb_host_interface *hintf = intf->cur_altsetting;int n, i;struct usb_host_endpoint *endp;unsigned int pipe;struct usb_device *dev;unsigned char *buffer;printk("num_alt = %d\n", intf->num_altsetting); n = hintf->desc.bNumEndpoints;endp = hintf->endpoint;printk("endpoints = %d\n", n);
//myurb = usb_alloc_urb(0, GFP_KERNEL);dev = interface_to_usbdev(intf);pipe = usb_rcvintpipe(dev, endp[0].desc.bEndpointAddress);buffer = kzalloc(endp[0].desc.wMaxPacketSize, GFP_KERNEL);usb_fill_int_urb(myurb, dev, pipe, buffer, endp[0].desc.wMaxPacketSize, mycomplete, buffer, endp[0].desc.bInterval);printk("in %s, %d\n", __func__, __LINE__);usb_submit_urb(myurb, GFP_ATOMIC);return 0;
}void mydisconnect(struct usb_interface *intf)
{usb_free_urb(myurb);printk("in %s, %d\n", __func__, __LINE__);
}struct usb_device_id ids[] = {{USB_DEVICE(0x046d, 0xc05a)},  // idVendor=046d, idProduct=c05a  mouse{USB_DEVICE(0x413c, 0x2107)},  // idVendor=413c, idProduct=2107  keyboard{USB_DEVICE(0x0951, 0x1666)},  // idVendor=0951, idProduct=1666  u_disk{},
};struct usb_driver myusb = {.name = "myusb",.probe = myprobe,.disconnect = mydisconnect,.id_table = ids,
};module_usb_driver(myusb);
MODULE_LICENSE("GPL");

另:通常情况下,设备驱动里都是通过urb来获取设备的数据。但有些说法,说不用urb,而通过一些函数来完成工作。

//下面两个函数用于简单的传输数据, 函数内部其实还是创建urb, 提交urb.
usb_bulk_msg 创建一个 USB 块 urb 并且发送它到特定的设备, 接着在返回到调用者之
前等待完成. 它定义为:
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,void *data, int len, int *actual_length,int timeout);usb_control_msg 函数就像 usb_bulk_msg 函数, 除了它允许一个驱动发送和结束 USB
控制信息:
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);

71 linux usb设备驱动相关推荐

  1. Linux usb设备驱动

    原文地址:http://blog.csdn.net/chenjin_zhong/article/details/6329316 1.Linux usb设备驱动框架 USB是通用串行总线的总称,Linu ...

  2. Linux usb设备驱动详解

    1.Linux usb设备驱动框架 USB是通用串行总线的总称,Linux内核几乎支持所有的usb设备,包括键盘,鼠标,打印机,modem,扫描仪.Linux的usb驱动分为主机驱动与gadget驱动 ...

  3. Linux USB设备驱动程序设计 和 USB下载线驱动设计

    Linux USB设备驱动程序设计 和 USB下载线驱动设计 USB设备驱动模型 USB设备包括配置(configuration).接口(interface)和端点(endpoint),一个USB设备 ...

  4. 嵌入式Linux设备驱动程序开发指南20(Linux USB设备驱动)——读书笔记

    Linux USB设备驱动 二十.Linux USB设备驱动 20.1 USB简介 20.1.1 USB2.0总线拓扑 20.1.2 USB总线枚举和设备布局 20.1.3 USB数据传输 20.1. ...

  5. 浅谈Linux USB设备驱动

    1.USB基础介绍 1-1.USB硬件接口介绍 USB接口在硬件上总共有四根线组成VCC.D+.D-.GND,通过计算D+和D-的差值来确定数据.USB设备在传输速率上可以分为低速(1.5Mbps). ...

  6. linux usb驱动 probe,linux USB设备驱动之2:usb设备的probe全过程

    本文将详细讲述2.6.22下的一个USB设备插上linux系统的PC后是如何一步一步调到我们的usb设备驱动的probe函数的,我们知道我们的USB驱动的probe函数中的一个参数是interface ...

  7. Linux usb设备驱动(2)--- usbmouse.c 源码分析

    一个 USB 总线引出两个重要的链表,一个为 USB 设备链表,一个为 USB 驱动链表.设备链表包含各种系统中的 USB 设备以及这些设备的所有接口,驱动链表包含 USB 设备驱动程序(usb de ...

  8. Linux设备驱动之usb设备驱动详解

    原文地址:http://blog.csdn.net/chenjin_zhong/article/details/6329316 1.Linux usb设备驱动框架 USB是通用串行总线的总称,Linu ...

  9. 编写Linux usb 键盘驱动的笔记

    编写linux usb 设备驱动参考:    linux-5.8.5\Documentation\driver-api\usb\writing_usb_driver.rst    linux-5.8. ...

最新文章

  1. 关于ASP.NET Web 部件连接的引入
  2. PHP strlen()函数和strpos()函数
  3. 红色警报 (25 分)【测试点分析】【两种解法】
  4. 再会迪杰斯特拉(Dijkstra)
  5. python bytes转换为string_Python3 中 bytes 和 string 之间的互相转换
  6. Redis面试 - redis 的并发竞争问题是什么?
  7. 基础知识(十四)服务器搭建
  8. 冲刺一阶段———个人总结08
  9. selenium系列--测试脚本--将Excel文件用于测试(unittest数据驱动实战)
  10. Mac OSX终极瘦身
  11. 实用:Google Chrome(谷歌浏览器)键盘快捷键大全
  12. 生物信息学常用的在线网站及数据库汇总
  13. uniAPP上架iOS商店踩到的坑(记录)
  14. python的tesseract库几个重要的命令
  15. MySQL 数据类型(转)
  16. 深圳易商网怎样轻松搞定网站SEO优化?
  17. python分组统计数据_数据分组统计
  18. 把三层交换机当成普通交换机来用
  19. css实现多行文本溢出显示省略号(…)全攻略
  20. SAGI GAMES 创始人曾嵘:瞄准休闲游戏,将“创意”转化为“商业”

热门文章

  1. kali忘记登陆密码解决方法
  2. Web技术(Java)初学+制作学期课程表
  3. java 修改pdf_Java 操作PDF书签详解 - 添加、修改、读取和删除
  4. cfa等级考试计算机,CFA考试计算器要求和设置
  5. 网络史话 因特网简史
  6. 60个项目管理甘特图模板,可编辑,可下载
  7. 从中关村到纳斯达克,龚宇的奇异8年与爱奇艺的全新时代
  8. android 环形时间显示_Android自定义波浪加载圆形进度条——(自定义控件 一)...
  9. 关于jsp嵌入flash
  10. ansys仿真论文描述