diff --git a/usb/usb/Usb.cpp b/usb/usb/Usb.cpp index 3944372..011c5e8 100644 --- a/usb/usb/Usb.cpp +++ b/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& 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; } diff --git a/usb/usb/Usb.h b/usb/usb/Usb.h index 91eea4f..96af846 100644 --- a/usb/usb/Usb.h +++ b/usb/usb/Usb.h @@ -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