转自http://blog.csdn.net/aaronychen/article/details/3555885
前段时间写了篇<qualcomm usb modem驱动小结>的文章,描述了自己如何为高通的一个usb modem设备写驱动的过程,最近发现实际上可以使用Linux自带的一个叫usbserial的模块作为这个modem的驱动并能良好的工作,所以写了这片文章来详细的分析下usbserial模块的源码(2.6.16.3).
应该来说,对于那些仅仅是用USB来通信,在上层可看作tty设备,不属于任何USB设备类型,没有什么流控等的普通USB设备来说都可以使用这个驱动来作为设备驱动程序.下面就来对这样一种通用的驱动程序来进行详细的分析.不对之处敬请指正!
为了能让usbserail模块支持我的设备,我必须在命令行上输入如下命令:
sudo modprobe usbserial vendor=0x12d1 product=0x1003
该命令用特权用户来加载usbserial模块,并把该模块依赖的模块一并加载进系统,同时它还设置了usbserial的两个参数: vendor, product, 很显然这两个参数是厂商ID和设备ID,而作用就是用于匹配设备.
首先,当然是要知道usbserial模块由哪些文件编译而成,这样才能有目的性的去分析其代码.而要知道其组成当然是去其目录下看Makefile了, 它位于内核源码目录下的./drivers/usb/serial/下
./drivers/usb/serial/Makefile:
#
# Makefile for the USB serial device drivers.
#
# Object file lists.
obj-$(CONFIG_USB_SERIAL) += usbserial.o #编译内核时如何编译该模块
usbserial-obj-$(CONFIG_USB_SERIAL_CONSOLE) += console.o
usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o
usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) #OK,就是usbserial模块的组成了.
obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o
obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o
.......
我们重点看的是usb-serial.c, generic.c, bus.c
在看源码之前我们先说说该模块的原理及整体结构:
很简单跟应用层交互的是一个tty设备,也就是说该模块把USB设备映射成一个tty设备(即在/dev/目录下为该USB设备创建一个tty设备文件),然后用于可以用minicom之类的串口工具来打开这个设备,并同设备端的设备通信.
对于发送过程: tty设备文件在获取了用户要求发送的数据之后传递到下层usbserial模块的核心层,而该核心层就是将数据打包成USB格式的数据并由USB通信发送到设备端去,
对于接收过程: usbserial模块会在该设备打开时就启动一个urb在那等待设备端发数据过来,收到数据后就push到上层tty设备的缓冲中去,而tty设备在收到数据后就会给用户,或直接显示在minicom之类的工具上.
usb-serial.c就是usbserial模块的核心,它主要用来接收设备端发来的数据并传送到上层,同时也接收来自上层应用的数据,并组装成urb包发送给设备.
generic.c对特定设备单独的操作,相当于是设备自己的驱动程序,由于很多设备具有通用性,所以对于没有特殊要求的设备都可以使用这个驱动来作为自己设备的驱动程序.它有两个参数vendor和product,上面提过了.
bus.c 每个usb驱动和设备都必须要归入某一条总线上,即都是归属于某条总线的,只有这样系统才能从特定一条总线开始找到每个驱动和设备并为他们匹配.这个文件就是用来模拟一条总线,而usbserial的每个驱动和设备都会注册到这条总线上来.