免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1429 | 回复: 0
打印 上一主题 下一主题

USB串口驱动(zz) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-05-05 09:50 |只看该作者 |倒序浏览

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
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP