重要文件由usb-serial.c ; generic.c ; usb.c ; option.c
从module_init(usb_serial_init)开始
//按照tty驱动结构,先创建"tty_driver"对象
alloc_tty_driver(SERIAL_TTY_MINIOR)
注册总线usb-serial,之后很多驱动及设备都会注册到该总线上
bus_register(&usb_serial_bus_type)
关于
struct bus_type usb_serial_bus_type = {
.name = "usb-serial",
.match = usb_serial_device_match,
.probe = usb_serial_device_probe,
.remove = usb_serial_device_remove,
.drv_attrs = drv_attrs,
};
??为什么没有注册这个总线设备,device_register(usb_serial_bus)??
初始化tty_driver对象
usb_serial_tty_driver->name=..
.
.
.
设置tty_driver的操作函数fops
tty_set_operation(usb_serial_tty_driver,&serial_ops)
向tty核心注册tty驱动
tty_register_driver(usb_serial_tty_driver)
将usb_serial_driver驱动注册到usb总线上
usb_register(usb_serial_driver)
关于usb_serial_driver
static struct usb_driver usb_serial_driver = {
.name = "usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.suspend = usb_serial_suspend,
.resume = usb_serial_resume,
.no_dynamic_id = 1,
};
最后注册generic驱动
usb_serial_generic_register(debug)
分析usb_serial_generic_register(debug)
保存idVendor generic_device_ids[0].idVendor=vendor
保存idProduct generic_device_ids[0].idProduct=idProduct
匹配类型generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
将usb_serial_generic_device结构体(未知是驱动结构体还是设备结构体)注册到usb-serial总线上
usb_serial_register(&usb_serial_generic_device)
关于usb_serial_generic_device
struct usb_serial_driver usb_serial_generic_device = {
.driver = {
.owner = THIS_MODULE,
.name = "generic",
},
.id_table = generic_device_ids,
.usb_driver = &generic_driver,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
.shutdown = usb_serial_generic_shutdown,
.throttle = usb_serial_generic_throttle,
.unthrottle = usb_serial_generic_unthrottle,
.resume = usb_serial_generic_resume,
};
其中,usb_serial_driver是新定义的驱动结构体
将"generic_driver"注册到usb总线上,目的是当设备插入系统后,通过generic_driver的generic_probe
来匹配设备。因此。已经注册了两个驱动进了usb总线
usb_register(&generic_driver)
关于generic_driver结构体
static struct usb_driver generic_driver = {
.name = "usbserial_generic", //驱动名称
.probe = generic_probe, //重要的匹配函数
.disconnect = usb_serial_disconnect,
.id_table = generic_serial_ids, //无用
.no_dynamic_id = 1, //不支持动态匹配
};
函数 usb_serial_generic_register(int _debug)已经整体分析完,下面分析该函数里面的usb_serial_register函数
为usb_serial_driver添加新的操作功能(open,write,close,....)
fixup_generic(struct usb_serial_driver* device)
将usb_serial_driver添加到usb-serial总线上的驱动列表usb_serial_driver_list上
list_add(&driver->driver_list, &usb_serial_driver_list);
注册驱动到usb-serial总线上
usb_serial_bus_register(driver)
?????????????在usb总线上注册了两个驱动"usbserial"和"usbserial_generic",那么当插入设备的时候
究竟是匹配哪一个驱动呢???????????????????????
现在似乎usb-serial总线和usb总线没有什么联系,好,那么就看generic_probe函数
id_pattern = usb_match_id(interface, generic_device_ids)
初步匹配
if (id_pattern != NULL)
return usb_serial_probe(interface, id);
继续匹配,寻找和其匹配的驱动
usb中的probe函数的工作
1.初始化用于控制usb设备的局部结构体
2.探测端点类型
3.保存相关局部结构体的信息
4.把设备注册到USB核心,以便与用户程序监护信息
另外一个匹配函数usn_serial_probe出场了
int usb_serial_probe(struct usb_interface *interface,const struct usb_device_id *id)
type = search_serial_device(interface);
获取该设备匹配的驱动,"struct usb_serial_driver* type"
获取到设备之后,为该设备创建一个"usb_serial"对象
serial = create_serial (dev, interface, type)
(一般的驱动程序都会为自己匹配设备创建一个用于描述设备的对象,在以后的所有操作中,
如读写等都会直接从这个对象获取相应的信息)
iface_desc = interface->cur_altsetting //获取设备接口的当前设置
endpoint = &iface_desc->endpoint[i].desc
检查当前接口的端点类型,并保存,对于usb_serial_generic设备,常见的端点类型为bulkin和bulkout
port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL)
用struct usb_serial_port来描述一个tty端口,因为每个端口都有自己的工作模式
关于 struct usb_serial_port
struct usb_serial_port {
struct usb_serial *serial;
struct tty_struct *tty;
spinlock_t lock;
struct mutex mutex;
unsigned char number;
unsigned char *interrupt_in_buffer;
struct urb *interrupt_in_urb;
__u8 interrupt_in_endpointAddress;
unsigned char *interrupt_out_buffer;
int interrupt_out_size;
struct urb *interrupt_out_urb;
__u8 interrupt_out_endpointAddress;
unsigned char *bulk_in_buffer;
int bulk_in_size;
struct urb *read_urb;
__u8 bulk_in_endpointAddress;
unsigned char *bulk_out_buffer;
int bulk_out_size;
struct urb *write_urb;
int write_urb_busy;
__u8 bulk_out_endpointAddress;
wait_queue_head_t write_wait;
struct work_struct work;
int open_count;
char throttled;
char throttle_req;
char console;
struct device dev;
};
port->serial = serial
将usb_serial对象保存到usb_serial_port中,便于通过port来访问serial
初始化bulk_in端点,保存到"usb_serial_port"(port对象中)
for (i = 0; i < num_bulk_in; ++i) {
endpoint = bulk_in_endpoint[i];
port = serial->port[i];
port->read_urb = usb_alloc_urb (0, GFP_KERNEL);//分配urb
if (!port->read_urb) {
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
}
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->bulk_in_size = buffer_size;
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);//创建DMA缓冲区
if (!port->bulk_in_buffer) {
dev_err(&interface->dev, "Couldn't allocate bulk_in_buffer\n");
goto probe_error;
}
usb_fill_bulk_urb (port->read_urb, dev,
usb_rcvbulkpipe (dev,
endpoint->bEndpointAddress),
port->bulk_in_buffer, buffer_size,
serial->type->read_bulk_callback,
port);//在提交urb之前将其正确的初始化
}
同样的方法初始化bulk_out端点
-----------------------------------------------------------------------------------------
初始化输入中断interrupt_in端点
if (serial->type->read_int_callback) {//对于generic驱动,read_int_callback指针为空
for (i = 0; i < num_interrupt_in; ++i) {
endpoint = interrupt_in_endpoint[i];
port = serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_in_urb) {
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
}
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->interrupt_in_buffer) {
dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
goto probe_error;
}
usb_fill_int_urb (port->interrupt_in_urb, dev,
usb_rcvintpipe (dev,
endpoint->bEndpointAddress),
port->interrupt_in_buffer, buffer_size,
serial->type->read_int_callback, port,
endpoint->bInterval);
}
} else if (num_interrupt_in) {
dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined");
}
同样的方法初始化interrupt_out端点和attach
————————————————————————————————————————————-
usbserial模块总共支持254个设备,他为每个设备分配了一个serial_table项,
用于保存"usb_serial"对象,方便以后直接通过minor号获取"usbserial"对象
serial->minor = minor
注册所有独立的ports到驱动核心
/* register all of the individual ports with the driver core */
for (i = 0; i < num_ports; ++i) {
port = serial->port[i];
port->dev.parent = &interface->dev;
port->dev.driver = NULL;
port->dev.bus = &usb_serial_bus_type;//驱动的总线
port->dev.release = &port_release;
snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number); //设置端口名称
dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
retval = device_register(&port->dev); //重要,吧设备注册到usb核心,以便与用户程序交互信息
if (retval)
dev_err(&port->dev, "Error registering port device, "
"continuing\n");
}
usb_serial_console_init (debug, minor); //初始化中断控制台
usb_set_intfdata (interface, serial);//把serial结构体保存到interface接口设备中,可以调用usb_get_intfdata来获取数据。
至此,probe函数完成了4个主要工作,probe函数也走到了尽头
--------------------------------------------------------------------------------------------
到现在usb_serial_bus都没怎么用到,也没有看到这个设备和初始化时的tty_driver
绑定,这些东西都在了probe函数最后调用的device_register中。
device_register(&port->dev);
一下分析device_driver:
int device_register(struct device *dev)
{
device_initialize(dev);
return device_add(dev);
}
1.device_add():把设备device注册到相应的总线上。并创建device_file,最后
调用bus_attach_device()函数
->bus_attach_device调用device_attach(dev)
->bus_for_each_drv()遍历bus上的每个driver,当找到一个就用__device_attach()
来判断匹配
->driver_probe_device(dev,drv)首先如果所有的driver所在总线由nach函数则
先调用match来匹配,如果匹配,直接调用really_probe(dev,drv)
->really_probe。判断总线,如果由probe函数则调用和匹配它
->drv->probe:它是一类设备的probe,在他里面会调用具体某个drv的probe函数,
这个函数是在我们的驱动程序里面注册的
在该device_register里,
struct bus_type usb_serial_bus_type = {
.name = "usb-serial",
.match = usb_serial_device_match,
.probe = usb_serial_device_probe,
.remove = usb_serial_device_remove,
.drv_attrs = drv_attrs,
};
所以会先调用usb_serial_device_match,进行匹配
static int usb_serial_device_match (struct device *dev, struct device_driver *drv)
{
struct usb_serial_driver *driver;
const struct usb_serial_port *port;
/*
* drivers are already assigned to ports in serial_probe so it's
* a simple check here.
*/
port = to_usb_serial_port(dev);
if (!port)
return 0;
driver = to_usb_serial_driver(drv);
if (driver == port->serial->type)//将设备和驱动进行匹配
return 1;
return 0;
}
接下来调用probe函数,也就是usb_serial_device_probe
static int usb_serial_device_probe (struct device *dev)
{
struct usb_serial_driver *driver;
struct usb_serial_port *port;
int retval = 0;
int minor;
port = to_usb_serial_port(dev);
if (!port) {
retval = -ENODEV;
goto exit;
}
driver = port->serial->type;
if (driver->port_probe) {
if (!try_module_get(driver->driver.owner)) {
dev_err(dev, "module get failed, exiting\n");
retval = -EIO;
goto exit;
}
retval = driver->port_probe (port);
module_put(driver->driver.owner);
if (retval)
goto exit;
}
retval = device_create_file(dev, &dev_attr_port_number);
if (retval)
goto exit;
minor = port->number;
tty_register_device (usb_serial_tty_driver, minor, dev);
dev_info(&port->serial->dev->dev,
"%s converter now attached to ttyUSB%d\n",
driver->description, minor);
exit:
return retval;
}
其中,调用了tty_register_device将tty_driver和device绑定,注册该驱动控制的设备
到了这一步完成了tty和usb的注册,同时也在/dev目录下创建了相应的设备文件,也就是说应用层可以使用这个设备了。
分析玩整个注册过程,接下来当然时分析它的读写过程了,读写过程相对来说
会感觉容易一点,因为他们没有太多错综复杂的关系,各功能函数相对独立
要使用设备当然要先打开这个设备了,应用层调用open系统调用来打开这个设备,他最终
调用到tty_driver的open函数
static const struct tty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
.write = serial_write,
.write_room = serial_write_room,
.ioctl = serial_ioctl,
.set_termios = serial_set_termios,
.throttle = serial_throttle,
.unthrottle = serial_unthrottle,
.break_ctl = serial_break,
.chars_in_buffer = serial_chars_in_buffer,
.read_proc = serial_read_proc,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
};
首先看serial_open函数:
serial = usb_serial_get_by_index(tty->index) //将tty指针(终端)中获取相应的usb_serial结构体上
port = serial->port[portNumber]; //获取设备对应的port对象
++port->port.count;记录打开次数
tty->driver_data=port; //保存相应的port信息到该终端(tty)的私有指针里
serial->type->open(tty,port,flip);//usb_serial_generic_device.open=usb_serial_generic_open
所以,将会调用usb_serial_generic_open函数
一下分析int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
{
..
..
..
..
/* if we have a bulk endpoint, start reading from it */
//如果有bulk_in端点,就提交这个端点的urb,即让系统开始在这个端点上接收
来自设备端发过来的数据,当数据收到后会调用serial->type->read_bulk_callback函数
if (serial->num_bulk_in) {
/* Start reading from the device */
usb_fill_bulk_urb (port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback),
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);//使用函数usb_submit_urb //将urb提交到usb_core,成功后若接受到数据将会执行 //usb_serial_generic_read_bulk_callback
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
return result;
}
分析usb_serial_generic_read_bulk_callback(struct urb *urb)
void usb_serial_generic_read_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
unsigned char *data = urb->transfer_buffer;
int status = urb->status;
unsigned long flags;
..
..
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
/* Throttle the device if requested by tty */
spin_lock_irqsave(&port->lock, flags);
if (!(port->throttled = port->throttle_req)) {
spin_unlock_irqrestore(&port->lock, flags);
flush_and_resubmit_read_urb(port);
} else {
spin_unlock_irqrestore(&port->lock, flags);
}
}
其中,调用函数flush_and_resubmit_read_urb(port) //将数据放入tty驱动的缓冲区中
/* Push data to tty layer and resubmit the bulk read URB */
static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
{
struct urb *urb = port->read_urb;
struct tty_struct *tty = port->tty;
int room;
/* Push data to tty */
if (tty && urb->actual_length) {
room = tty_buffer_request_room(tty, urb->actual_length);
if (room) {
tty_insert_flip_string(tty, urb->transfer_buffer, room);
tty_flip_buffer_push(tty);
}
}
resubmit_read_urb(port, GFP_ATOMIC);//继续传输
}
最后调用的函数resubmit_read_urb(port, GFP_ATOMIC);
static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags)
{
struct urb *urb = port->read_urb;
struct usb_serial *serial = port->serial;
int result;
/* Continue reading from device */
usb_fill_bulk_urb (urb, serial->dev,
usb_rcvbulkpipe (serial->dev,
port->bulk_in_endpointAddress),
urb->transfer_buffer,
urb->transfer_buffer_length,
((serial->type->read_bulk_callback) ?
serial->type->read_bulk_callback :
usb_serial_generic_read_bulk_callback), port);
result = usb_submit_urb(urb, mem_flags);
if (result)
dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
在函数里又调用了usb_submit_urb函数,起到递归的作用。
至此,打开设备和读设备的流程已经写完
最后看serial_write函数,该函数对应了usb_serial_generic_write
int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
..
..
..
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
if (port->write_urb_busy) {
spin_unlock_irqrestore(&port->lock, flags);
dbg("%s - already writing", __FUNCTION__);
return 0;
}
port->write_urb_busy = 1;
spin_unlock_irqrestore(&port->lock, flags);
count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
//将数据存放进urb中
memcpy (port->write_urb->transfer_buffer, buf, count);
data = port->write_urb->transfer_buffer;
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, data);
/* set up our urb */
//初始化urb
usb_fill_bulk_urb (port->write_urb, serial->dev,
usb_sndbulkpipe (serial->dev,
port->bulk_out_endpointAddress),
port->write_urb->transfer_buffer, count,
((serial->type->write_bulk_callback) ?
serial->type->write_bulk_callback :
usb_serial_generic_write_bulk_callback), port);
/* send the data out the bulk port */
port->write_urb_busy = 1;
//提交urb到usb core中
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
..
..
}
当serial_write函数的urb成功提交到usb_core后,若urb被成功的传递到USB设备后,将会调用回调函数
usb_serial_generic_write_bulk_callback
void usb_serial_generic_write_bulk_callback (struct urb *urb)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
int status = urb->status;
dbg("%s - port %d", __FUNCTION__, port->number);
port->write_urb_busy = 0;
if (status) {
dbg("%s - nonzero write bulk status received: %d",
__FUNCTION__, status);
return;
}
usb_serial_port_softint(port); //请求更多的传输
}