/****************************************
* USB主机与设备驱动
* 主机侧:由底到高:USB主机控制器硬件-->
* USB主机控制器驱动--> USB核心层 --> USB
* 设备驱动层
* 设备侧:UDC驱动程序、Gadget API和Gadget
* 驱动程序
* 逻辑组织:设备(1) 配置(n)
* 配置(1) 接口(n)
* 端点(0/n) 接口(1) 设置(n)
* USB主机控制驱动:控制插入其中的USB设备
* USB设备驱动:控制USB设备如何与主机通信
* 标准描述符:
* 设备描述符 usb_device_descriptor
* 配置描述符 usb_config_descriptor
* 接口描述符 usb_interface_descriptor
* 端点描述符 usb_endpoint_descriptor
* 字符串描述符 usb_string_descriptor
* 几个重要的数据结构:hc_driver usb_hcd
* ohci_hcd usb_driver urb(请求块)
* urb的典型生命周期:
* (1) 被一个USB设备驱动创建
* (2) 初始化,被安排给一个特定USB设备的特定端点
* (3) 被USB设备驱动提交给USB核心
* (4) 提交与USB核心指定的USB主机控制器驱动
* (5) 被USB主机控制器处理,进行一次到USB设备的传送
* (6) 当urb完成,USB主机控制器驱动通知USB设备驱动
*
* probe() 和 disconnect() 这两个函数比较重要
*
********************************************/
/*
* USB 设备驱动实例:USB串口驱动(部分)
*
*/
/* Driver structure we register with the USB core */
staticstructusb_driver usb_serial_driver = {
.name ="usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.suspend = usb_serial_suspend,
.resume = usb_serial_resume,
.no_dynamic_id = 1,
}
/* USB串口设备驱动的模块加载函数 */
staticint__init usb_serial_init(void)
{
inti;
intresult;
/* 分配tty_driver */
usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS);
if(usb_serial_tty_driver)
{
return-ENOMEM;
}
/* 初始化全局变量 */
for(i = 0; i
serial_table[i] = NULL;
/* 注册总线 */
result = bus_register(&usb_serial_bus_type);
if(result)
{
printk(KERN_ERR"usb-serial: %s - registering bus driver failed\n", __func__);
gotoexit_bus;
}
/* 初始化tty_driver */
usb_serial_tty_driver->owner = THIS_MODULE;
usb_serial_tty_driver->driver_name ="usbserial";
usb_serial_tty_driver->name ="ttyUSB";
usb_serial_tty_driver->major = SERIAL_TTY_MAJOR;
usb_serial_tty_driver->minor_start = 0;
usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL;
usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
usb_serial_tty_driver->init_termios = tty_std_termios;
usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
| HUPCL | CLOCAL;
usb_serial_tty_driver->init_termios.c_ispeed = 9600;
usb_serial_tty_driver->init_termios.c_ospeed = 9600;
tty_set_operations(usb_serial_tty_driver, &serial_ops);
/* 注册tty_driver */
result = tty_register_driver(usb_serial_tty_driver);
if(result)
{
printk(KERN_ERR"usb-serial: %s - tty_register_driver failed\n",
__func__);
gotoexit_reg_driver;
}
/* 注册USB驱动 */
result = usb_register(&usb_serial_driver);
if(result
{
printk(KERN_ERR"usb-serial: %s - usb_register failed\n",
__func__);
gotoexit_tty;
}
/* register the generic driver, if we should */
result = usb_serial_generic_register(debug);
if(result
{
printk(KERN_ERR"usb-serial: %s - registering generic "
"driver failed\n", __func__);
gotoexit_generic;
}
printk(KERN_INFO KBUILD_MODNAME": "DRIVER_DESC"\n");
returnresult;
exit_generic:
usb_deregister(&usb_serial_driver);
exit_tty:
tty_unregister_driver(usb_serial_tty_driver);
exit_reg_driver:
bus_unregister(&usb_serial_bus_type);
exit_bus:
printk(KERN_ERR"usb-serial: %s - returning with error %d\n",
__func__, result);
put_tty_driver(usb_serial_tty_driver);
returnresult;
}
staticvoid__exit usb_serial_exit(void)
{
usb_serial_console_exit();
usb_serial_generic_deregister();
usb_deregister(&usb_serial_driver);//注销usb_driver
tty_unregister_driver(usb_serial_tty_driver);// 注销tty_driver
put_tty_driver(usb_serial_tty_driver);// 减少引用计数
bus_unregister(&usb_serial_bus_type);// 注销bus
}
/*
* 在usb_driver的探测成员函数usb_serial_probe()中,将初始化USB端点
* 等信息,并通过usb_set_intfdata()设置接口私有数据,它也将初始化urb。
*
*/
staticconststructtty_operations serial_ops = {
.open = serial_open,
.close = serial_close,
.write = serial_write,
.hangup = serial_hangup,
.write_room = serial_write_room,
.ioctl = serial_ioctl,
.set_termios = serial_set_termios,
.throttle = serial_throttle,
.unthrottle = serial_unthrottle,
.break_ctl = serial_break,
.chars_in_buffer = serial_chars_in_buffer,
.tiocmget = serial_tiocmget,
.tiocmset = serial_tiocmset,
.get_icount = serial_get_icount,
.cleanup = serial_cleanup,
.install = serial_install,
.proc_fops = &serial_proc_fops,
};
///
/*
* USB 设备驱动实例:USB键盘驱动(部分)
* 主要包含两部分:
* usb_driver的成员函数
* 输入设备的打开、关闭、中断处理等函数
*
*/
/*
* 在USB键盘设备驱动的模块加载和卸载函数中
* ,将分别注册和注销对于USB键盘的usb_driver
* 结构体usb_kbd_driver
*/
staticint__init usb_kbd_init(void)
{
intresult = usb_register(&usb_kbd_driver);//注册USB设备驱动
if(result == 0)
printk(KERN_INFO KBUILD_MODNAME": "DRIVER_VERSION":"
DRIVER_DESC"\n");
returnresult;
}
staticvoid__exit usb_kbd_exit(void)
{
usb_deregister(&usb_kbd_driver);
}
staticstructusb_driver usb_kbd_driver = {
.name ="usbkbd",
.probe = usb_kbd_probe,
.disconnect = usb_kbd_disconnect,
.id_table = usb_kbd_id_table,
};
// 支持的设备列表
staticstructusb_device_id usb_kbd_id_table [] = {
{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
USB_INTERFACE_PROTOCOL_KEYBOARD) },
{ }/* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
/*
* 在usb_driver的探测函数中,将进行input设备的初始化和注册。
* usb键盘要使用的中断urb和控制urb的初始化,并设置接口的私有数据。
*/
staticintusb_kbd_probe(structusb_interface *iface,
conststructusb_device_id *id)
{
...
}
/* 设置接口私有数据为NULL、终止已提交的urb并注销输入设备。*/
staticvoidusb_kbd_disconnect(structusb_interface *intf)
{
...
}
/*
* 键盘中断处理函数中,也就是urb的完成函数中,将会通过input_report_key()
* 报告按键事件,通过input_sync()报告同步事件,并发起一次新的控制urb传输。
*/
staticvoidusb_kbd_irq(structurb *urb)
{
structusb_kbd *kbd = urb->context;
inti;
switch(urb->status)
{
case0:/* success */
break;
case-ECONNRESET:/* unlink */
case-ENOENT:
case-ESHUTDOWN:
return;
/* -EPIPE: should clear the halt */
default:/* error */
gotoresubmit;
}
for(i = 0; i
{
input_report_key(kbd->dev, usb_kbd_keycode[i + 224],
(kbd->new[0] >> i) & 1);
}
for(i = 2; i
{
if(kbd->old[i] > 3 &&
memscan(kbd->new+ 2, kbd->old[i], 6) == kbd->new+ 8)
{
if(usb_kbd_keycode[kbd->old[i]])
{
input_report_key(kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
}
else
{
dev_info(&urb->dev->dev,
"Unknown key (scancode %#x) released.\n", kbd->old[i]);
}
}
if(kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8)
{
if(usb_kbd_keycode[kbd->new[i]])
input_report_key(kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
else
dev_info(&urb->dev->dev,
"Unknown key (scancode %#x) released.\n", kbd->new[i]);
}
}
input_sync(kbd->dev);
memcpy(kbd->old, kbd->new, 8);
resubmit:
i = usb_submit_urb (urb, GFP_ATOMIC);
if(i)
{
err_hid ("can't resubmit intr, %s-%s/input0, status %d",
kbd->usbdev->bus->bus_name,
kbd->usbdev->devpath, i);
}
}