Android Qcom USB Driver Learning (12)

The link to the general catalog of this series of articles and the introduction of each part: Android Qcom USB Driver learning (zero)
keypad in the suspend process causes Android to fail to enter the suspend problem, resulting in high overall power consumption. In fact, the host does not enter sleep. Through the following The method of logging finally locates the problem. When the pmic vbus outputs, there will be a reverse boost, so the power consumption on the pmic side will also increase. When the pmic power is low, it will trigger uvlo and cause the power on the vbus to be disconnected. If necessary, We can lower the trigger threshold of this uvlo, so that the corresponding firmware can be used at low power

usb_enable_autosuspend -> pm_runtime_allow -> rpm_idle -> rpm_suspend -> rpm_callback

.runtime_suspend =      usb_runtime_suspend 入口

usb_runtime_suspend -> autosuspend_check
                    -> usb_suspend_both <return error>
				-> usb_suspend_interface<return error>
					-> driver->suspend(intf, msg)<return error>
						-> hid_suspend
							-> hidinput_count_leds
							-> if(!test_bit(HID_RESET_PENDING, &usbhid->iofl)
                   					 && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
                    					 && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)
                   					 && !test_bit(HID_CTRL_RUNNING, &usbhid->iofl)
                    					 && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl)
                    					 && (!ledcount || ignoreled ))<return error>
							-> driver_suspend = true
							
				-> usb_suspend_device
					-> udriver->suspend(udev, msg)
						-> generic_suspend
							-> usb_port_suspend
								-> usb_enable_remote_wakeup
								-> usb_disable_usb2_hardware_lpm
								-> usb_disable_ltm
								-> set_port_feature(USB_PORT_FEAT_SUSPEND)
									-> usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
                							    USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
                							    NULL, 0, 1000);
								-> usb_set_device_state(USB_STATE_SUSPENDED)
								-> pm_runtime_put_sync

After analyzing the problem, it is determined that in ledcount in usb_suspend_both, ignored is obtained in Module params

The usb suspend/resume is controlled by the setportfeature command. The linux usb driver also controls the suspend and resume status through this port command. If you want to suspend a device, you want to send USB_PORT_FEAT_SUSPEND to the hub port where it is located to make the device Enter the suspend state. At this time, the basic host enters the suspend state, and the power consumption is still high. The state can basically be disconnected. If the device does not enter the suspend state, it can basically be positioned as the usb external device suspend failed. For roothub, it does not have a port. , so there is no corresponding setportfeatre method, then it uses the system's global call bus_suspend, in addition to the above-mentioned led report problems, you also need to pay attention to the remote wakeup function will also cause usb_suspend_both to fail

Android

One method is to filter out our equipment and make it go into the normal suspend process, and the other method is to set ignoreled to true

bool isKeypad(struct hid_device *hid,struct usb_interface *intf){
    
    
	if(hid->vendor == 0xXXXX && hid->product == 0xXXXX)
		return true;
	return false;
}

usbhid_probe
	ifisKeypad(hid, intf)){
    
    
		usb_enable_autosuspend(dev);
		hid_err(intf, "enable autosuspend++++++\n");
	}

usbhid_disconnect
	ifisKeypad(hid, intf)){
    
    
		usb_disable_autosuspend(dev);
		hid_err(intf, "disable autosuspend++++++\n");
	}

hid_suspend
-	&& (!ledcount || ignoreled ))
+	&& (!ledcount || ignoreled || isCW45Keypad(hid, intf)))

Firmware

Introduction to HID report and report description In this article, we can learn that the report descriptor of the keyboard is related to the usage in the report. It may be that Android can support the processing of keypad led. If it is not processed for Android, the ReportDescriptor in the keypad firmware It may be OK to delete or modify some values ​​in this paragraph. I guess, the firmware code has not been analyzed

code char KeyBoardReportDescriptor[63] = {
    
    
	0x05, 0x01, // USAGE_PAGE (Generic Desktop)  //表示用途页为通用桌面设备
	0x09, 0x06, // USAGE (Keyboard) //表示用途为键盘
	0xa1, 0x01, // COLLECTION (Application)
	...
-	0x05, 0x08, // USAGE_PAGE (LEDs) //用途是 LED,即用来控制键盘上的 LED 用的,因此下面会说明它是输出用
-	0x19, 0x01, // USAGE_MINIMUM (Num Lock) //用途最小值是 Num Lock,即数字键锁定灯
-	0x29, 0x05, // USAGE_MAXIMUM (Kana) //用途最大值是 Kana,这个是什么灯我也不清楚
-	0x91, 0x02, // OUTPUT (Data,Var,Abs) //1 表示灯亮, 0 表示灯灭
-	0x95, 0x01, // REPORT_COUNT (1) //这样的数据段个数为 1
-	0x75, 0x03, // REPORT_SIZE (3) //每个段大小为 3bits
-	0x91, 0x03, // OUTPUT (Cnst,Var,Abs) 输出用,常量,值,绝对 对上面的5字节进行补齐
	...
	0xc0 // END_COLLECTION
};

Guess you like

Origin blog.csdn.net/qq_40405527/article/details/130941334