serial_table[i]=NULL; //该模块共支持SERIAL_TTY_MINORS个该类型设备.
}
result=bus_register(&usb_serial_bus_type); //注册这条serialbus.
if(result){
err("%s-registeringbusdriverfailed",__FUNCTION__);
gotoexit_bus;
}
//初始化tty_driver对象
usb_serial_tty_driver->owner=THIS_MODULE;
usb_serial_tty_driver->driver_name="usbserial";
usb_serial_tty_driver->devfs_name="usb/tts/";
usb_serial_tty_driver->name= "ttyUSB"; //tty设备文件名以这个开头,后加0,1,2,3,....
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_NO_DEVFS;
usb_serial_tty_driver->init_termios=tty_std_termios;
usb_serial_tty_driver->init_termios.c_cflag=B9600|CS8|CREAD|HUPCL|CLOCAL;
//赋值tty设备的操作集合,即应用层调用open时最终会调到serial_ops->open里面
tty_set_operations(usb_serial_tty_driver,&serial_ops);
result=tty_register_driver(usb_serial_tty_driver); //注册这个tty驱动
if(result){
err("%s-tty_register_driverfailed",__FUNCTION__);
gotoexit_reg_driver;
}
/*registertheUSBdriver*/
result=usb_register(&usb_serial_driver); //注册一个usb驱动
if(result<0){
err("%s-usb_registerfailed",__FUNCTION__);
gotoexit_tty;
}
/*registerthegenericdriver,ifweshould*/
result=usb_serial_generic_register(debug); //注册generic驱动程序
if(result<0){
err("%s-registeringgenericdriverfailed",__FUNCTION__);
gotoexit_generic;
}
info(DRIVER_DESC);
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:
err("%s-returningwitherror%d",__FUNCTION__,result);
put_tty_driver(usb_serial_tty_driver);
returnresult;
}
该函数先创建并初始化好了一个tty_driver的对象, 并把该对象注册进系统, 该对象就是tty设备的驱动程序, 后面我们会看到他是如何于具体tty设备绑定在一起的.
usb_serial.c:
staticstructtty_operationsserial_ops={
.open= serial_open,
.close= serial_close,
.write= serial_write,
.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,
.read_proc= serial_read_proc,
.tiocmget= serial_tiocmget,
.tiocmset= serial_tiocmset,
};
这个就是tty设备文件对应的操作方法集合, 例如, 应用层调用open函数来打开该设备文件时将最终会走到serial_open里面.
usb_serial_init() 还注册了一条总线:
usb_serial_bus_type, 这样当有设备连上系统时, 该总线上的驱动就有机会去匹配这个设备. 后面我们会看到generic的驱动就是注册在该总线上的.
bus.c:
structbus_typeusb_serial_bus_type={
.name= "usb-serial",
.match= usb_serial_device_match, //在设备匹配时会调用
.probe= usb_serial_device_probe,
.remove= usb_serial_device_remove,
};
关于设备匹配过程(probe)可以参考我的另一篇文章.
usb_serial_init() 在最后usb_serial_generic_register(debug)来注册generic驱动.
generic.c:
intusb_serial_generic_register(int_debug)
{
intretval=0;
debug=_debug;
#ifdefCONFIG_USB_SERIAL_GENERIC
generic_device_ids[0].idVendor=vendor; //保存厂商ID
generic_device_ids[0].idProduct=product; //保存产品ID
generic_device_ids[0].match_flags=USB_DEVICE_ID_MATCH_VENDOR|USB_DEVICE_ID_MATCH_PRODUCT; //匹配类型
/*registerourgenericdriverwithourselves*/
retval=usb_serial_register(&usb_serial_generic_device); //注册驱动
if(retval)
gotoexit;
retval=usb_register(&generic_driver); //注册驱动
if(retval)
usb_serial_deregister(&usb_serial_generic_device);
exit:
#endif
returnretval;
}
该函数首先保存了命令通过命令行设备的vendor,product 用于以后设备匹配, 由此我们知道该驱动可以动态支持设备匹配. 接着该函数注册了usb_serial_generic_device驱动.
generic.c:
structusb_serial_driverusb_serial_generic_device={
.driver={
.owner= THIS_MODULE,
.name= "generic",
},
.id_table= generic_device_ids, //匹配用的设备列表, 支持动态匹配
.num_interrupt_in= NUM_DONT_CARE,
.num_bulk_in= NUM_DONT_CARE,
.num_bulk_out= NUM_DONT_CARE,
.num_ports= 1,
.shutdown= usb_serial_generic_shutdown,
};
Usb-serial.c:
intusb_serial_register(structusb_serial_driver*driver)
{
intretval;
fixup_generic(driver); //为driver赋上默认的操作函数
if(!
driver->description)
driver->description=driver->driver.name;
/*Addthisdevicetoourlistofdevices*/
list_add(&driver->driver_list,&usb_serial_driver_list); //加入驱动列表
retval=usb_serial_bus_register(driver); //把该驱动注册进usbserialbus下
if(retval){
err("problem%dwhenregisteringdriver%s",retval,driver->description);
list_del(&driver->driver_list);
}
else
info("USBSerialsupportregisteredfor%s",driver->description);
returnretval;
}
其中的fixup_generic()函数仅仅是为driver赋上默认的操作函数.
Usb-serial.c:
#defineset_to_generic_if_null(type,function) \
do{ \
if(!
type->function){ \
type->function=usb_serial_generic_##function; \
dbg("Hadtooverridethe"#function \
"usbserialoperationwiththegenericone.");\
} \
}while(0)
staticvoidfixup_generic(structusb_serial_driver*device)
{
set_to_generic_if_null(device,open);
set_to_generic_if_null(device,write);
set_to_generic_if_null(device,close);
set_to_generic_if_null(device,write_room);
set_to_generic_if_null(device,chars_in_buffer);
set_to_generic_if_null(device,read_bulk_callback);
set_to_generic_if_null(device,write_bulk_callback);
set_to_generic_if_null(device,shutdown);
}
即通过上面的usb_serial_register()函数后usb_serial_generic_device的函数集为:
usb_serial_generic_device.open=usb_serial_generic_open;
usb_serial_generic_device.close=usb_serial_generic_close
......
驱动usb_serial_generic_device将是以后操作tty设备的主要函数.我们会在后面分析.
bus.c:
intusb_serial_bus_register(structusb_serial_driver*driver)
{
intretval;
driver->driver.bus=&usb_serial_bus_type; //注册到该bus下
retval=driver_register(&driver->driver);
returnretval;
}
最后usb_serial_generic_register()函数注册了一个generic_driver驱动.
generic.c:
staticstructusb_drivergeneric_driver={
.name= "usbserial_generic",
.probe= generic_probe, //匹配函数
.disconnect=