usb 转 uart cp210x 驱动解析

USB 转 uart (cp210x.c) 驱动解析


#### * usb_serial_driver 结构体解析 ``` include/linux/usb/serial.h /** 描述一个usb 串口设备驱动 * usb_serial_driver - describes a usb serial driver * 将一串描述这个驱动的字符串保存在其中,这个指针在syslog中打印当设备被插入或被拔出 * @description: pointer to a string that describes this driver. This string * used in the syslog messages when a device is inserted or removed. * 指向一个列表有关 usb 设备ID结构体 ,这个结构体定义了所有能支持的设备 * @id_table: pointer to a list of usb_device_id structures that define all * of the devices this structure can support. * 这个设备将有不同的端口 * @num_ports: the number of different ports this device will have. * bulk-in 缓冲区最小的申请的空间 * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer * (0 = end-point size) * 申请的bulk-out 缓冲区大小 * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size) * 指向一个函数去决定多少个端口这个设备已经动态申请,这个将在probe 之后被调用 * @calc_num_ports: pointer to a function to determine how many ports this * device has dynamically. It will be called after the probe() * callback is called, but before attach() * 指向一个驱动的 probe 函数 * @probe: pointer to the driver's probe function. * 这个函数将在设备被插入的时候被调用,但是这个设备必须完全被usb_serial系统完全初始化 * This will be called when the device is inserted into the system, * but before the device has been fully initialized by the usb_serial * subsystem. Use this function to download any firmware to the device, * or any other early initialization that might be needed. * Return 0 to continue on with the initialization sequence. Anything * else will abort it. * 指向驱动的attach 函数 * @attach: pointer to the driver's attach function. * 这个函数将在usb_serial 结构体完全启动后被调用 * This will be called when the struct usb_serial structure is fully set * set up. Do any local initialization of the device, or any private * memory structure allocation at this point in time. * 指向驱动断开连接函数,这个函数将在设备被断开活被释放的时候被调用 * @disconnect: pointer to the driver's disconnect function. This will be * called when the device is unplugged or unbound from the driver. * 指向驱动释放函数,这个将在usb_serial 数据结构体被销毁的时候被调用 * @release: pointer to the driver's release function. This will be called * when the usb_serial data structure is about to be destroyed. * 指向控制这个设备的usb_driver 结构体,这个是必须动态添加这个驱动在 sysfs里面 * @usb_driver: pointer to the struct usb_driver that controls this * device. This is necessary to allow dynamic ids to be added to * the driver from sysfs. * 这个结构体是定义了USB serial 驱动,他提供了所有的信息有关usb serial 核心代码需要。 * 如果这个功能被定义,那么当对应的 tty 端口要使用对应功能的时候被调用 * This structure is defines a USB Serial driver. It provides all of * the information that the USB serial core code needs. If the function * pointers are defined, then the USB serial core code will call them when * the corresponding tty port functions are called. If they are not * called, the generic serial function will be used instead. * * The driver.owner field should be set to the module owner of this driver. * The driver.name field should be set to the name of this driver (remember * it will show up in sysfs, so it needs to be short and to the point. * Using the module name is a good idea.) */ ```
	struct usb_serial_driver {                                                      
	    const char *description;                                                    
	    const struct usb_device_id *id_table;                                       
	    char    num_ports;                                                          
	                                                                                
	    struct list_head    driver_list;                                            
	    struct device_driver    driver;                                             
	    struct usb_driver   *usb_driver;                                            
	    struct usb_dynids   dynids;                                                 
	                                                                                
	    size_t          bulk_in_size;                                               
	    size_t          bulk_out_size;                                              
	                                                                                
	    int (*probe)(struct usb_serial *serial, const struct usb_device_id *id);    
	    int (*attach)(struct usb_serial *serial);                                   
	    int (*calc_num_ports) (struct usb_serial *serial);                          
	                                                                                
	    void (*disconnect)(struct usb_serial *serial);                              
	    void (*release)(struct usb_serial *serial);                                 
	
	    int (*port_probe)(struct usb_serial_port *port);                            
	    int (*port_remove)(struct usb_serial_port *port);                           
	                                                                                
	    int (*suspend)(struct usb_serial *serial, pm_message_t message);            
	    int (*resume)(struct usb_serial *serial);                                   
	                                                                                
	    /* serial function calls */                                                 
	    /* Called by console and by the tty layer */                                
	    int  (*open)(struct tty_struct *tty, struct usb_serial_port *port);         
	    void (*close)(struct usb_serial_port *port);                                
	    int  (*write)(struct tty_struct *tty, struct usb_serial_port *port,         
	            const unsigned char *buf, int count);                               
	    /* Called only by the tty layer */                                          
	    int  (*write_room)(struct tty_struct *tty);                                 
	    int  (*ioctl)(struct tty_struct *tty,                                       
	              unsigned int cmd, unsigned long arg);                             
	    void (*set_termios)(struct tty_struct *tty,                                 
	            struct usb_serial_port *port, struct ktermios *old);                
	    void (*break_ctl)(struct tty_struct *tty, int break_state);                 
	    int  (*chars_in_buffer)(struct tty_struct *tty);                            
	    void (*throttle)(struct tty_struct *tty);                                   
	    void (*unthrottle)(struct tty_struct *tty);                                 
	    int  (*tiocmget)(struct tty_struct *tty);                                   
	    int  (*tiocmset)(struct tty_struct *tty,                                    
	             unsigned int set, unsigned int clear);                             
	    int  (*get_icount)(struct tty_struct *tty,                                  
	            struct serial_icounter_struct *icount);                             
	    /* Called by the tty layer for port level work. There may or may not        
	       be an attached tty at this point */                                      
	    void (*dtr_rts)(struct usb_serial_port *port, int on);                      
	    int  (*carrier_raised)(struct usb_serial_port *port);                       
	    /* Called by the usb serial hooks to allow the user to rework the           
	       termios state */                                                         
	    void (*init_termios)(struct tty_struct *tty);                               
	    /* USB events */                                                            
	    void (*read_int_callback)(struct urb *urb);                                 
	    void (*write_int_callback)(struct urb *urb);                                
	    void (*read_bulk_callback)(struct urb *urb);                                
	    void (*write_bulk_callback)(struct urb *urb);                               
	    /* Called by the generic read bulk callback */                              
	    void (*process_read_urb)(struct urb *urb);                                  
	    /* Called by the generic write implementation */                            
	    int (*prepare_write_buffer)(struct usb_serial_port *port,                   
	                        void *dest, size_t size);                               
	};                                                        

