diff options
| author | Albert Wang <albertccwang@google.com> | 2021-03-21 19:23:24 +0800 |
|---|---|---|
| committer | Albert Wang <albertccwang@google.com> | 2021-03-21 19:23:24 +0800 |
| commit | f9083c098a02dc8f18efaab0af4584442cc69d41 (patch) | |
| tree | 865179719b5849993e0e1ae1ae912a13ebb06221 /usb | |
| parent | c85f9efbd4eaae3ac9bdc9acb24306934920487f (diff) | |
Add USB Gadget HAL 1.2 support
Bug: 181938674
Test: Pass USB Gadget V1.2 HIDL tests
Signed-off-by: Albert Wang <albertccwang@google.com>
Change-Id: I17da3e7a22eea008663fafdd7b8a4be6cce0745a
Diffstat (limited to 'usb')
| -rw-r--r-- | usb/Android.bp | 4 | ||||
| -rw-r--r-- | usb/UsbGadget.cpp | 884 | ||||
| -rw-r--r-- | usb/UsbGadget.h | 56 | ||||
| -rw-r--r-- | usb/android.hardware.usb.gadget@1.2-service.bonito.xml (renamed from usb/android.hardware.usb.gadget@1.1-service.bonito.xml) | 2 | ||||
| -rw-r--r-- | usb/service.cpp | 4 |
5 files changed, 348 insertions, 602 deletions
diff --git a/usb/Android.bp b/usb/Android.bp index cc21f754..7cee21de 100644 --- a/usb/Android.bp +++ b/usb/Android.bp @@ -22,7 +22,7 @@ cc_binary { init_rc: ["android.hardware.usb@1.2-service.bonito.rc"], vintf_fragments: [ "android.hardware.usb@1.2-service.bonito.xml", - "android.hardware.usb.gadget@1.1-service.bonito.xml", + "android.hardware.usb.gadget@1.2-service.bonito.xml", ], srcs: ["service.cpp", "Usb.cpp", "UsbGadget.cpp"], shared_libs: [ @@ -36,7 +36,9 @@ cc_binary { "android.hardware.usb@1.2", "android.hardware.usb.gadget@1.0", "android.hardware.usb.gadget@1.1", + "android.hardware.usb.gadget@1.2", "libcutils", ], + static_libs: ["libpixelusb"], proprietary: true, } diff --git a/usb/UsbGadget.cpp b/usb/UsbGadget.cpp index 58daf242..333d1fd4 100644 --- a/usb/UsbGadget.cpp +++ b/usb/UsbGadget.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "android.hardware.usb.gadget@1.1-service.bonito" +#define LOG_TAG "android.hardware.usb.gadget@1.2-service.bonito" #include "UsbGadget.h" #include <dirent.h> @@ -26,635 +26,373 @@ #include <sys/types.h> #include <unistd.h> -constexpr int BUFFER_SIZE = 512; -constexpr int MAX_FILE_PATH_LENGTH = 256; -constexpr int EPOLL_EVENTS = 10; -constexpr bool DEBUG = false; -constexpr int DISCONNECT_WAIT_US = 100000; -constexpr int PULL_UP_DELAY = 500000; - -#define BUILD_TYPE "ro.build.type" -#define GADGET_PATH "/config/usb_gadget/g1/" -#define PULLUP_PATH GADGET_PATH "UDC" -#define GADGET_NAME "a600000.dwc3" -#define PERSISTENT_BOOT_MODE "ro.bootmode" -#define VENDOR_ID_PATH GADGET_PATH "idVendor" -#define PRODUCT_ID_PATH GADGET_PATH "idProduct" -#define DEVICE_CLASS_PATH GADGET_PATH "bDeviceClass" -#define DEVICE_SUB_CLASS_PATH GADGET_PATH "bDeviceSubClass" -#define DEVICE_PROTOCOL_PATH GADGET_PATH "bDeviceProtocol" -#define DESC_USE_PATH GADGET_PATH "os_desc/use" -#define OS_DESC_PATH GADGET_PATH "os_desc/b.1" -#define CONFIG_PATH GADGET_PATH "configs/b.1/" -#define FUNCTIONS_PATH GADGET_PATH "functions/" -#define FUNCTION_NAME "function" -#define FUNCTION_PATH CONFIG_PATH FUNCTION_NAME -#define RNDIS_PATH FUNCTIONS_PATH "gsi.rndis" - -#define PERSISTENT_VENDOR_CONFIG "persist.vendor.usb.usbradio.config" -#define VENDOR_CONFIG "vendor.usb.config" - namespace android { namespace hardware { namespace usb { namespace gadget { -namespace V1_1 { +namespace V1_2 { namespace implementation { -volatile bool gadgetPullup; - -// Used for debug. -static void displayInotifyEvent(struct inotify_event *i) { - ALOGE(" wd =%2d; ", i->wd); - if (i->cookie > 0) ALOGE("cookie =%4d; ", i->cookie); - - ALOGE("mask = "); - if (i->mask & IN_ACCESS) ALOGE("IN_ACCESS "); - if (i->mask & IN_ATTRIB) ALOGE("IN_ATTRIB "); - if (i->mask & IN_CLOSE_NOWRITE) ALOGE("IN_CLOSE_NOWRITE "); - if (i->mask & IN_CLOSE_WRITE) ALOGE("IN_CLOSE_WRITE "); - if (i->mask & IN_CREATE) ALOGE("IN_CREATE "); - if (i->mask & IN_DELETE) ALOGE("IN_DELETE "); - if (i->mask & IN_DELETE_SELF) ALOGE("IN_DELETE_SELF "); - if (i->mask & IN_IGNORED) ALOGE("IN_IGNORED "); - if (i->mask & IN_ISDIR) ALOGE("IN_ISDIR "); - if (i->mask & IN_MODIFY) ALOGE("IN_MODIFY "); - if (i->mask & IN_MOVE_SELF) ALOGE("IN_MOVE_SELF "); - if (i->mask & IN_MOVED_FROM) ALOGE("IN_MOVED_FROM "); - if (i->mask & IN_MOVED_TO) ALOGE("IN_MOVED_TO "); - if (i->mask & IN_OPEN) ALOGE("IN_OPEN "); - if (i->mask & IN_Q_OVERFLOW) ALOGE("IN_Q_OVERFLOW "); - if (i->mask & IN_UNMOUNT) ALOGE("IN_UNMOUNT "); - ALOGE("\n"); - - if (i->len > 0) ALOGE(" name = %s\n", i->name); -} - -static void *monitorFfs(void *param) { - UsbGadget *usbGadget = (UsbGadget *)param; - char buf[BUFFER_SIZE]; - bool writeUdc = true, stopMonitor = false; - struct epoll_event events[EPOLL_EVENTS]; - steady_clock::time_point disconnect; - - bool descriptorWritten = true; - for (int i = 0; i < static_cast<int>(usbGadget->mEndpointList.size()); i++) { - if (access(usbGadget->mEndpointList.at(i).c_str(), R_OK)) { - descriptorWritten = false; - break; - } - } - - // notify here if the endpoints are already present. - if (descriptorWritten) { - usleep(PULL_UP_DELAY); - if (!!WriteStringToFile(GADGET_NAME, PULLUP_PATH)) { - lock_guard<mutex> lock(usbGadget->mLock); - usbGadget->mCurrentUsbFunctionsApplied = true; - gadgetPullup = true; - writeUdc = false; - ALOGI("GADGET pulled up"); - usbGadget->mCv.notify_all(); - } - } - - while (!stopMonitor) { - int nrEvents = epoll_wait(usbGadget->mEpollFd, events, EPOLL_EVENTS, -1); - - if (nrEvents <= 0) { - ALOGE("epoll wait did not return descriptor number"); - continue; +UsbGadget::UsbGadget() { + if (access(OS_DESC_PATH, R_OK) != 0) { + ALOGE("configfs setup not done yet"); + abort(); } - - for (int i = 0; i < nrEvents; i++) { - ALOGI("event=%u on fd=%d\n", events[i].events, events[i].data.fd); - - if (events[i].data.fd == usbGadget->mInotifyFd) { - // Process all of the events in buffer returned by read(). - int numRead = read(usbGadget->mInotifyFd, buf, BUFFER_SIZE); - for (char *p = buf; p < buf + numRead;) { - struct inotify_event *event = (struct inotify_event *)p; - if (DEBUG) displayInotifyEvent(event); - - p += sizeof(struct inotify_event) + event->len; - - bool descriptorPresent = true; - for (int j = 0; j < static_cast<int>(usbGadget->mEndpointList.size()); - j++) { - if (access(usbGadget->mEndpointList.at(j).c_str(), R_OK)) { - if (DEBUG) - ALOGI("%s absent", usbGadget->mEndpointList.at(j).c_str()); - descriptorPresent = false; - break; - } - } - - if (!descriptorPresent && !writeUdc) { - if (DEBUG) ALOGI("endpoints not up"); - writeUdc = true; - disconnect = std::chrono::steady_clock::now(); - } else if (descriptorPresent && writeUdc) { - steady_clock::time_point temp = steady_clock::now(); - - if (std::chrono::duration_cast<microseconds>(temp - disconnect).count() - < PULL_UP_DELAY) - usleep(PULL_UP_DELAY); - - if(!!WriteStringToFile(GADGET_NAME, PULLUP_PATH)) { - lock_guard<mutex> lock(usbGadget->mLock); - usbGadget->mCurrentUsbFunctionsApplied = true; - ALOGI("GADGET pulled up"); - writeUdc = false; - gadgetPullup = true; - // notify the main thread to signal userspace. - usbGadget->mCv.notify_all(); - } - } - } - } else { - uint64_t flag; - read(usbGadget->mEventFd, &flag, sizeof(flag)); - if (flag == 100) { - stopMonitor = true; - break; - } - } - } - } - return NULL; } -UsbGadget::UsbGadget() - : mMonitorCreated(false), mCurrentUsbFunctionsApplied(false) { - if (access(OS_DESC_PATH, R_OK) != 0) ALOGE("configfs setup not done yet"); +void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) { + UsbGadget *gadget = (UsbGadget *)payload; + gadget->mCurrentUsbFunctionsApplied = functionsApplied; } -static int unlinkFunctions(const char *path) { - DIR *config = opendir(path); - struct dirent *function; - char filepath[MAX_FILE_PATH_LENGTH]; - int ret = 0; - - if (config == NULL) return -1; - - // d_type does not seems to be supported in /config - // so filtering by name. - while (((function = readdir(config)) != NULL)) { - if ((strstr(function->d_name, FUNCTION_NAME) == NULL)) continue; - // build the path for each file in the folder. - sprintf(filepath, "%s/%s", path, function->d_name); - ret = remove(filepath); - if (ret) { - ALOGE("Unable remove file %s errno:%d", filepath, errno); - break; - } - } +Return<void> UsbGadget::getCurrentUsbFunctions(const sp<V1_0::IUsbGadgetCallback> &callback) { + Return<void> ret = callback->getCurrentUsbFunctionsCb( + mCurrentUsbFunctions, + mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED); + if (!ret.isOk()) + ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.description().c_str()); - closedir(config); - return ret; + return Void(); } -static int addEpollFd(const unique_fd &epfd, const unique_fd &fd) { - struct epoll_event event; - int ret; - - event.data.fd = fd; - event.events = EPOLLIN; +Return<void> UsbGadget::getUsbSpeed(const sp<V1_2::IUsbGadgetCallback> &callback) { + std::string current_speed; + if (ReadFileToString(SPEED_PATH, ¤t_speed)) { + current_speed = Trim(current_speed); + ALOGI("current USB speed is %s", current_speed.c_str()); + if (current_speed == "low-speed") + mUsbSpeed = UsbSpeed::LOWSPEED; + else if (current_speed == "full-speed") + mUsbSpeed = UsbSpeed::FULLSPEED; + else if (current_speed == "high-speed") + mUsbSpeed = UsbSpeed::HIGHSPEED; + else if (current_speed == "super-speed") + mUsbSpeed = UsbSpeed::SUPERSPEED; + else if (current_speed == "super-speed-plus") + mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb; + else if (current_speed == "UNKNOWN") + mUsbSpeed = UsbSpeed::UNKNOWN; + else + mUsbSpeed = UsbSpeed::RESERVED_SPEED; + } else { + ALOGE("Fail to read current speed"); + mUsbSpeed = UsbSpeed::UNKNOWN; + } - ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); - if (ret) ALOGE("epoll_ctl error %d", errno); + if (callback) { + Return<void> ret = callback->getUsbSpeedCb(mUsbSpeed); - return ret; -} + if (!ret.isOk()) + ALOGE("Call to getUsbSpeedCb failed %s", ret.description().c_str()); + } -Return<void> UsbGadget::getCurrentUsbFunctions( - const sp<V1_0::IUsbGadgetCallback> &callback) { - Return<void> ret = callback->getCurrentUsbFunctionsCb( - mCurrentUsbFunctions, mCurrentUsbFunctionsApplied - ? Status::FUNCTIONS_APPLIED - : Status::FUNCTIONS_NOT_APPLIED); - if (!ret.isOk()) - ALOGE("Call to getCurrentUsbFunctionsCb failed %s", - ret.description().c_str()); - - return Void(); + return Void(); } V1_0::Status UsbGadget::tearDownGadget() { - ALOGI("setCurrentUsbFunctions None"); - - if (!WriteStringToFile("none", PULLUP_PATH)) - ALOGI("Gadget cannot be pulled down"); - - if (!WriteStringToFile("0", DEVICE_CLASS_PATH)) return Status::ERROR; - - if (!WriteStringToFile("0", DEVICE_SUB_CLASS_PATH)) return Status::ERROR; - - if (!WriteStringToFile("0", DEVICE_PROTOCOL_PATH)) return Status::ERROR; - - if (!WriteStringToFile("0", DESC_USE_PATH)) return Status::ERROR; - - if (unlinkFunctions(CONFIG_PATH)) return Status::ERROR; - - if (mMonitorCreated) { - uint64_t flag = 100; - unsigned long ret; + if (resetGadget() != Status::SUCCESS) + return Status::ERROR; - // Stop the monitor thread by writing into signal fd. - ret = TEMP_FAILURE_RETRY(write(mEventFd, &flag, sizeof(flag))); - if (ret < 0) { - ALOGE("Error writing errno=%d", errno); - } else if (ret < sizeof(flag)) { - ALOGE("Short write length=%zd", ret); + if (monitorFfs.isMonitorRunning()) { + monitorFfs.reset(); + } else { + ALOGI("mMonitor not running"); } + return Status::SUCCESS; +} - ALOGI("mMonitor signalled to exit"); - mMonitor->join(); - mMonitorCreated = false; - ALOGI("mMonitor destroyed"); - } else { - ALOGI("mMonitor not running"); - } - - mInotifyFd.reset(-1); - mEventFd.reset(-1); - mEpollFd.reset(-1); - mEndpointList.clear(); - return Status::SUCCESS; +static V1_0::Status validateAndSetVidPid(uint64_t functions) { + V1_0::Status ret = Status::SUCCESS; + std::string vendorFunctions = getVendorFunctions(); + + switch (functions) { + case static_cast<uint64_t>(GadgetFunction::MTP): + if (vendorFunctions == "diag") { + ret = setVidPid("0x05C6", "0x901B"); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee1"); + } + } + break; + + case GadgetFunction::ADB | GadgetFunction::MTP: + if (vendorFunctions == "diag") { + ret = setVidPid("0x05C6", "0x903A"); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee2"); + } + } + break; + + case static_cast<uint64_t>(GadgetFunction::RNDIS): + if (vendorFunctions == "diag") { + ret = setVidPid("0x05C6", "0x902C"); + } else if (vendorFunctions == "serial_cdev,diag") { + ret = setVidPid("0x05C6", "0x90B5"); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee3"); + } + } + break; + + case GadgetFunction::ADB | GadgetFunction::RNDIS: + if (vendorFunctions == "diag") { + ret = setVidPid("0x05C6", "0x902D"); + } else if (vendorFunctions == "serial_cdev,diag") { + ret = setVidPid("0x05C6", "0x90B6"); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee4"); + } + } + break; + + case static_cast<uint64_t>(GadgetFunction::PTP): + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee5"); + } + break; + + case GadgetFunction::ADB | GadgetFunction::PTP: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee6"); + } + break; + + case static_cast<uint64_t>(GadgetFunction::ADB): + if (vendorFunctions == "diag") { + ret = setVidPid("0x05C6", "0x901D"); + } else if (vendorFunctions == "diag,serial_cdev,rmnet_gsi") { + ret = setVidPid("0x05C6", "0x9091"); + } else if (vendorFunctions == "diag,serial_cdev") { + ret = setVidPid("0x05C6", "0x901F"); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee7"); + } + } + break; + + case static_cast<uint64_t>(GadgetFunction::MIDI): + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee8"); + } + break; + + case GadgetFunction::ADB | GadgetFunction::MIDI: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = setVidPid("0x18d1", "0x4ee9"); + } + break; + + case static_cast<uint64_t>(GadgetFunction::ACCESSORY): + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = setVidPid("0x18d1", "0x2d00"); + break; + + case GadgetFunction::ADB | GadgetFunction::ACCESSORY: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = setVidPid("0x18d1", "0x2d01"); + break; + + case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE): + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = setVidPid("0x18d1", "0x2d02"); + break; + + case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = setVidPid("0x18d1", "0x2d03"); + break; + + case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = setVidPid("0x18d1", "0x2d04"); + break; + + case GadgetFunction::ADB | GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = setVidPid("0x18d1", "0x2d05"); + break; + + default: + ALOGE("Combination not supported"); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } + return ret; } Return<Status> UsbGadget::reset() { + ALOGI("USB Gadget reset"); + if (!WriteStringToFile("none", PULLUP_PATH)) { ALOGI("Gadget cannot be pulled down"); return Status::ERROR; } + usleep(kDisconnectWaitUs); + + if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) { + ALOGI("Gadget cannot be pulled up"); + return Status::ERROR; + } + return Status::SUCCESS; } -static int linkFunction(const char *function, int index) { - char functionPath[MAX_FILE_PATH_LENGTH]; - char link[MAX_FILE_PATH_LENGTH]; - - sprintf(functionPath, "%s%s", FUNCTIONS_PATH, function); - sprintf(link, "%s%d", FUNCTION_PATH, index); - if (symlink(functionPath, link)) { - ALOGE("Cannot create symlink %s -> %s errno:%d", link, functionPath, errno); - return -1; - } - return 0; -} +V1_0::Status UsbGadget::setupFunctions(uint64_t functions, + const sp<V1_0::IUsbGadgetCallback> &callback, + uint64_t timeout) { + bool ffsEnabled = false; + int i = 0; -static V1_0::Status setVidPid(const char *vid, const char *pid) { - if (!WriteStringToFile(vid, VENDOR_ID_PATH)) return Status::ERROR; + uint64_t usbFunctions = functions; + const std::string vendorRndisConfig = GetProperty(google::pixel::usb::kVendorRndisConfig, ""); - if (!WriteStringToFile(pid, PRODUCT_ID_PATH)) return Status::ERROR; + if (addGenericAndroidFunctions(&monitorFfs, usbFunctions, &ffsEnabled, &i) != Status::SUCCESS) + return Status::ERROR; - return Status::SUCCESS; -} + std::string vendorFunctions = getVendorFunctions(); -static std::string getVendorFunctions() { - if (GetProperty(BUILD_TYPE, "") == "user") return "user"; - - std::string bootMode = GetProperty(PERSISTENT_BOOT_MODE, ""); - std::string persistVendorFunctions = - GetProperty(PERSISTENT_VENDOR_CONFIG, ""); - std::string vendorFunctions = GetProperty(VENDOR_CONFIG, ""); - std::string ret = ""; - - if (vendorFunctions != "") { - ret = vendorFunctions; - } else if (bootMode == "usbradio") { - if (persistVendorFunctions != "") - ret = persistVendorFunctions; - else - ret = "diag"; - // vendor.usb.config will reflect the current configured functions - SetProperty(VENDOR_CONFIG, ret); - } - - return ret; -} + if (vendorFunctions != "") { + ALOGI("enable usbradio debug functions"); + char *function = strtok(const_cast<char *>(vendorFunctions.c_str()), ","); -static V1_0::Status validateAndSetVidPid(uint64_t functions) { - V1_0::Status ret = Status::SUCCESS; - std::string vendorFunctions = getVendorFunctions(); - - switch (functions) { - case static_cast<uint64_t>(GadgetFunction::MTP): - if (vendorFunctions == "diag") { - ret = setVidPid("0x05C6", "0x901B"); - } else { - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee1"); - } - break; - case GadgetFunction::ADB | GadgetFunction::MTP: - if (vendorFunctions == "diag") { - ret = setVidPid("0x05C6", "0x903A"); - } else { - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee2"); - } - break; - case static_cast<uint64_t>(GadgetFunction::RNDIS): - if (vendorFunctions == "diag") { - ret = setVidPid("0x05C6", "0x902C"); - } else if (vendorFunctions == "serial_cdev,diag") { - ret = setVidPid("0x05C6", "0x90B5"); - } else { - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee3"); - } - break; - case GadgetFunction::ADB | GadgetFunction::RNDIS: - if (vendorFunctions == "diag") { - ret = setVidPid("0x05C6", "0x902D"); - } else if (vendorFunctions == "serial_cdev,diag") { - ret = setVidPid("0x05C6", "0x90B6"); - } else { - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee4"); - } - break; - case static_cast<uint64_t>(GadgetFunction::PTP): - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee5"); - break; - case GadgetFunction::ADB | GadgetFunction::PTP: - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee6"); - break; - case static_cast<uint64_t>(GadgetFunction::ADB): - if (vendorFunctions == "diag") { - ret = setVidPid("0x05C6", "0x901D"); - } else if (vendorFunctions == "diag,serial_cdev,rmnet_gsi") { - ret = setVidPid("0x05C6", "0x9091"); - } else if (vendorFunctions == "diag,serial_cdev") { - ret = setVidPid("0x05C6", "0x901F"); - } else { - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee7"); - } - break; - case static_cast<uint64_t>(GadgetFunction::MIDI): - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee8"); - break; - case GadgetFunction::ADB | GadgetFunction::MIDI: - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x4ee9"); - break; - case static_cast<uint64_t>(GadgetFunction::ACCESSORY): - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x2d00"); - break; - case GadgetFunction::ADB | GadgetFunction::ACCESSORY: - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x2d01"); - break; - case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE): - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x2d02"); - break; - case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE: - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x2d03"); - break; - case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE: - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x2d04"); - break; - case GadgetFunction::ADB | GadgetFunction::ACCESSORY | - GadgetFunction::AUDIO_SOURCE: - if (!(vendorFunctions == "user" || vendorFunctions == "")) - ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); - ret = setVidPid("0x18d1", "0x2d05"); - break; - default: - ALOGE("Combination not supported"); - ret = Status::CONFIGURATION_NOT_SUPPORTED; - } - return ret; -} + while (function != NULL) { + if (string(function) == "diag" && linkFunction("diag.diag", i++)) + return Status::ERROR; + if (string(function) == "serial_cdev" && linkFunction("cser.dun.0", i++)) + return Status::ERROR; + if (string(function) == "rmnet_gsi" && linkFunction("gsi.rmnet", i++)) + return Status::ERROR; + } + } -V1_0::Status UsbGadget::setupFunctions( - uint64_t functions, const sp<V1_0::IUsbGadgetCallback> &callback, - uint64_t timeout) { - std::unique_lock<std::mutex> lk(mLock); - - unique_fd inotifyFd(inotify_init()); - if (inotifyFd < 0) { - ALOGE("inotify init failed"); - return Status::ERROR; - } - - bool ffsEnabled = false; - int i = 0; - std::string bootMode = GetProperty(PERSISTENT_BOOT_MODE, ""); - - if (((functions & GadgetFunction::MTP) != 0)) { - ffsEnabled = true; - ALOGI("setCurrentUsbFunctions mtp"); - if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR; - - if (inotify_add_watch(inotifyFd, "/dev/usb-ffs/mtp/", IN_ALL_EVENTS) == -1) - return Status::ERROR; - - if (linkFunction("ffs.mtp", i++)) return Status::ERROR; - - // Add endpoints to be monitored. - mEndpointList.push_back("/dev/usb-ffs/mtp/ep1"); - mEndpointList.push_back("/dev/usb-ffs/mtp/ep2"); - mEndpointList.push_back("/dev/usb-ffs/mtp/ep3"); - } else if (((functions & GadgetFunction::PTP) != 0)) { - ffsEnabled = true; - ALOGI("setCurrentUsbFunctions ptp"); - if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR; - - if (inotify_add_watch(inotifyFd, "/dev/usb-ffs/ptp/", IN_ALL_EVENTS) == -1) - return Status::ERROR; - - - if (linkFunction("ffs.ptp", i++)) return Status::ERROR; - - // Add endpoints to be monitored. - mEndpointList.push_back("/dev/usb-ffs/ptp/ep1"); - mEndpointList.push_back("/dev/usb-ffs/ptp/ep2"); - mEndpointList.push_back("/dev/usb-ffs/ptp/ep3"); - } - - if ((functions & GadgetFunction::MIDI) != 0) { - ALOGI("setCurrentUsbFunctions MIDI"); - if (linkFunction("midi.gs5", i++)) return Status::ERROR; - } - - if ((functions & GadgetFunction::ACCESSORY) != 0) { - ALOGI("setCurrentUsbFunctions Accessory"); - if (linkFunction("accessory.gs2", i++)) return Status::ERROR; - } - - if ((functions & GadgetFunction::AUDIO_SOURCE) != 0) { - ALOGI("setCurrentUsbFunctions Audio Source"); - if (linkFunction("audio_source.gs3", i++)) return Status::ERROR; - } - - if ((functions & GadgetFunction::RNDIS) != 0) { - ALOGI("setCurrentUsbFunctions rndis"); - if (linkFunction("gsi.rndis", i++)) return Status::ERROR; - } - - std::string vendorFunctions = getVendorFunctions(); - if (vendorFunctions != "") { - ALOGI("enable usbradio debug functions"); - char *function = strtok(const_cast<char *>(vendorFunctions.c_str()), ","); - while (function != NULL) { - if (string(function) == "diag" && linkFunction("diag.diag", i++)) - return Status::ERROR; - if (string(function) == "serial_cdev" && linkFunction("cser.dun.0", i++)) - return Status::ERROR; - if (string(function) == "rmnet_gsi" && linkFunction("gsi.rmnet", i++)) - return Status::ERROR; - function = strtok(NULL, ","); + if ((usbFunctions & GadgetFunction::ADB) != 0) { + ffsEnabled = true; + if (addAdb(&monitorFfs, &i) != Status::SUCCESS) + return Status::ERROR; } - } - - if ((functions & GadgetFunction::ADB) != 0) { - ffsEnabled = true; - ALOGI("setCurrentUsbFunctions Adb"); - if (!WriteStringToFile("1", DESC_USE_PATH)) - return Status::ERROR; - if (inotify_add_watch(inotifyFd, "/dev/usb-ffs/adb/", IN_ALL_EVENTS) == -1) - return Status::ERROR; - - if (linkFunction("ffs.adb", i++)) return Status::ERROR; - mEndpointList.push_back("/dev/usb-ffs/adb/ep1"); - mEndpointList.push_back("/dev/usb-ffs/adb/ep2"); - ALOGI("Service started"); - } - - // Pull up the gadget right away when there are no ffs functions. - if (!ffsEnabled) { - if (!WriteStringToFile(GADGET_NAME, PULLUP_PATH)) return Status::ERROR; - mCurrentUsbFunctionsApplied = true; - if (callback) - callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS); - return Status::SUCCESS; - } - - unique_fd eventFd(eventfd(0, 0)); - if (eventFd == -1) { - ALOGE("mEventFd failed to create %d", errno); - return Status::ERROR; - } - - unique_fd epollFd(epoll_create(2)); - if (epollFd == -1) { - ALOGE("mEpollFd failed to create %d", errno); - return Status::ERROR; - } - - if (addEpollFd(epollFd, inotifyFd) == -1) return Status::ERROR; - - if (addEpollFd(epollFd, eventFd) == -1) return Status::ERROR; - - mEpollFd = move(epollFd); - mInotifyFd = move(inotifyFd); - mEventFd = move(eventFd); - gadgetPullup = false; - - // Monitors the ffs paths to pull up the gadget when descriptors are written. - // Also takes of the pulling up the gadget again if the userspace process - // dies and restarts. - mMonitor = unique_ptr<thread>(new thread(monitorFfs, this)); - mMonitorCreated = true; - if (DEBUG) ALOGI("Mainthread in Cv"); - - if (callback) { - if (mCv.wait_for(lk, timeout * 1ms, [] { return gadgetPullup; })) { - ALOGI("monitorFfs signalled true"); - } else { - ALOGI("monitorFfs signalled error"); - // continue monitoring as the descriptors might be written at a later - // point. + + // Pull up the gadget right away when there are no ffs functions. + if (!ffsEnabled) { + if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) + return Status::ERROR; + mCurrentUsbFunctionsApplied = true; + if (callback) + callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS); + return Status::SUCCESS; } - Return<void> ret = callback->setCurrentUsbFunctionsCb( - functions, gadgetPullup ? Status::SUCCESS : Status::ERROR); - if (!ret.isOk()) - ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str()); - } - return Status::SUCCESS; + monitorFfs.registerFunctionsAppliedCallback(¤tFunctionsAppliedCallback, this); + // Monitors the ffs paths to pull up the gadget when descriptors are written. + // Also takes of the pulling up the gadget again if the userspace process + // dies and restarts. + monitorFfs.startMonitor(); + + if (kDebug) + ALOGI("Mainthread in Cv"); + + if (callback) { + bool pullup = monitorFfs.waitForPullUp(timeout); + Return<void> ret = callback->setCurrentUsbFunctionsCb( + functions, pullup ? Status::SUCCESS : Status::ERROR); + if (!ret.isOk()) + ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str()); + } + + return Status::SUCCESS; } -Return<void> UsbGadget::setCurrentUsbFunctions( - uint64_t functions, const sp<V1_0::IUsbGadgetCallback> &callback, - uint64_t timeout) { - std::unique_lock<std::mutex> lk(mLockSetCurrentFunction); +Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions, + const sp<V1_0::IUsbGadgetCallback> &callback, + uint64_t timeout) { + std::unique_lock<std::mutex> lk(mLockSetCurrentFunction); - mCurrentUsbFunctions = functions; - mCurrentUsbFunctionsApplied = false; + mCurrentUsbFunctions = functions; + mCurrentUsbFunctionsApplied = false; - // Unlink the gadget and stop the monitor if running. - V1_0::Status status = tearDownGadget(); - if (status != Status::SUCCESS) { - goto error; - } + // Unlink the gadget and stop the monitor if running. + V1_0::Status status = tearDownGadget(); + if (status != Status::SUCCESS) { + goto error; + } - ALOGI("Returned from tearDown gadget"); + ALOGI("Returned from tearDown gadget"); - // Leave the gadget pulled down to give time for the host to sense disconnect. - usleep(DISCONNECT_WAIT_US); + // Leave the gadget pulled down to give time for the host to sense disconnect. + usleep(kDisconnectWaitUs); - if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) { - if (callback == NULL) return Void(); - Return<void> ret = - callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS); - if (!ret.isOk()) - ALOGE("Error while calling setCurrentUsbFunctionsCb %s", - ret.description().c_str()); - return Void(); - } + if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) { + if (callback == NULL) + return Void(); + Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS); + if (!ret.isOk()) + ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str()); + return Void(); + } - status = validateAndSetVidPid(functions); + status = validateAndSetVidPid(functions); - if (status != Status::SUCCESS) { - goto error; - } + if (status != Status::SUCCESS) { + goto error; + } - status = setupFunctions(functions, callback, timeout); - if (status != Status::SUCCESS) { - goto error; - } + status = setupFunctions(functions, callback, timeout); + if (status != Status::SUCCESS) { + goto error; + } - ALOGI("Usb Gadget setcurrent functions called successfully"); - return Void(); + ALOGI("Usb Gadget setcurrent functions called successfully"); + return Void(); error: - ALOGI("Usb Gadget setcurrent functions failed"); - if (callback == NULL) return Void(); - Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status); - if (!ret.isOk()) - ALOGE("Error while calling setCurrentUsbFunctionsCb %s", - ret.description().c_str()); - return Void(); + ALOGI("Usb Gadget setcurrent functions failed"); + if (callback == NULL) + return Void(); + Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status); + if (!ret.isOk()) + ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str()); + return Void(); } } // namespace implementation -} // namespace V1_1 +} // namespace V1_2 } // namespace gadget } // namespace usb } // namespace hardware diff --git a/usb/UsbGadget.h b/usb/UsbGadget.h index 327be9ad..9bada7b3 100644 --- a/usb/UsbGadget.h +++ b/usb/UsbGadget.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,13 @@ #include <android-base/file.h> #include <android-base/properties.h> +#include <android-base/strings.h> #include <android-base/unique_fd.h> -#include <android/hardware/usb/gadget/1.1/IUsbGadget.h> +#include <android/hardware/usb/gadget/1.2/IUsbGadget.h> +#include <android/hardware/usb/gadget/1.2/types.h> #include <hidl/MQDescriptor.h> #include <hidl/Status.h> +#include <pixelusb/UsbGadgetCommon.h> #include <sys/epoll.h> #include <sys/eventfd.h> #include <utils/Log.h> @@ -35,12 +38,14 @@ namespace android { namespace hardware { namespace usb { namespace gadget { -namespace V1_1 { +namespace V1_2 { namespace implementation { using ::android::sp; using ::android::base::GetProperty; +using ::android::base::ReadFileToString; using ::android::base::SetProperty; +using ::android::base::Trim; using ::android::base::unique_fd; using ::android::base::WriteStringToFile; using ::android::hardware::hidl_array; @@ -49,37 +54,36 @@ using ::android::hardware::hidl_string; using ::android::hardware::hidl_vec; using ::android::hardware::Return; using ::android::hardware::Void; -using ::android::hardware::usb::gadget::V1_0::GadgetFunction; +using ::android::hardware::google::pixel::usb::addAdb; +using ::android::hardware::google::pixel::usb::addEpollFd; +using ::android::hardware::google::pixel::usb::getVendorFunctions; +using ::android::hardware::google::pixel::usb::kDebug; +using ::android::hardware::google::pixel::usb::kDisconnectWaitUs; +using ::android::hardware::google::pixel::usb::linkFunction; +using ::android::hardware::google::pixel::usb::MonitorFfs; +using ::android::hardware::google::pixel::usb::resetGadget; +using ::android::hardware::google::pixel::usb::setVidPid; +using ::android::hardware::google::pixel::usb::unlinkFunctions; +using ::android::hardware::usb::gadget::V1_0::IUsbGadgetCallback; using ::android::hardware::usb::gadget::V1_0::Status; -using ::android::hardware::usb::gadget::V1_1::IUsbGadget; -using ::std::lock_guard; -using ::std::move; -using ::std::mutex; +using ::android::hardware::usb::gadget::V1_2::GadgetFunction; +using ::android::hardware::usb::gadget::V1_2::IUsbGadget; using ::std::string; -using ::std::thread; -using ::std::unique_ptr; -using ::std::vector; -using ::std::chrono::steady_clock; -using namespace std::chrono; -using namespace std::chrono_literals; + +constexpr char kGadgetName[] = "a600000.dwc3"; +#define UDC_PATH "/sys/class/udc/a600000.dwc3/" +static MonitorFfs monitorFfs(kGadgetName); + +#define SPEED_PATH UDC_PATH "current_speed" struct UsbGadget : public IUsbGadget { UsbGadget(); - unique_fd mInotifyFd; - unique_fd mEventFd; - unique_fd mEpollFd; - - unique_ptr<thread> mMonitor; - volatile bool mMonitorCreated; - vector<string> mEndpointList; - // protects the CV. - std::mutex mLock; - std::condition_variable mCv; // Makes sure that only one request is processed at a time. std::mutex mLockSetCurrentFunction; uint64_t mCurrentUsbFunctions; bool mCurrentUsbFunctionsApplied; + UsbSpeed mUsbSpeed; Return<void> setCurrentUsbFunctions(uint64_t functions, const sp<V1_0::IUsbGadgetCallback> &callback, @@ -89,6 +93,8 @@ struct UsbGadget : public IUsbGadget { Return<Status> reset() override; + Return<void> getUsbSpeed(const sp<V1_2::IUsbGadgetCallback> &callback) override; + private: Status tearDownGadget(); Status setupFunctions(uint64_t functions, const sp<V1_0::IUsbGadgetCallback> &callback, @@ -96,7 +102,7 @@ private: }; } // namespace implementation -} // namespace V1_1 +} // namespace V1_2 } // namespace gadget } // namespace usb } // namespace hardware diff --git a/usb/android.hardware.usb.gadget@1.1-service.bonito.xml b/usb/android.hardware.usb.gadget@1.2-service.bonito.xml index a6f9a1f4..8557f6ff 100644 --- a/usb/android.hardware.usb.gadget@1.1-service.bonito.xml +++ b/usb/android.hardware.usb.gadget@1.2-service.bonito.xml @@ -2,7 +2,7 @@ <hal format="hidl"> <name>android.hardware.usb.gadget</name> <transport>hwbinder</transport> - <version>1.1</version> + <version>1.2</version> <interface> <name>IUsbGadget</name> <instance>default</instance> diff --git a/usb/service.cpp b/usb/service.cpp index 5fc14319..fe9be45d 100644 --- a/usb/service.cpp +++ b/usb/service.cpp @@ -27,8 +27,8 @@ using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; // Generated HIDL files -using android::hardware::usb::gadget::V1_1::IUsbGadget; -using android::hardware::usb::gadget::V1_1::implementation::UsbGadget; +using android::hardware::usb::gadget::V1_2::IUsbGadget; +using android::hardware::usb::gadget::V1_2::implementation::UsbGadget; using android::hardware::usb::V1_2::IUsb; using android::hardware::usb::V1_2::implementation::Usb; |
