Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3808059
  • 博文数量: 197
  • 博客积分: 10086
  • 博客等级: 上将
  • 技术积分: 5145
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-13 10:50
文章分类

全部博文(197)

文章存档

2011年(2)

2009年(30)

2008年(165)

我的朋友

分类: LINUX

2008-05-05 09:50:08

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 < SERIAL_TTY_MINORS; ++i)
13 {
14 serial_table[i] = NULL;
15 }
16
17 /* 注册总线 */
18 result = bus_register(&usb_serial_bus_type);
19 if (result)
20 {
21 err("%s - registering bus driver failed", _ _FUNCTION_ _);
22 goto exit_bus;
23 }
24
25 /* 初始化tty_driver */
26 usb_serial_tty_driver->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 < 0)
50 {
51 err("%s - usb_register failed", _ _FUNCTION_ _);
52 goto exit_tty;
53 }
54
55 result = usb_serial_generic_register(debug);
56 if (result < 0)
57 {
58 err("%s - registering generic driver failed", _ _FUNCTION_ _);
59 goto exit_generic;
60 }
61
62 info(DRIVER_DESC);
63
64 return result;
65
66 exit_generic: usb_deregister(&usb_serial_driver);
67 exit_tty: tty_unregister_driver(usb_serial_tty_driver);
68 exit_reg_driver: bus_unregister(&usb_serial_bus_type);
69 exit_bus: err("%s - returning with error %d", _ _FUNCTION_ _, result);
70 put_tty_driver(usb_serial_tty_driver);
71 return result;
72 }

在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 }
阅读(2556) | 评论(1) | 转发(1) |
0

上一篇:USB骨架程序

下一篇:USB键盘驱动(zz)

给主人留下些什么吧!~~

chinaunix网友2008-12-02 10:46:20

你好,能不能向你请教一下关于USB串口驱动方面的问题,我的QQ421920134,邮箱csuzhsh@gmail.com