#### * usb_serial 实现的各个函数描述 ```c include/linux/usb/serial.h # 利用usb_serial_driver 里面的某一个成员找到整个结构体 #define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver) # register usb 串口驱动注册 extern int usb_serial_register(struct usb_serial_driver *driver); # deregister 解除注册 extern void usb_serial_deregister(struct usb_serial_driver *driver); extern void usb_serial_port_softint(struct usb_serial_port *port); # usb serial 的probe 函数 extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); # disconnect 断开连接函数 extern void usb_serial_disconnect(struct usb_interface *iface); # suspend 挂起,可以理解为睡眠状态 extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message); # resume 重新启动 extern int usb_serial_resume(struct usb_interface *intf);
extern int ezusb_writememory(struct usb_serial *serial, int address,            
                 unsigned char *data, int length, __u8 bRequest);               
extern int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit); 
/* USB Serial console functions */                                              
#ifdef CONFIG_USB_SERIAL_CONSOLE  
#  usb serial 控制台初始化                                              
extern void usb_serial_console_init(int debug, int minor); 
#  退出                     
extern void usb_serial_console_exit(void);     
#  断开连接                                 
extern void usb_serial_console_disconnect(struct usb_serial *serial);           
#else                                                                           
static inline void usb_serial_console_init(int debug, int minor) { }            
static inline void usb_serial_console_exit(void) { }                            
static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}  
#endif                                                                          
/* Functions needed by other parts of the usbserial core */    
#  usb serial 核心的其他部分功能               
extern struct usb_serial *usb_serial_get_by_index(unsigned int minor);
#            
extern void usb_serial_put(struct usb_serial *serial);                          
extern int usb_serial_generic_open(struct tty_struct *tty,                      
    struct usb_serial_port *port);                                              
extern int usb_serial_generic_write(struct tty_struct *tty,                     
    struct usb_serial_port *port, const unsigned char *buf, int count);         
