今天我们来看看linux kernel driver中的glue:u_serial.c。
这个文件把以TTY和USB Gadget设备驱动贴合在一起,实现了TTY(一般为串口)到Gadget设备的转换
。该文件实现的功能框图如下:
+-----------------+---------------------+
| | |
| | TTY device |
| | |
| u_serial.c +---------------------+
| | |
| | gadget device |
| | |
+----------------+----------------------+
我们先来看一下struct gs_port这个结构:
struct gs_port {
97 struct tty_port port;
98 spinlock_t port_lock; /* guard port_* access */
99
100 struct gserial *port_usb;
101
102 bool openclose; /* open/close in progress */
103 u8 port_num;
104
105 struct list_head read_pool;
106 int read_started;
107 int read_allocated;
108 struct list_head read_queue;
109 unsigned n_read;
110 struct tasklet_struct push;
111
112 struct list_head write_pool;
113 int write_started;
114 int write_allocated;
115 struct gs_buf port_write_buf; //这是一个环形Buf,我们会在linux kernel
data struct里进行讨论
116 wait_queue_head_t drain_wait; /* wait while writes drain */
117
118 /* REVISIT this state ... */
119 struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
120 };
在这个结构中,我们可以看到两个很重要的成员:struct tty_port port;和 struct gserial
*port_usb;由此可知,这个结构是TTY到gadget的枢纽,它是胶水层的主要结构。
讨论如何实现之前,我们来看一下源码中的一段注释:
60 /*
61 * gserial is the lifecycle interface, used by USB functions
62 * gs_port is the I/O nexus, used by the tty driver
63 * tty_struct links to the tty/filesystem framework
64 *
65 * gserial <---> gs_port ... links will be null when the USB link is
66 * inactive; managed by gserial_{connect,disconnect}(). each gserial
67 * instance can wrap its own USB control protocol.
68 * gserial->ioport == usb_ep->driver_data ... gs_port
69 * gs_port->port_usb ... gserial
70 *
71 * gs_port <---> tty_struct ... links will be null when the TTY file
72 * isn't opened; managed by gs_open()/gs_close()
73 * gserial->port_tty ... tty_struct
74 * tty_struct->driver_data ... gserial
75 */
具体的翻译这里就仁者见仁,智者见智了。
这个结构何时被创建呢? 以下成员函数实现 TTY 创建和初始化任务:
1075 int gserial_setup(struct usb_gadget *g, unsigned count)
1076 {
1077 unsigned i;
1078 struct usb_cdc_line_coding coding;
1079 int status;
1080
1081 if (count == 0 || count > N_PORTS)
1082 return -EINVAL;
1083
1084 gs_tty_driver = alloc_tty_driver(count); //分配空间
1085 if (!gs_tty_driver)
1086 return -ENOMEM;
1087
//各种赋值。。。
1088 gs_tty_driver->driver_name = "g_serial";
1089 gs_tty_driver->name = PREFIX;
1090 /* uses dynamically assigned dev_t values */
1091
1092 gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
1093 gs_tty_driver->subtype = SERIAL_TYPE_NORMAL;
1094 gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
1095 gs_tty_driver->init_termios = tty_std_termios;
1096
1097 /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on
1098 * MS-Windows. Otherwise, most of these flags shouldn't affect
1099 * anything unless we were to actually hook up to a serial line.
1100 */
1101 gs_tty_driver->init_termios.c_cflag =
1102 B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1103 gs_tty_driver->init_termios.c_ispeed = 9600;
1104 gs_tty_driver->init_termios.c_ospeed = 9600;
1105
1106 coding.dwDTERate = cpu_to_le32(9600);
1107 coding.bCharFormat = 8;
1108 coding.bParityType = USB_CDC_NO_PARITY;
1109 coding.bDataBits = USB_CDC_1_STOP_BITS;
1110
//TTY driver 跟具体的ops挂钩 ******TTY 下来的操作就靠它来“接收”、转换了
1111 tty_set_operations(gs_tty_driver, &gs_tty_ops);
1112
1113 /* make devices be openable */
1114 for (i = 0; i < count; i++) {
1115 mutex_init(&ports[i].lock);
//gs_port就是在这里进行创建的,有几个tty port就创建几个gs port***
1116 status = gs_port_alloc(i, &coding);
1117 if (status) {
1118 count = i;
1119 goto fail;
1120 }
1121 }
1122 n_ports = count;
1123
1124 /* export the driver ... */
1125 status = tty_register_driver(gs_tty_driver); //TTY 驱动注册
1126 if (status) {
1127 pr_err("%s: cannot register, err %d\n",
1128 __func__, status);
1129 goto fail;
1130 }
1131
1132 /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */
1133 for (i = 0; i < count; i++) {
1134 struct device *tty_dev;
1135
//TTY port 注册
1136 tty_dev = tty_port_register_device(&ports[i].port->port,
1137 gs_tty_driver, i, &g->dev);
1138 if (IS_ERR(tty_dev))
1139 pr_warning("%s: no classdev for port %d, err %ld\n",
1140 __func__, i, PTR_ERR(tty_dev));
1141 }
1142
1143 pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
1144 count, (count == 1) ? "" : "s");
1145
1146 return status;
1147 fail:
1148 while (count--) {
1149 tty_port_destroy(&ports[count].port->port);
1150 kfree(ports[count].port);
1151 }
1152 put_tty_driver(gs_tty_driver);
1153 gs_tty_driver = NULL;
1154 return status;
1155 }
我们继续来看看,gs_port创建的地方,如下:
1029 static int
1030 gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding)
1031 {
1032 struct gs_port *port;
1033
1034 port = kzalloc(sizeof(struct gs_port), GFP_KERNEL); //胶水结构创建
1035 if (port == NULL)
1036 return -ENOMEM;
1037
1038 tty_port_init(&port->port); //tty port 初始化
//胶水用到的spin lock、queue、tasklet、List等成员初始化
1039 spin_lock_init(&port->port_lock);
1040 init_waitqueue_head(&port->drain_wait);
1041
1042 tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
1043
1044 INIT_LIST_HEAD(&port->read_pool);
1045 INIT_LIST_HEAD(&port->read_queue);
1046 INIT_LIST_HEAD(&port->write_pool);
1047
1048 port->port_num = port_num;
1049 port->port_line_coding = *coding;
1050
1051 ports[port_num].port = port; //用数组来管理这些gs_port
1052
1053 return 0;
1054 }
接下来,我们一起来看看 TTY 下来的操作,如何被转换、执行:
1013 static const struct tty_operations gs_tty_ops = {
1014 .open = gs_open,
1015 .close = gs_close,
1016 .write = gs_write,
1017 .put_char = gs_put_char,
1018 .flush_chars = gs_flush_chars,
1019 .write_room = gs_write_room,
1020 .chars_in_buffer = gs_chars_in_buffer,
1021 .unthrottle = gs_unthrottle,
1022 .break_ctl = gs_break_ctl,
1023 };
我们找其中的open、close和write来看看吧,选open、close主要是本文起初的那段英文注释里有
描述,层与层之间是动态链接和关闭的,所以值得一看;选write是因为,想看看胶水是如何接收和转换
的。
718 /*
719 * gs_open sets up the link between a gs_port and its associated TTY.
720 * That link is broken *only* by TTY close(), and all driver methods
721 * know that.
722 */
这个open操作有些繁琐,我们保留一些相对重要的操作
723 static int gs_open(struct tty_struct *tty, struct file *file)
724 {
725 int port_num = tty->index;
726 struct gs_port *port;
727 int status;
728
//判断是否打开过,一些省略一些代码
。。。。。
771
772 /* Do the "real open" */
773 spin_lock_irq(&port->port_lock);
774
775 /* allocate circular buffer on first open */
776 if (port->port_write_buf.buf_buf == NULL) {
777
778 spin_unlock_irq(&port->port_lock);
//为gs_port开创环形缓冲区
779 status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE);
780 spin_lock_irq(&port->port_lock);
781
....
795
796 tty->driver_data = port;
797 port->port.tty = tty;
798
799 port->port.count = 1;
800 port->openclose = false;
801
802 /* if connected, start the I/O stream */
803 if (port->port_usb) {
804 struct gserial *gser = port->port_usb;
805
806 pr_debug("gs_open: start ttyGS%d\n", port->port_num);
807 gs_start_io(port);
808
//TTY open时才去connect 到gadget serial function
809 if (gser->connect)
810 gser->connect(gser);
811 }
812
813 pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
814
....
820 }
close为逆过程,这里不贴代码了;
接下来,我们看看TTY write的过程:
895 static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count)
896 {
897 struct gs_port *port = tty->driver_data;
898 unsigned long flags;
899 int status;
...
904 spin_lock_irqsave(&port->port_lock, flags);
905 if (count)
906 count = gs_buf_put(&port->port_write_buf, buf, count);
907 /* treat count == 0 as flush_chars() */
//如果存在gadget就发送
908 if (port->port_usb)
909 status = gs_start_tx(port);
910 spin_unlock_irqrestore(&port->port_lock, flags);
911
912 return count;
913 }
gs_start_tx -> gs_send_packet -> gs_buf_get //环形缓冲区的消费者
---->usb_ep_queue
由此,实现了tty 到usb的转换,最终在usb的端点中送出。