频 道 直 达 - 新闻 - 培训 - 软件 - 教程 - 前沿 - 组网 - 系统应用 - 安全 - 编程 - 存储 - 操作系统 - 数据库 - 服务器 - 专题 - 产品 - 案例库 - 读书 - 博客 - BBS
51CTO.COM_中国最大的网络技术网站
找资料:

20.4.1 USB串口驱动

作者: 宋宝华 编著 出处:人民邮电出版社  2008-03-11 12:07    砖    好    评论   进入论坛
阅读提示:《Linux设备驱动开发详解》本书全面而详细地讲解了Linux设备驱动开发中涉及的理论以及多种设备驱动的框架。第20章主要讲解从主机侧角度看到的USB主机控制器驱动和设备驱动。本文写的是USB串口驱动。

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 }

【责任编辑:董书 TEL:(010)68476606】

回书目   上一节   下一节
专题
Linux——从菜鸟到高手
Linux/Solaris服务器的安全配置
Linux 集群技术专题
Linux中文环境
Linux防火墙
我也说两句

匿名发表

(如果看不清请点击图片进行更换)


中 国 最 大 的 网 络 技 术 网 站 ·
技 术 成 就 梦 想
订阅技术快讯
电子杂志下载
名称:SQL Server数据库管理精品黄皮书
简介:书中文章经过精挑细选,便于用户能根据自己的实际工作和学习,快速在本书寻找到相关资料。内容涵盖了SQL Server的安装与升级、语句查询、数据备份和恢复、自动化任务、数据同步、数据字典、安全和预防、性能和优化、集群等各方面应用信息,以及DBA管理人员在数据库管理工作中
名称:2007路由技术大全
简介:《2007路由技术大全》由51CTO.com网站特别策划制作,该书包括路由器技术、路由器产品、路由器配置、安全设置、路由器故障处理、路由器密码恢复,以及广大网友在实践使用中的心得经验和技巧文章,内容注重实用性,适用于初学者入门,也适合多年从业者提高,是一本实践和理论完
名称:网络安全精品应用黄皮书
简介:《2007精品网络安全黄皮书》包括了9个大类24个小类, 800余篇文章,内容包含了熊猫烧香病毒、DDOS攻击、ARP病等热点问题的介绍及解决方案。从病毒查杀、防范、系统、数据等各方面的安全设置到黑客技术的了解、防范,涉及到了安全应用的全部领域, 由浅至深内容全面。
RAID——磁盘阵列基础
RAID——磁盘阵列基础
华为员工自杀频频拷问企业文化
华为员工自杀频频拷问企业文化
Linux——从菜鸟到高手
Linux——从菜鸟到高手
· Linux——从菜鸟到高手
· 微软Forefront企业安全..
· 如何优化IT 控制能耗
· 国际文档格式标准开战
· CISSP认证成长之路
· 珊瑚虫QQ作者侵权案开庭
· 微软出价446亿美元收购..
· Windows Server 2008专..
· 隐私保护技术探讨
· 贝恩资本携手华为22亿..
· 802.11n:下一代的无线..
· 体验Visual Studio 200..
· 运营商封堵非法ADSL共享
· ADSL应用面面俱到
· 龙芯要做中国的“奔腾”
· 华为七千人主动辞职规..
清除流氓软件——51CTO特别专题
清除流氓软件——51CTO特别专..
ARP攻击防范与解决方案
ARP攻击防范与解决方案
VPN技术
VPN技术
· VPN技术
· SQL Server 2008/2005..
· SOA 面向服务架构
· 子网掩码教程
· SQL Server 2008/2005..
· RAID——磁盘阵列基础
· 中间件应用技术专题
· 深入了解PGP加密技术
· MySQL数据库备份
· 病毒查杀专题
· VPN技术
· Solaris 10 配置管理
· SSL VPN详细知识
· Linux防火墙
· 打造安全服务器
· Sniffer安全技术从入门..
服务器选型与选购
服务器选型与选购
ARP攻击防范与解决方案
ARP攻击防范与解决方案
VPN技术
VPN技术
· VPN技术
· SQL Server 2008/2005..
· 中间件应用技术专题
· SQL Server 2008/2005..
· SOA 面向服务架构
· 子网掩码教程
· MySQL数据库备份
· RAID——磁盘阵列基础
· 身份认证技术
· 病毒查杀专题
· 清除流氓软件——51CTO..
· SSL VPN详细知识
· Sniffer安全技术从入门..
· VPN技术
· SOA 面向服务架构
· 了解统一威胁管理(UTM)..