extern void usb_serial_generic_close(struct usb_serial_port *port);             
extern int usb_serial_generic_resume(struct usb_serial *serial);                
extern int usb_serial_generic_write_room(struct tty_struct *tty);               
extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);          
extern void usb_serial_generic_read_bulk_callback(struct urb *urb);             
extern void usb_serial_generic_write_bulk_callback(struct urb *urb);            
extern void usb_serial_generic_throttle(struct tty_struct *tty);                
extern void usb_serial_generic_unthrottle(struct tty_struct *tty);              
extern void usb_serial_generic_disconnect(struct usb_serial *serial);           
extern void usb_serial_generic_release(struct usb_serial *serial);              
extern int usb_serial_generic_register(int debug);                              
extern void usb_serial_generic_deregister(void);                                
extern int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,     
                         gfp_t mem_flags);                                      
extern void usb_serial_generic_process_read_urb(struct urb *urb);               
extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port,
                        void *dest, size_t size);                               
extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port,           
                    unsigned int ch);                                           
extern int usb_serial_handle_break(struct usb_serial_port *port);               
extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,      
                     struct tty_struct *tty,                                    
                     unsigned int status);                                      
                                                                                                                                                      
extern int usb_serial_bus_register(struct usb_serial_driver *device);           
extern void usb_serial_bus_deregister(struct usb_serial_driver *device);    
                                                                                
extern struct usb_serial_driver usb_serial_generic_device;                      
extern struct bus_type usb_serial_bus_type;                                     
extern struct tty_driver *usb_serial_tty_driver;                                                                                                               
</br>

#### * cp210x.c
	
