- 论坛徽章:
- 0
|
20.4 USB设备驱动实例
20.4.1 USB串口驱动
在Linux内核中,串口属于tty设备,对于一个USB串口设备而言,其驱动主要由两部分组成:usb_driver的成员函数和tty设备的tty_operations结构体成员函数。
在USB串口设备驱动的模块加载函数中,将注册对应于USB串口的usb_driver,并初始化和注册tty驱动,如代码清单20.28所示。
代码清单20.28 USB串口设备驱动的模块加载函数
1 static int __init usb_serial_init(void)
2 {
3 int i;
4 int result;
5
6 /* 分配tty_driver */
7 usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
8 if (!usb_serial_tty_driver)
9 return - ENOMEM;
10
11 /* 初始化全局数据 */
12 for (i = 0; i owner = THIS_MODULE;
27 usb_serial_tty_driver->driver_name = "usbserial";
28 usb_serial_tty_driver->devfs_name = "usb/tts/";
29 usb_serial_tty_driver->name = "ttyUSB";
30 usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
31 usb_serial_tty_driver->minor_start = 0;
32 usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
33 usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
34 usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
35 usb_serial_tty_driver->init_termios = tty_std_termios;
36 usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
37 CLOCAL;
38 tty_set_operations(usb_serial_tty_driver, &serial_ops);
39 /* 注册tty_driver */
40 result = tty_register_driver(usb_serial_tty_driver);
41 if (result)
42 {
43 err("%s - tty_register_driver failed", _ _FUNCTION_ _);
44 goto exit_reg_driver;
45 }
46
47 /* 注册USB驱动 */
48 result = usb_register(&usb_serial_driver);
49 if (result
在USB串口设备驱动的模块卸载函数中,将注销对应于USB串口的usb_driver,并注销tty驱动,如代码清单20.29所示。
代码清单20.29 USB串口设备驱动的模块卸载函数
1 static void _ _exit usb_serial_exit(void)
2 {
3 usb_serial_console_exit();
4 usb_serial_generic_deregister();
5 usb_deregister(&usb_serial_driver);//注销usb_driver
6 tty_unregister_driver(usb_serial_tty_driver);//注销tty_driver
7 put_tty_driver(usb_serial_tty_driver);//减少引用计数
8 bus_unregister(&usb_serial_bus_type);//注销bus
9 }
在usb_driver的探测成员函数usb_serial_probe()中,将初始化USB端点等信息,并通过
usb_set_intfdata()设置接口私有数据,它也将初始化urb。相反地,在断开成员函数usb_serial_disconnect()中
将设置接口私有数据为NULL,并释放引用计数。
USB串口驱动的tty_operations结构体实例serial_ops定义如代码清单20.30所示,它封装了USB串口设备驱动中的串口驱动成分。
代码清单20.30 USB串口驱动的tty_operations结构体
1 static struct tty_operations serial_ops =
2 {
3 .open =serial_open,
4 .close =serial_close,
5 .write =serial_write,
6 .write_room =serial_write_room,
7 .ioctl =serial_ioctl,
8 .set_termios =serial_set_termios,
9 .throttle =serial_throttle,
10 .unthrottle =serial_unthrottle,
11 .break_ctl =serial_break,
12 .chars_in_buffer =serial_chars_in_buffer,
13 .read_proc =serial_read_proc,
14 .tiocmget =serial_tiocmget,
15 .tiocmset =serial_tiocmset,
16 };
在tty_operations的各write()、read()等成员函数中,将调用usb_serial_driver结构体中的相应函数,
usb_serial_driver结构体中封装了串口的各函数(读写、读写中断端点完成函数、读写批量端点完成函数等),其定义如代码清单20.31所
示。
代码清单20.31 usb_serial_driver结构体
1 struct usb_serial_driver
2 {
3 const char *description; //用于描述该驱动的字符串
4 const struct usb_device_id *id_table; //usb_device_id数组
5 char num_interrupt_in; //中断输入端点数量
6 char num_interrupt_out; //中断输出端点数量
7 char num_bulk_in; //批量输入端点数量
8 char num_bulk_out; //批量输出端点数量
9 char num_ports; //设备包含的端口数量
10
11 struct list_head driver_list;
12 struct device_driver driver;
13
14 int(*probe)(struct usb_serial *serial, const struct usb_device_id *id);
15 int(*attach)(struct usb_serial *serial);
16 int(*calc_num_ports)(struct usb_serial *serial);
17
18 void(*shutdown)(struct usb_serial *serial);
19
20 int(*port_probe)(struct usb_serial_port *port);
21 int(*port_remove)(struct usb_serial_port *port);
22
23 /* 串口函数 */
24 int(*open)(struct usb_serial_port *port, struct file *filp);
25 void(*close)(struct usb_serial_port *port, struct file *filp);
26 int(*write)(struct usb_serial_port *port, const unsigned char *buf, int count)
27 ;
28 int(*write_room)(struct usb_serial_port *port);
29 int(*ioctl)(struct usb_serial_port *port, struct file *file, unsigned int cmd,
30 unsigned long arg);
31 void(*set_termios)(struct usb_serial_port *port, struct termios *old);
32 void(*break_ctl)(struct usb_serial_port *port, int break_state);
33 int(*chars_in_buffer)(struct usb_serial_port *port);
34 void(*throttle)(struct usb_serial_port *port);
35 void(*unthrottle)(struct usb_serial_port *port);
36 int(*tiocmget)(struct usb_serial_port *port, struct file *file);
37 int(*tiocmset)(struct usb_serial_port *port, struct file *file, unsigned int
38 set, unsigned int clear);
39 /* urb完成回调函数 */
40 void(*read_int_callback)(struct urb *urb, struct pt_regs *regs);
41 void(*write_int_callback)(struct urb *urb, struct pt_regs *regs);
42 void(*read_bulk_callback)(struct urb *urb, struct pt_regs *regs);
43 void(*write_bulk_callback)(struct urb *urb, struct pt_regs *regs);
44 };
文件drivers/usb/serial/Generic.c文件中提供了USB串口驱动的通用打开/关闭、写函数、批量urb完成函数,如
usb_serial_generic_write()、usb_serial_generic_write_bulk_callback()、
usb_serial_
generic_read_bulk_callback()等。代码清单20.32列举了通用写函数及输出批量urb完成回调函数。
代码清单20.32 USB串口通用写函数及批量写urb完成函数
1 int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char
2 *buf, int count)
3 {
4 struct usb_serial *serial = port->serial;
5 int result;
6 unsigned char *data;
7
8 if (count == 0)
9 {
10 dbg("%s - write request of 0 bytes", _ _FUNCTION_ _);
11 return (0);
12 }
13
14 /* 如果有批量输出端点 */
15 if (serial->num_bulk_out)
16 {
17 spin_lock(&port->lock);
18 if (port->write_urb_busy)
19 {
20 spin_unlock(&port->lock);
21 dbg("%s - already writing", _ _FUNCTION_ _);
22 return 0;
23 }
24 port->write_urb_busy = 1;
25 spin_unlock(&port->lock);
26
27 count = (count > port->bulk_out_size) ? port->bulk_out_size: count;
28
29 memcpy(port->write_urb->transfer_buffer, buf, count);
30 data = port->write_urb->transfer_buffer;
31 usb_serial_debug_data(debug, &port->dev, _ _FUNCTION_ _, count, data);
32
33 /* 设置urb */
34 usb_fill_bulk_urb(port->write_urb, serial->dev, usb_sndbulkpipe(serial->dev,
35 port->bulk_out_endpointAddress), port->write_urb->transfer_buffer, count,
36 ((serial->type->write_bulk_callback) ? serial->type->write_bulk_callback:
37 usb_serial_generic_write_bulk_callback), port);
38
39 /* 将数据送出给批量端口 */
40 port->write_urb_busy = 1;
41 result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
42 if (result)
43 {
44 port->write_urb_busy = 0;
45 }
46 else
47 result = count;
48
49 return result;
50 }
51
52 return 0;
53 }
54
55 void usb_serial_generic_write_bulk_callback(struct urb *urb, struct pt_regs
56 *regs)
57 {
58 struct usb_serial_port *port = (struct usb_serial_port*)urb->context;
59
60 port->write_urb_busy = 0;
61 if (urb->status) //不成功
62 {
63 dbg("%s - nonzero write bulk status received: %d", _ _FUNCTION_ _, urb
64 ->status);
65 return ;
66 }
67
68 usb_serial_port_softint((void*)port);//tty_wakeup
69 schedule_work(&port->work);//调度底半部
70 }
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/38576/showart_673361.html |
|