Linux cdc_acm设备 – 发送到USB设备的意外字符
作者:互联网
我在使用cdc_acm驱动程序在USB端口上发送意外字符时遇到问题.更令人困惑的是,代码在Ubuntu 12.04(3.2内核)上运行良好,但在Centos 6(3.6内核)上失败(这个问题的主题).
USB设备是Bluegiga BLED112蓝牙智能加密狗.它的嵌入式微控制器将在其USB接口上的任何意外输入时复位.
测试代码打开端口,写入4个字节(一个问候消息)并期望读取响应.读取永远不会完成,因为意外字符会导致设备重置,从而导致集线器丢弃设备并重新枚举.
要进行故障排除,这就是我所做的:
>下载cdc_acm驱动程序的源代码.添加了一堆printk调试消息和stack_dump来跟踪正在发生的事情.
>我rmmod’d“stock”cdc_acm并insmod’d我的仪器化模块.所有设备枚举工作,右驱动程序附加等.
>由于代码适用于Ubuntu 12.04 / Linux 3.2,我抓住了3.2 cdc_acm代码并在CentOS 6 / Linux 3.6平台上编译了该模块.使用3.2模块而不是3.6模块并没有什么区别.我回到了3.6模块.
>用usbmon打开调试文件系统,观察USB流量.我可以看到USB接口上发送了额外的字符.
>要观察正在发生的事情,在cdc_acm模块中的printk之上,我已经合并了usb mon(cat / sys / kernel / debug / usb / usbmon / 3u | logger)的输出和测试应用程序的输出(scan_example / dev / ttyACM0 | logger -s)所以我有一个时间相关的调试跟踪流.
>在USB端点上发送的虚假字符是x5E x40 x5E x40 x5E x40 x5E x40 x41(在ASCII中它的^ @ ^ @ ^ @ ^ @ A)看起来像某种探测或试图引起调制解调器的注意这些在应用程序的write()导致将4个hello字节发送到结束点后立即发送字符.
>由于cdc_acm设备应该是调制解调器,我试图通过将其添加到cdc_acm.c中的usb_device_id acm_ids []来关闭调制解调器控制.
/* bluegiga BLED112*/
{ USB_DEVICE(0x2458, 0x0001),
.driver_info = NOT_A_MODEM,
},
>重新编译并insmod’d和syslog显示这被识别(怪癖是8),但功能没有变化.
NetowrkManager和调制解调器管理器都没有运行,但我仍然怀疑在某个地方有某种调制解调器控制功能,我只是不知道在哪里.
这是一个带注释的调试日志(MDV前缀那些我添加到cdc_acm的printk)
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_bulk
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_done
以下是应用程序00 00 00 01发送的4个字节
Feb 13 18:14:32 localhost cpcenter: df046a80 3672670191 C Bi:3:006:4 0 4 = 00000001
Feb 13 18:14:32 localhost cpcenter: 1360797272.669690 write: data2: len=0 contains:
……而这些额外的角色出乎意料地出现了5e 40 5e 40 5e 40 ……
Feb 13 18:14:32 localhost cpcenter: df046a80 3672670232 S Bi:3:006:4 -115 128 <
Feb 13 18:14:32 localhost cpcenter: f3cc5740 3672670297 S Bo:3:006:4 -115 1 = 5e
Feb 13 18:14:32 localhost cpcenter: df2e1300 3672670332 S Bo:3:006:4 -115 1 = 40
Feb 13 18:14:32 localhost cpcenter: f3cc5740 3672670347 C Bo:3:006:4 0 1 >
Feb 13 18:14:32 localhost cpcenter: f3cc5740 3672670392 S Bo:3:006:4 -115 1 = 5e
Feb 13 18:14:32 localhost cpcenter: df2e1180 3672670426 S Bo:3:006:4 -115 1 = 40
Feb 13 18:14:32 localhost cpcenter: df2e1c00 3672670461 S Bo:3:006:4 -115 1 = 5e
Feb 13 18:14:32 localhost cpcenter: df2e1840 3672670496 S Bo:3:006:4 -115 1 = 40
Feb 13 18:14:32 localhost cpcenter: df2e1300 3672670591 C Bo:3:006:4 0 1 >
在这一点上,我们得到了自发的脱节.
Feb 13 18:14:32 localhost kernel: usb 3-1: USB disconnect, device number 6
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_bulk
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_done
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm read_bulk_callback
Feb 13 18:14:32 localhost kernel: MDV 1 acm_read_bulk_callback - urb 1, len 0
Feb 13 18:14:32 localhost kernel: MDV 3 acm_read_bulk_callback - non-zero urb status: -71
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_bulk
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_done
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm read_bulk_callback
Feb 13 18:14:32 localhost kernel: MDV 1 acm_read_bulk_callback - urb 1, len 0
Feb 13 18:14:32 localhost kernel: MDV 3 acm_read_bulk_callback - non-zero urb status: -71
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_bulk
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_done
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm read_bulk_callback
Feb 13 18:14:32 localhost kernel: MDV 1 acm_read_bulk_callback - urb 2, len 0
Feb 13 18:14:32 localhost cpcenter: df2e1d80 3672670629 S Bo:3:006:4 -115 1 = 5e
Feb 13 18:14:32 localhost kernel: MDV 3 acm_read_bulk_callback - non-zero urb status: -71
Feb 13 18:14:32 localhost cpcenter: df2e1300 3672670677 S Bo:3:006:4 -115 1 = 41
Feb 13 18:14:32 localhost cpcenter: f3cc5740 3672670802 C Bo:3:006:4 0 1 >
Feb 13 18:14:32 localhost cpcenter: df2e1180 3672671019 C Bo:3:006:4 0 1 >
Feb 13 18:14:32 localhost cpcenter: df2e1c00 3672671237 C Bo:3:006:4 0 1 >
Feb 13 18:14:32 localhost cpcenter: dfbf8c00 3672673193 C Ii:3:001:1 0:2048 1 = 02
Feb 13 18:14:32 localhost cpcenter: dfbf8c00 3672673207 S Ii:3:001:1 -115:2048 4 <
Feb 13 18:14:32 localhost cpcenter: f3c26c00 3672673221 S Ci:3:001:0 s a3 00 0000 0001 0004 4 <
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_disconnect
Feb 13 18:14:32 localhost kernel: Pid: 29, comm: khubd Tainted: G O 3.5.3-1.el6.elrepo.i686 #1
断开连接时的堆栈跟踪
Feb 13 18:14:32 localhost kernel: Call Trace:
Feb 13 18:14:32 localhost kernel: [<f82dabc5>] acm_disconnect+0x35/0x1f0 [cdc_acm]
Feb 13 18:14:32 localhost kernel: [<c13835db>] usb_unbind_interface+0x4b/0x180
Feb 13 18:14:32 localhost cpcenter: f3c26c00 3672673239 C Ci:3:001:0 0 4 = 00010100
Feb 13 18:14:32 localhost kernel: [<c1318bfb>] __device_release_driver+0x5b/0xb0
Feb 13 18:14:32 localhost kernel: [<c1318d05>] device_release_driver+0x25/0x40
Feb 13 18:14:32 localhost kernel: [<c1317f0c>] bus_remove_device+0xcc/0x130
Feb 13 18:14:32 localhost kernel: [<c131612f>] ? device_remove_attrs+0x2f/0x90
Feb 13 18:14:32 localhost kernel: [<c1316275>] device_del+0xe5/0x180
Feb 13 18:14:32 localhost kernel: [<c1380326>] usb_disable_device+0x96/0x240 Feb 13 18:14:32 localhost kernel: [<c1379f91>] usb_disconnect+0x91/0x130
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_bulk
Feb 13 18:14:32 localhost kernel: [<c137a2c0>] hub_port_connect_change+0xb0/0xa60
Feb 13 18:14:32 localhost kernel: [<c1380f4e>] ? usb_control_msg+0xce/0xe0
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm acm_write_done
Feb 13 18:14:32 localhost kernel: [<c137b296>] hub_events+0x536/0x810
Feb 13 18:14:32 localhost cpcenter: f3c26c00 3672673243 S Co:3:001:0 s 23 01 0010 0001 0000 0
Feb 13 18:14:32 localhost cpcenter: f3c26c00 3672673250 C Co:3:001:0 0 0
Feb 13 18:14:32 localhost kernel: [<c1065bdf>] ? finish_wait+0x4f/0x70
Feb 13 18:14:32 localhost kernel: [<c137b5aa>] hub_thread+0x3a/0x1d0
Feb 13 18:14:32 localhost cpcenter: df2e1840 3672673260 C Bo:3:006:4 -71 0
Feb 13 18:14:32 localhost kernel: [<c1065a70>] ? wake_up_bit+0x30/0x30
Feb 13 18:14:32 localhost kernel: [<c137b570>] ? hub_events+0x810/0x810
Feb 13 18:14:32 localhost kernel: [<c106564c>] kthread+0x7c/0x90
Feb 13 18:14:32 localhost cpcenter: f3c16c80 3672673292 C Bi:3:006:4 -71 0
Feb 13 18:14:32 localhost cpcenter: df2e1d80 3672673453 C Bo:3:006:4 -71 0
Feb 13 18:14:32 localhost cpcenter: f3c16d40 3672673553 C Bi:3:006:4 -71 0
Feb 13 18:14:32 localhost kernel: [<c10655d0>] ? kthread_freezable_should_stop+0x60/0x60
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm read_bulk_callback
Feb 13 18:14:32 localhost kernel: [<c14dedbe>] kernel_thread_helper+0x6/0x10
Feb 13 18:14:32 localhost kernel: MDV 1 acm_read_bulk_callback - urb 3, len 0
Feb 13 18:14:32 localhost kernel: MDV:cdc-acm stop_data_traffic
Feb 13 18:14:32 localhost cpcenter: f3d19500 3672674474 C Ii:3:006:2 -108:64 0
Feb 13 18:14:32 localhost kernel: MDV 2 acm_read_bulk_callback - disconnected
Feb 13 18:14:32 localhost cpcenter: df2e1300 3672674636 C Bo:3:006:4 -71 0
Feb 13 18:14:32 localhost cpcenter: f3c16140 3672674753 C Bi:3:006:4 -71 0
解决方法:
添加更多内核跟踪后,我发现了
localhost kernel: [<c12c6757>] process_echoes+0x117/0x2c0
localhost kernel: [<c12c8409>] n_tty_receive_char+0x379/0x770
localhost kernel: [<c121fce4>] ? rb_erase+0xb4/0x120
localhost kernel: [<c12c89f6>] n_tty_receive_buf+0x1f6/0x380
localhost kernel: [<c14d62cb>] ? __schedule+0x39b/0x6d0
它显示了tty子系统回显和擦除字符 – 这些是造成问题的字符.以下代码删除了tty线路规则,现在可以正常工作
struct termios usb_termio; // set the USB to raw mode
memset(&usb_termio, 0, sizeof(usb_termio)); // clear the structure
cfmakeraw(&usb_termio);
if (tcsetattr(BLED_fd, TCSANOW, &usb_termio)< 0) {
perror("tcsetattr usb");
return(1);
}
Stack Overflow的@Sergey Vlasov分析了USB消息跟踪,并从另一条路径得出了相同的结论.他的解释帮助我更好地理解了usbmon输出
https://stackoverflow.com/questions/14866899/linux-cdc-acm-device-unexpected-characters-sent-to-device
标签:drivers,linux,usb,kernel-modules 来源: https://codeday.me/bug/20190815/1659649.html