在调试移远5G模块时,发现5G模块通过USB3.0方式连接的时候,android系统无法进入休眠,原因自然跟USB有关系。联系移远FAE, 反馈回来的结果是根据他们给的文档,增加一下USB自动休眠与支持远程唤醒即可。依据移远给的提示,增加了相关代码,usb_enable_autosuspend()与device_init_wakeup()。
通过测试,发现USB终于可以进入休眠,但当系统进入休眠,唤醒的时候,5G模块与主机之间断掉了。
usb_wwan_port_remove--port=2
usb_serial_device_remove--GSM modem (1-port) converter now disconnected from ttyUSB2
跑去移远公司现场调试,确认硬件连接没有问题,5G模块休眠唤醒正常。仅用USB3.0的4根tx,rx线与电源,地即可。排查一个下午,也无法解决问题。
联系AP端FAE,想确认一下AP端芯片上的USB主机在系统休眠之后是否能够正常唤醒。但很遗憾,由于某些原因,移远FAE并未支持我。
无奈只能靠自己啃代码。
为了确认主机端能否进入休眠,首先想到的就是确认USB2.0是否可以正常休眠唤醒。于是,我接了一个USB2.0的鼠标。
在drivers/hid/usbhid/hid-core.c的usbhid_probe()函数加入
usb_enable_autosuspend(dev);
在usbhid_disconnect()加入
struct usb_device *dev = interface_to_usbdev(intf);
usb_disable_autosuspend(dev);
然后编译内核,烧录进板子,发现鼠标没操作时,电流减少,鼠标上面的灯灭掉,系统可进入休眠。然后点击鼠标,板子屏幕亮,可正常唤醒。说明USB2.0的唤醒是正常的。
USB2.0可以正常休眠唤醒,USB3.0是否也能够正常休眠唤醒。认为希望还是很大。于是开始跟踪代码
Linux内核:
###drivers\usb\serial\usb_wwan.c
int usb_wwan_port_remove(struct usb_serial_port *port)
这个函数的调用说明了5G USB连接被移除了。
******************************************************************************
###drivers\usb\serial\bus.c
static int usb_serial_device_remove(struct device *dev)
里面执行了
if (driver->port_remove)
retval = driver->port_remove(port);
也就是调用了usb_wwan_port_remove()
******************************************************************************
###drivers\base\dd.c
static void __device_release_driver(struct device *dev)
里面执行了
dev->bus->remove(dev);
也就是调用了usb_serial_device_remove()
******************************************************************************
###drivers\base\bus.c
void bus_remove_device(struct device *dev)
里面调用:
device_release_driver(dev)-->__device_release_driver()
******************************************************************************
###drivers\base\core.c
void device_del(struct device *dev)
里面调用:
bus_remove_device(dev);
******************************************************************************
###kernel\msm-4.4\drivers\usb\core\hub.c
void usb_disconnect(struct usb_device **pdev)
里面调用:
device_del(&udev->dev);
******************************************************************************
static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
u16 portchange)
里面调用:
usb_disconnect(&port_dev->child);
******************************************************************************
static void hub_port_connect_change(struct usb_hub *hub, int port1,
u16 portstatus, u16 portchange)
__must_hold(&port_dev->status_lock)
里面调用:
hub_port_connect(hub, port1, portstatus, portchange);
******************************************************************************
static void port_event(struct usb_hub *hub, int port1)
__must_hold(&port_dev->status_lock)
里面调用:
hub_port_connect_change(hub, port1, portstatus, portchange);
******************************************************************************
static void hub_event(struct work_struct *work)
里面调用:
port_event(hub, i);
******************************************************************************
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
里面:
INIT_WORK(&hub->events, hub_event);
由以上代码跟踪可知,因为唤醒的时候,hub检测不到任何有效USB连接,所以把所有存在的usb连接全部清除掉。
跟踪到这里,代码似乎已经无法跟踪下去了,只能从硬件上面分析,可用USB分析仪进行线路上的分析,看看是否能查找到原因。