本系列解析usbseiral ko的源码,记录主要函数,调用流程,USB一端和串口一端的注册流程,本节简介主要函数以及替换规则。
首先,usbserial是USB转串口驱动的一个基础模板,其中有许多默认函数,他们的定义方式如下:
const struct bus_type usb_serial_bus_type = {.name = "usb-serial",.match = usb_serial_device_match,.probe = usb_serial_device_probe,.remove = usb_serial_device_remove,.drv_groups = usb_serial_drv_groups,
};
static struct usb_serial_driver usb_serial_generic_device = {.driver = {.owner = THIS_MODULE,.name = "generic",},.id_table = generic_device_ids,.probe = usb_serial_generic_probe,.calc_num_ports = usb_serial_generic_calc_num_ports,.throttle = usb_serial_generic_throttle,.unthrottle = usb_serial_generic_unthrottle,.resume = usb_serial_generic_resume,
};
static const struct tty_port_operations serial_port_ops = {.carrier_raised = serial_port_carrier_raised,.dtr_rts = serial_port_dtr_rts,.activate = serial_port_activate,.shutdown = serial_port_shutdown,
};
static const struct tty_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,.wait_until_sent = serial_wait_until_sent,.tiocmget = serial_tiocmget,.tiocmset = serial_tiocmset,.get_icount = serial_get_icount,.set_serial = serial_set_serial,.get_serial = serial_get_serial,.cleanup = serial_cleanup,.install = serial_install,.proc_show = serial_proc_show,
};
其中,tty operation中有部分函数可以被替换掉,替换的过程如下:
static void usb_serial_operations_init(struct usb_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);if (device->tx_empty)set_to_generic_if_null(device, wait_until_sent);set_to_generic_if_null(device, read_bulk_callback);set_to_generic_if_null(device, write_bulk_callback);set_to_generic_if_null(device, process_read_urb);set_to_generic_if_null(device, prepare_write_buffer);
}
可见open、write、close、write_room、chars_in_buffer、read_bulk_callback、write_bulk_callback、process_read_urb、prepare_write_buffer函数可以被替换掉,不过有些函数采取的是插入的方式,目的是在generic的基础上,增加一些属vendor的其他操作,比如probe
以generic 的probe为例子,usbseiral设备在被probe的时候,一定会进行search_serial_device、create_serial等等操作,然后再简单的打印一些信息——如果有一些vendor specific的probe操作,可以单独添加——endpoint的查找在vendor的probe的后面,也是一定会进行的。