Support GL852G USB hub JK level tuning
The JK level setting is configured to the hub via a vendor USB command whenever the hub is enabled. The shell command can be used to change the JK setting for testing purpose, but the values take effect next time the hub is enumerated. Bug: 261923350 Bug: 340665903 Test: adb shell cmd android.hardware.usb.IUsb/default hub-vendor-cmd <hex wValue> <hex wIndex> Test: verify on user/userdebug builds the vendor command is triggered in the following scenarios. 1. boot with Kolan docked 2. undock and dock Kolan 3. kill android.hardware.usb.IUsb/default Change-Id: I8873695c42f362138d99b45ffa2ef637c357202b
This commit is contained in:
parent
b058b0088f
commit
fd704fdcfb
2 changed files with 88 additions and 80 deletions
163
usb/usb/Usb.cpp
163
usb/usb/Usb.cpp
|
@ -126,6 +126,9 @@ AltModeData::DisplayPortAltModeData constructAltModeData(string hpd, string pin_
|
|||
#define GL852G_PRODUCT_ID1 0x0608
|
||||
#define GL852G_PRODUCT_ID2 0x0610
|
||||
#define GL852G_VENDOR_CMD_REQ 0xe3
|
||||
// GL852G port 1 and port 2 JK level default settings
|
||||
#define GL852G_VENDOR_CMD_VALUE_DEFAULT 0x0008
|
||||
#define GL852G_VENDOR_CMD_INDEX_DEFAULT 0x0404
|
||||
|
||||
ScopedAStatus Usb::enableUsbData(const string& in_portName, bool in_enable,
|
||||
int64_t in_transactionId) {
|
||||
|
@ -521,6 +524,61 @@ void updatePortStatus(android::hardware::usb::Usb *usb) {
|
|||
queryVersionHelper(usb, ¤tPortStatus);
|
||||
}
|
||||
|
||||
static int usbDeviceRemoved(const char *devname, void* client_data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbDeviceAdded(const char *devname, void* client_data) {
|
||||
uint16_t vendorId, productId;
|
||||
struct usb_device *device;
|
||||
::aidl::android::hardware::usb::Usb *usb;
|
||||
int value, index;
|
||||
|
||||
device = usb_device_open(devname);
|
||||
if (!device) {
|
||||
ALOGE("usb_device_open failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
usb = (::aidl::android::hardware::usb::Usb *)client_data;
|
||||
value = usb->mUsbHubVendorCmdValue;
|
||||
index = usb->mUsbHubVendorCmdIndex;
|
||||
|
||||
// The vendor cmd only applies to USB Hubs of Genesys Logic, Inc.
|
||||
// The request field of vendor cmd is fixed to 0xe3.
|
||||
vendorId = usb_device_get_vendor_id(device);
|
||||
productId = usb_device_get_product_id(device);
|
||||
if (vendorId == GL852G_VENDOR_ID &&
|
||||
(productId == GL852G_PRODUCT_ID1 || productId == GL852G_PRODUCT_ID2)) {
|
||||
int ret = usb_device_control_transfer(device,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR, GL852G_VENDOR_CMD_REQ, value, index,
|
||||
NULL, 0, CTRL_TRANSFER_TIMEOUT_MSEC);
|
||||
ALOGI("USB hub vendor cmd %s (wValue 0x%x, wIndex 0x%x, return %d)\n",
|
||||
ret? "failed" : "succeeded", value, index, ret);
|
||||
}
|
||||
|
||||
usb_device_close(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *usbHostWork(void *param) {
|
||||
struct usb_host_context *ctx;
|
||||
|
||||
ALOGI("creating USB host thread\n");
|
||||
|
||||
ctx = usb_host_init();
|
||||
if (!ctx) {
|
||||
ALOGE("usb_host_init failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This will never return, it will keep monitoring USB sysfs inotify events
|
||||
usb_host_run(ctx, usbDeviceAdded, usbDeviceRemoved, NULL, param);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Usb::Usb()
|
||||
: mLock(PTHREAD_MUTEX_INITIALIZER),
|
||||
mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER),
|
||||
|
@ -542,7 +600,9 @@ Usb::Usb()
|
|||
mDisplayPortPollRunning(false),
|
||||
mDisplayPortPollStarting(false),
|
||||
mDisplayPortCVLock(PTHREAD_MUTEX_INITIALIZER),
|
||||
mDisplayPortLock(PTHREAD_MUTEX_INITIALIZER) {
|
||||
mDisplayPortLock(PTHREAD_MUTEX_INITIALIZER),
|
||||
mUsbHubVendorCmdValue(GL852G_VENDOR_CMD_VALUE_DEFAULT),
|
||||
mUsbHubVendorCmdIndex(GL852G_VENDOR_CMD_INDEX_DEFAULT) {
|
||||
pthread_condattr_t attr;
|
||||
if (pthread_condattr_init(&attr)) {
|
||||
ALOGE("pthread_condattr_init failed: %s", strerror(errno));
|
||||
|
@ -579,6 +639,10 @@ Usb::Usb()
|
|||
ALOGE("mDisplayPortActivateTimer timerfd failed: %s", strerror(errno));
|
||||
abort();
|
||||
}
|
||||
if (pthread_create(&mUsbHost, NULL, usbHostWork, this)) {
|
||||
ALOGE("pthread creation failed %d\n", errno);
|
||||
abort();
|
||||
}
|
||||
|
||||
ALOGI("feature flag enable_usb_data_compliance_warning: %d",
|
||||
usb_flags::enable_usb_data_compliance_warning());
|
||||
|
@ -1950,82 +2014,6 @@ void Usb::shutdownDisplayPortPoll(bool force) {
|
|||
}
|
||||
}
|
||||
|
||||
struct hub_vendor_cmd {
|
||||
// wValue filed of standard device request
|
||||
int value;
|
||||
// wIndex field of standard device request
|
||||
int index;
|
||||
// Output pipe to shell command
|
||||
int out;
|
||||
// Whether the hub is found
|
||||
bool found;
|
||||
};
|
||||
|
||||
static int usbDeviceAdded(const char *devname, void* client_data) {
|
||||
struct hub_vendor_cmd *cmd = (struct hub_vendor_cmd *)client_data;
|
||||
uint16_t vendorId, productId;
|
||||
struct usb_device *device = usb_device_open(devname);
|
||||
|
||||
if (!device) {
|
||||
dprintf(cmd->out, "usb_device_open failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The vendor cmd only applies to USB Hubs of Genesys Logic, Inc.
|
||||
// The request field of vendor cmd is fixed to 0xe3.
|
||||
vendorId = usb_device_get_vendor_id(device);
|
||||
productId = usb_device_get_product_id(device);
|
||||
if (vendorId == GL852G_VENDOR_ID &&
|
||||
(productId == GL852G_PRODUCT_ID1 || productId == GL852G_PRODUCT_ID2)) {
|
||||
int ret = usb_device_control_transfer(
|
||||
device, USB_DIR_OUT | USB_TYPE_VENDOR,
|
||||
GL852G_VENDOR_CMD_REQ, cmd->value, cmd->index, NULL, 0,
|
||||
CTRL_TRANSFER_TIMEOUT_MSEC);
|
||||
dprintf(cmd->out, "Vendor cmd %s (wValue %x, wIndex %x, return %d)\n",
|
||||
ret? "failed" : "succeeded", cmd->value, cmd->index, ret);
|
||||
// Stop iterating through usb devices once the hub is found.
|
||||
cmd->found = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbDiscoveryDone(void *client_data)
|
||||
{
|
||||
struct hub_vendor_cmd *cmd = (struct hub_vendor_cmd *)client_data;
|
||||
|
||||
dprintf(cmd->out, "Done USB discovery, hub %s found\n",
|
||||
cmd->found ? "is" : "not");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static status_t sendHubVendorCmd(int out, Vector<String8>& args) {
|
||||
if (args.size() < 3) {
|
||||
dprintf(out, "Incorrect number of argument supplied\n");
|
||||
return ::android::UNKNOWN_ERROR;
|
||||
}
|
||||
struct hub_vendor_cmd cmd = {
|
||||
.value = std::stoi(args[1].c_str(), NULL, 16),
|
||||
.index = std::stoi(args[2].c_str(), NULL, 16),
|
||||
.out = out,
|
||||
.found = false
|
||||
};
|
||||
|
||||
struct usb_host_context *ctx;
|
||||
ctx = usb_host_init();
|
||||
if (!ctx) {
|
||||
dprintf(out, "usb_host_init failed\n");
|
||||
return ::android::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
usb_host_run(ctx, usbDeviceAdded, NULL, usbDiscoveryDone, &cmd);
|
||||
usb_host_cleanup(ctx);
|
||||
|
||||
return ::android::NO_ERROR;
|
||||
}
|
||||
|
||||
status_t Usb::handleShellCommand(int in, int out, int err, const char** argv,
|
||||
uint32_t argc) {
|
||||
uid_t uid = AIBinder_getCallingUid();
|
||||
|
@ -2041,13 +2029,28 @@ status_t Usb::handleShellCommand(int in, int out, int err, const char** argv,
|
|||
|
||||
if (argc >= 1) {
|
||||
if (!utf8Args[0].compare(String8("hub-vendor-cmd"))) {
|
||||
return sendHubVendorCmd(out, utf8Args);
|
||||
if (utf8Args.size() < 3) {
|
||||
dprintf(out, "Incorrect number of argument supplied\n");
|
||||
return ::android::UNKNOWN_ERROR;
|
||||
}
|
||||
int value, index;
|
||||
if (!::android::base::ParseInt(utf8Args[1].c_str(), &value) ||
|
||||
!::android::base::ParseInt(utf8Args[2].c_str(), &index)) {
|
||||
dprintf(out, "Fail to parse arguments\n");
|
||||
return ::android::UNKNOWN_ERROR;
|
||||
}
|
||||
mUsbHubVendorCmdValue = value;
|
||||
mUsbHubVendorCmdIndex = index;
|
||||
ALOGI("USB hub vendor cmd update (wValue 0x%x, wIndex 0x%x)\n",
|
||||
mUsbHubVendorCmdValue, mUsbHubVendorCmdIndex);
|
||||
return ::android::NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf(out, "usage: adb shell cmd hub-vendor-cmd VALUE INDEX\n"
|
||||
" VALUE wValue field in hex format, e.g. f321\n"
|
||||
" INDEX wIndex field in hex format, e.g. f321\n");
|
||||
" VALUE wValue field in hex format, e.g. 0xf321\n"
|
||||
" INDEX wIndex field in hex format, e.g. 0xf321\n"
|
||||
" The settings take effect next time the hub is enabled\n");
|
||||
|
||||
return ::android::NO_ERROR;
|
||||
}
|
||||
|
|
|
@ -167,10 +167,15 @@ struct Usb : public BnUsb {
|
|||
*/
|
||||
bool mPartnerSupportsDisplayPort;
|
||||
|
||||
// Usb hub vendor command settings for JK level tuning
|
||||
int mUsbHubVendorCmdValue;
|
||||
int mUsbHubVendorCmdIndex;
|
||||
|
||||
private:
|
||||
pthread_t mPoll;
|
||||
pthread_t mDisplayPortPoll;
|
||||
pthread_t mDisplayPortShutdownHelper;
|
||||
pthread_t mUsbHost;
|
||||
};
|
||||
|
||||
} // namespace usb
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue