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