```c
	drivers/usb/serial/cp210x.c  (kernel 3.2.0)
	887 module_init(cp210x_init);   # 模块入口函数                                                      
	888 module_exit(cp210x_exit);   # 模块出口函数                                          
	889                                                                                 
	890 MODULE_DESCRIPTION(DRIVER_DESC); # 模块描述                                               
	891 MODULE_VERSION(DRIVER_VERSION);  # 模块版本                                                
	892 MODULE_LICENSE("GPL");           # 遵循 GPL 协议                                               
	893                                                                                 
	894 module_param(debug, bool, S_IRUGO | S_IWUSR);                                   
	895 MODULE_PARM_DESC(debug, "Enable verbose debugging messages");                   

	# ---> 入口
	860 static int __init cp210x_init(void)                                             
	861 {                                                                               
	862     int retval;                                                                 
	863               # usb 串口设备注册                                                                  
	864     retval = usb_serial_register(&cp210x_device);                               
	865     if (retval)                                                                 
	866         return retval; /* Failed to register */                                 
	867               # usb 串口驱动注册                                                                  
	868     retval = usb_register(&cp210x_driver);                                      
	869     if (retval) {                                                               
	870         /* Failed to register */                                                
	871         usb_serial_deregister(&cp210x_device);                                  
	872         return retval;                                                          
	873     }                                                                           
	874                                                                                 
	875     /* Success */                                                               
	876     printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"                     
	877            DRIVER_DESC "
");                                                   
	878     return 0;                                                                   
	879 }     

	# ---> cp210x_device 结构体
	155 static struct usb_serial_driver cp210x_device = {                               
	156     .driver = {                                                                 
	157         .owner =    THIS_MODULE,                                                
	158         .name =     "cp210x",                                                   
	159     },                                                                          
	160     .usb_driver     = &cp210x_driver,                                           
	161     .id_table       = id_table,                                                 
	162     .num_ports      = 1,                                                        
	163     .bulk_in_size       = 256,                                                  
	164     .bulk_out_size      = 256,                                                  
	165     .open           = cp210x_open,      # 打开函数                                        
	166     .close          = cp210x_close,     # 关闭函数                               
	167     .break_ctl      = cp210x_break_ctl,                                         
	168     .set_termios        = cp210x_set_termios,                                   
	169     .tiocmget       = cp210x_tiocmget,                                          
	170     .tiocmset       = cp210x_tiocmset,                                          
	171     .attach         = cp210x_startup,   # 设备启动函数                                        
	172     .dtr_rts        = cp210x_dtr_rts                                            
	173 };  

	#  ---> cp210x_driver 结构体
	147 static struct usb_driver cp210x_driver = {                                      
	148     .name       = "cp210x",                                                     
	149     .probe      = usb_serial_probe,                                             
	150     .disconnect = usb_serial_disconnect,                                        
	151     .id_table   = id_table,                                                     
	152     .no_dynamic_id  =   1,                                                      
	153 };                                                                              
                                                                           	                                                                        

#### * 具体的各个函数实现解析
  • open 函数
	//---> open 函数
	399 static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)    
	400 {                                                                               
	401     int result;                                                                 
	402                                                                                 
	403     dbg("%s - port %d", __func__, port->number);                                
	404        /* 这里面是通过USB传输控制信号使能cp210x  */                                                                 
	405     if (cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_ENABLE)) {       
	406         dev_err(&port->dev, "%s - Unable to enable UART
",                     
	407                 __func__);                                                      
	408         return -EPROTO;                                                         
	409     }                                                                           
	410                                                                                 
	411     result = usb_serial_generic_open(tty, port);                                
	412     if (result)                                                                 
	413         return result;                                                          
	414                                                                                 
	415     /* Configure the termios structure */                                       
	416     cp210x_get_termios(tty, port);  /*获取termios 信息,包括波特率数据位等信息*/                                          
	417     return 0;                                                                   
	418 }   

	// ---> cp210x_get_termios 函数
	438 static void cp210x_get_termios(struct tty_struct *tty,                          
	439     struct usb_serial_port *port)                                               
	440 {                                                                               
	441     unsigned int baud;                                                          
	442                                                                                 
	443     if (tty) {     // 获取相关终端的信息                                                             
	444         cp210x_get_termios_port(tty->driver_data,                               
	445             &tty->termios->c_cflag, &baud);                                     
	446         tty_encode_baud_rate(tty, baud, baud);                                  
	447     }                                                                           
	448                                                                                 
	449     else {                                                                      
	450         unsigned int cflag;                                                     
	451         cflag = 0;                                                              
	452         cp210x_get_termios_port(port, &cflag, &baud);                           
	453     }                                                                           
	454 }                                                                               

	// ---> cp210x_get_termios_port 函数
	460 static void cp210x_get_termios_port(struct usb_serial_port *port,               
	461     unsigned int *cflagp, unsigned int *baudp)                                  
	462 {                                                                               
	463     unsigned int cflag, modem_ctl[4];                                           
	464     unsigned int baud;                                                          
	465     unsigned int bits;                                                          
	466                                                                                 
	467     dbg("%s - port %d", __func__, port->number);                                
	468     //  核心是通过这个函数进行获取相关的配置信息,读取到baud rate                                                                         
	469     cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);                      
	470     /* Convert to baudrate */                                                   
	471     if (baud)    // 波特率的计算                                                            
	472         baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);   
	 		// ... ...
	475     *baudp = baud;                                                              
	476                                                                                 
	477     cflag = *cflagp;                                                            
	478                                              读取数据位                               
	479     cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2);                   
			// ... ...			
	583     *cflagp = cflag;                                                            
	584 }                                                                               
	585                                                                                 
         
	// --->  cp210x_get_config  函数
	248 /*                                                                              
	249  * cp210x_get_config    从cp210x 配置寄存器中读取相关信息                                                        
	250  * Reads from the CP210x configuration registers                                 
	251  * 'size' is specified in bytes.                                                
	252  * 'data' is a pointer to a pre-allocated array of integers large               
	253  * enough to hold 'size' bytes (with 4 bytes to each integer)                   
	254  */                 data 即是读到的数据                                                         
	255 static int cp210x_get_config(struct usb_serial_port *port, u8 request,          
	256         unsigned int *data, int size)                                           
	257 {                                                                               
	258     struct usb_serial *serial = port->serial;                                   
	259     __le32 *buf;                                                                
	260     int result, i, length;                                                      
	261                                                                                 
	262     /* Number of integers required to contain the array */                      
	263     length = (((size - 1) | 3) + 1)/4;                                          
    264     // 申请一段空间                                                                          
	265     buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);                          
	266     if (!buf) {                                                                 
	267         dev_err(&port->dev, "%s - out of memory.
", __func__);                 
	268         return -ENOMEM;                                                         
	269     }                                                                           
	270                                                                                 
	271     /* Issue the request, attempting to read 'size' bytes */
				    /*   通过USB的控制传输读取相关数据 ,读到buf里面 */                  
	272     result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),      
	273                 request, REQTYPE_DEVICE_TO_HOST, 0x0000,                        
	274                 0, buf, size, 300);                                             
	275                                                                                 
	276     /* Convert data into an array of integers */                                
	277     for (i = 0; i < length; i++)                                                
	278         data[i] = le32_to_cpu(buf[i]);                                          
    279             // 转换成data                                                                    
	280     kfree(buf);                                                                 
	281                                                                                 
	282     if (result != size) {                                                       
	283         dbg("%s - Unable to send config request, "                              
	284                 "request=0x%x size=%d result=%d
",                             
	285                 __func__, request, size, result);                               
	286         return -EPROTO;                                                         
	287     }                                                                           
	288                                                                                 
	289     return 0;                                                                   
	290 }                                                                               
	                                              
  • cp210x_break_ctl 函数解析
	// ---> cp210x_break_ctl 函数
	838 static void cp210x_break_ctl (struct tty_struct *tty, int break_state)          
	839 {                                                                               
	840     struct usb_serial_port *port = tty->driver_data;                            
	841     unsigned int state;                                                         
	842                                                                                 
	843     dbg("%s - port %d", __func__, port->number);                                
	844     if (break_state == 0)                                                       
	845         state = BREAK_OFF;                                                      
	846     else                                                                        
	847         state = BREAK_ON;                                                       
	848     dbg("%s - turning break %s", __func__,                                      
	849             state == BREAK_OFF ? "off" : "on");                                 
	850     cp210x_set_config(port, CP210X_SET_BREAK, &state, 2);                       
	851 }     // 设置 break 的状态,如果break_state为0,state == BREAK_OFF
    
	// --->   // request表示要设置什么,data 表示设置的数据,size 为大小                                                     
	298 static int cp210x_set_config(struct usb_serial_port *port, u8 request,          
	299         unsigned int *data, int size)                                           
	300 {                                                                               
	301     struct usb_serial *serial = port->serial;                                   
	302     __le32 *buf;                                                                
	303     int result, i, length;                                                      
	304                                                                                 
	305     if (request == CP210X_SET_BAUDDIV)                                          
	306     {                                                                           
	307         printk("---------------baud  rate : %d
", *data);                      
	308     }                                                                           
	309     /* Number of integers required to contain the array */                      
	310     length = (((size - 1) | 3) + 1)/4;                                          
	311     // 申请一段大小的空间                                                                            
	312     buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);                         
	313     if (!buf) {                                                                 
	314         dev_err(&port->dev, "%s - out of memory.
",                            
	315                 __func__);                                                      
	316         return -ENOMEM;                                                         
	317     }                                                                           
	318                                                                                 
	319     /* Array of integers into bytes */                                          
	320     for (i = 0; i < length; i++)                                                
	321         buf[i] = cpu_to_le32(data[i]);                                          
	322     // 判断数据大小是否大于2                                                                           
	323     if (size > 2) {                                                             
	324         result = usb_control_msg(serial->dev,                                   
	325                 usb_sndctrlpipe(serial->dev, 0),                                
	326                 request, REQTYPE_HOST_TO_DEVICE, 0x0000,                        
	327                 0, buf, size, 300);                                             
	328     } else {                                                                    
	329         result = usb_control_msg(serial->dev,                                   
	330                 usb_sndctrlpipe(serial->dev, 0),                                
	331                 request, REQTYPE_HOST_TO_DEVICE, data[0],                       
	332                 0, NULL, 0, 300);                                               
	333     }                                                                           
	334     // 释放                                                                           
	335     kfree(buf);                                                                 
	336                                                                                 
	337     if ((size > 2 && result != size) || result < 0) {                           
	338         dbg("%s - Unable to send request, "                                     
	339                 "request=0x%x size=%d result=%d
",                             
	340                 __func__, request, size, result);                               
	341         return -EPROTO;                                                         
	342     }                                                                           
	343                                                                                 
	344     return 0;                                                                   
	345 }                                                                               
  • 配置函数 cp210x_set_termios
	639 static void cp210x_set_termios(struct tty_struct *tty,                          
	640         struct usb_serial_port *port, struct ktermios *old_termios)             
	641 {                                                                               
	642     unsigned int cflag, old_cflag;                                              
	643     unsigned int baud = 0, bits;                                                
	644     unsigned int modem_ctl[4];                                                  
	645                                                                                 
	646     dbg("%s - port %d", __func__, port->number);                                
	647                                                                                 
	648     if (!tty)                                                                   
	649         return;                                                                 
	650                                                                                 
	651     tty->termios->c_cflag &= ~CMSPAR;                                           
	652     cflag = tty->termios->c_cflag;                                              
	653     old_cflag = old_termios->c_cflag;                                           
	654                                                                                 
	655     // 改变其波特率,这个是我根据kernel4.4.12的函数该过来的                    
	656     cp210x_change_speed(tty, port, old_termios);                                
	657     // 如果数据位需要升级                                                                         
	658     /* If the number of data bits is to be updated */                           
	659     if ((cflag & CSIZE) != (old_cflag & CSIZE)) {       
				// 先读旧的数据位                        
	660         cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2);                 
	661         bits &= ~BITS_DATA_MASK;  
	662         switch (cflag & CSIZE) {                                                
	663         case CS5:                                                               
	664             bits |= BITS_DATA_5;                                                
	665             dbg("%s - data bits = 5", __func__);                                
	666             break;                                                              
				// ... ...
	689         }              // 设置数据位                                                         
	690         if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2))             
	691             dbg("Number of data bits requested "                                
	692                     "not supported by device
");                               
	693     }
			// ... ...  8n1 115200  各种配置
	750                                                                                 
	751 }                                                                               
  • cp210x_tiocmget 函数
	797 static int cp210x_tiocmget (struct tty_struct *tty)                             
	798 {                                                                               
	799     struct usb_serial_port *port = tty->driver_data;                            
	800     unsigned int control;                                                       
	801     int result;                                                                 
	802                                                                                 
	803     dbg("%s - port %d", __func__, port->number);                                
	804                                                                                 
	805     cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1);                    
	806                                                                                 
	807     result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)                          
	808         |((control & CONTROL_RTS) ? TIOCM_RTS : 0)                              
	809         |((control & CONTROL_CTS) ? TIOCM_CTS : 0)                              
	810         |((control & CONTROL_DSR) ? TIOCM_DSR : 0)                              
	811         |((control & CONTROL_RING)? TIOCM_RI  : 0)                              
	812         |((control & CONTROL_DCD) ? TIOCM_CD  : 0);                             
	813     将所有的状态 | 在一起返回结果                                                                             
	814     dbg("%s - control = 0x%.2x", __func__, control);                            
	815                                                                                 
	816     return result;                                                              
	817 }                                                                               
  • cp210x_tiocmset 函数,设置相关的配置
	753 static int cp210x_tiocmset (struct tty_struct *tty,                             
	754         unsigned int set, unsigned int clear)                                   
	755 {                                                                               
	756     struct usb_serial_port *port = tty->driver_data;                            
	757     return cp210x_tiocmset_port(port, set, clear);                              
	758 }                                                                               
	759  

	// ---> cp210x_tiocmset_port
	760 static int cp210x_tiocmset_port(struct usb_serial_port *port,                   
	761         unsigned int set, unsigned int clear)                                   
	762 {                                                                               
	763     unsigned int control = 0;                                                   
	764                                                                                 
	765     dbg("%s - port %d", __func__, port->number);                                
	766                                                                                 
	767     if (set & TIOCM_RTS) {                                                      
	768         control |= CONTROL_RTS;                                                 
	769         control |= CONTROL_WRITE_RTS;                                           
	770     }                                                                           
	771     if (set & TIOCM_DTR) {                                                      
	772         control |= CONTROL_DTR;                                                 
	773         control |= CONTROL_WRITE_DTR;                                           
	774     }                                                                           
	775     if (clear & TIOCM_RTS) {                                                    
	776         control &= ~CONTROL_RTS;                                                
	777         control |= CONTROL_WRITE_RTS;                                           
	778     }                                                                           
	779     if (clear & TIOCM_DTR) {                                                    
	780         control &= ~CONTROL_DTR;                                                
	781         control |= CONTROL_WRITE_DTR;                                           
	782     }                                                                           
    783                                                                                 
	784     dbg("%s - control = 0x%.4x", __func__, control);                            
	785     //  配置函数                                                                            
	786     return cp210x_set_config(port, CP210X_SET_MHS, &control, 2);                
	787 }                                                                                                                                                         
  • cp210x_dtr_rts 函数
	789 static void cp210x_dtr_rts(struct usb_serial_port *p, int on)                   
	790 {                                                                               
	791     if (on)                                                                     
	792         cp210x_tiocmset_port(p, TIOCM_DTR|TIOCM_RTS, 0);                        
	793     else                                                                        
	794         cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);                        
	795 }                                                                               
原文地址:https://www.cnblogs.com/chenfulin5/p/6694286.html