Set VID/PID for diag functions

persist.vendor.usb.config stores the vendor specific functions that are
enabled in the target when ro.bootmode is set to usbradio through
the adb command. Since its a persistent property, the oem functions
are persisted once enabled. Alternatively, store the oem functions
in vendor.usb.config. vendor.usb.config is not persisted though.
vendor.usb.config will also reflect the enabled oem functions.

Configurations supported in this CL:
1. diag
2. diag,serial_cdev,rmnet_gsi

This would work irrespective of when ADB is not or not.

Bug: 74603740
Test: Made sure the QXDM recognized wahoo when adb is enabled/
disabled for diag and diag,serial_cdev,rmnet_gsi
Change-Id: Icbbe177e3f8958efc36f67692b9ec935b718fb03
diff --git a/init.hardware.diag.rc.userdebug b/init.hardware.diag.rc.userdebug
index 234ea23..070b2d7 100644
--- a/init.hardware.diag.rc.userdebug
+++ b/init.hardware.diag.rc.userdebug
@@ -92,3 +92,9 @@
 
 on property:persist.bluetooth.btsnoopenable=false
    setprop persist.service.bdroid.soclog false
+
+on property:vendor.usb.config=*
+   start usbd
+
+on property:persist.vendor.usb.usbradio.config=*
+   start usbd
diff --git a/usb/UsbGadget.cpp b/usb/UsbGadget.cpp
index 3394443..05608e2 100644
--- a/usb/UsbGadget.cpp
+++ b/usb/UsbGadget.cpp
@@ -32,6 +32,7 @@
 constexpr bool DEBUG = false;
 constexpr int DISCONNECT_WAIT_US = 10000;
 
+#define BUILD_TYPE "ro.build.type"
 #define GADGET_PATH "/config/usb_gadget/g1/"
 #define PULLUP_PATH GADGET_PATH "UDC"
 #define GADGET_NAME "a800000.dwc3"
@@ -49,6 +50,9 @@
 #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 {
@@ -165,10 +169,8 @@
 }
 
 UsbGadget::UsbGadget()
-    : mMonitorCreated(false),
-      mCurrentUsbFunctionsApplied(false) {
-  if (access(OS_DESC_PATH, R_OK) != 0)
-    ALOGE("configfs setup not done yet");
+    : mMonitorCreated(false), mCurrentUsbFunctionsApplied(false) {
+  if (access(OS_DESC_PATH, R_OK) != 0) ALOGE("configfs setup not done yet");
 }
 
 static int unlinkFunctions(const char *path) {
@@ -277,40 +279,115 @@
   return Status::SUCCESS;
 }
 
+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;
+}
+
 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):
-      ret = setVidPid("0x18d1", "0x4ee1");
+      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:
-      ret = setVidPid("0x18d1", "0x4ee2");
+      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):
-      ret = setVidPid("0x18d1", "0x4ee3");
+      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:
-      ret = setVidPid("0x18d1", "0x4ee4");
+      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):
-      ret = setVidPid("0x18d1", "0x4ee7");
+      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;
     default:
@@ -344,7 +421,6 @@
     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.
@@ -355,7 +431,7 @@
 
   if ((functions & GadgetFunction::MIDI) != 0) {
     ALOGI("setCurrentUsbFunctions MIDI");
-    if (linkFunction("midi.gs5", i++)) return Status::ERROR;;
+    if (linkFunction("midi.gs5", i++)) return Status::ERROR;
   }
 
   if ((functions & GadgetFunction::ACCESSORY) != 0) {
@@ -368,11 +444,19 @@
     if (linkFunction("gsi.rndis", i++)) return Status::ERROR;
   }
 
-  if (bootMode == "usbradio") {
+  std::string vendorFunctions = getVendorFunctions();
+  if (vendorFunctions != "") {
     ALOGI("enable usbradio debug functions");
-    if (linkFunction("diag.diag", i++)) return Status::ERROR;
-    if (linkFunction("cser.dun.0", i++)) return Status::ERROR;
-    if (linkFunction("gsi.rmnet", i++)) return Status::ERROR;
+    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 ((functions & GadgetFunction::ADB) != 0) {
diff --git a/usb/UsbGadget.h b/usb/UsbGadget.h
index ef2ea4d..9a2c4dd 100644
--- a/usb/UsbGadget.h
+++ b/usb/UsbGadget.h
@@ -23,6 +23,7 @@
 #include <android/hardware/usb/gadget/1.0/IUsbGadget.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
+#include <string>
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
 #include <thread>
@@ -40,6 +41,7 @@
 
 using ::android::sp;
 using ::android::base::GetProperty;
+using ::android::base::SetProperty;
 using ::android::base::unique_fd;
 using ::android::base::WriteStringToFile;
 using ::android::hardware::hidl_array;