• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "android.hardware.usb.gadget@1.2-service.gs101"
18 
19 #include "UsbGadget.h"
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <sys/inotify.h>
24 #include <sys/mount.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 
29 namespace android {
30 namespace hardware {
31 namespace usb {
32 namespace gadget {
33 namespace V1_2 {
34 namespace implementation {
35 
36 string enabledPath;
37 constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c";
38 constexpr char kI2CPath[] = "/sys/devices/platform/10d50000.hsi2c/i2c-";
39 constexpr char kAccessoryLimitCurrent[] = "i2c-max77759tcpc/usb_limit_accessory_current";
40 constexpr char kAccessoryLimitCurrentEnable[] = "i2c-max77759tcpc/usb_limit_accessory_enable";
41 
UsbGadget()42 UsbGadget::UsbGadget() : mGadgetIrqPath("") {
43     if (access(OS_DESC_PATH, R_OK) != 0) {
44         ALOGE("configfs setup not done yet");
45         abort();
46     }
47 }
48 
getUsbGadgetIrqPath()49 V1_0::Status UsbGadget::getUsbGadgetIrqPath() {
50     std::string irqs;
51     size_t read_pos = 0;
52     size_t found_pos = 0;
53 
54     if (!ReadFileToString(kProcInterruptsPath, &irqs)) {
55         ALOGE("cannot read all interrupts");
56         return Status::ERROR;
57     }
58 
59     while (true) {
60         found_pos = irqs.find_first_of("\n", read_pos);
61         if (found_pos == std::string::npos) {
62             ALOGI("the string of all interrupts is unexpected");
63             return Status::ERROR;
64         }
65 
66         std::string single_irq = irqs.substr(read_pos, found_pos - read_pos);
67 
68         if (single_irq.find("dwc3", 0) != std::string::npos) {
69             unsigned int dwc3_irq_number;
70             size_t dwc3_pos = single_irq.find_first_of(":");
71             if (!ParseUint(single_irq.substr(0, dwc3_pos), &dwc3_irq_number)) {
72                 ALOGI("unknown IRQ strings");
73                 return Status::ERROR;
74             }
75 
76             mGadgetIrqPath = kProcIrqPath + single_irq.substr(0, dwc3_pos) + kSmpAffinityList;
77             break;
78         }
79 
80         if (found_pos == irqs.npos) {
81             ALOGI("USB gadget doesn't start");
82             return Status::ERROR;
83         }
84 
85         read_pos = found_pos + 1;
86     }
87 
88     return Status::SUCCESS;
89 }
90 
currentFunctionsAppliedCallback(bool functionsApplied,void * payload)91 void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) {
92     UsbGadget *gadget = (UsbGadget *)payload;
93     gadget->mCurrentUsbFunctionsApplied = functionsApplied;
94 }
95 
getCurrentUsbFunctions(const sp<V1_0::IUsbGadgetCallback> & callback)96 Return<void> UsbGadget::getCurrentUsbFunctions(const sp<V1_0::IUsbGadgetCallback> &callback) {
97     Return<void> ret = callback->getCurrentUsbFunctionsCb(
98         mCurrentUsbFunctions,
99         mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED);
100     if (!ret.isOk())
101         ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.description().c_str());
102 
103     return Void();
104 }
105 
getUsbSpeed(const sp<V1_2::IUsbGadgetCallback> & callback)106 Return<void> UsbGadget::getUsbSpeed(const sp<V1_2::IUsbGadgetCallback> &callback) {
107     std::string current_speed;
108     if (ReadFileToString(SPEED_PATH, &current_speed)) {
109         current_speed = Trim(current_speed);
110         ALOGI("current USB speed is %s", current_speed.c_str());
111         if (current_speed == "low-speed")
112             mUsbSpeed = UsbSpeed::LOWSPEED;
113         else if (current_speed == "full-speed")
114             mUsbSpeed = UsbSpeed::FULLSPEED;
115         else if (current_speed == "high-speed")
116             mUsbSpeed = UsbSpeed::HIGHSPEED;
117         else if (current_speed == "super-speed")
118             mUsbSpeed = UsbSpeed::SUPERSPEED;
119         else if (current_speed == "super-speed-plus")
120             mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb;
121         else if (current_speed == "UNKNOWN")
122             mUsbSpeed = UsbSpeed::UNKNOWN;
123         else
124             mUsbSpeed = UsbSpeed::RESERVED_SPEED;
125     } else {
126         ALOGE("Fail to read current speed");
127         mUsbSpeed = UsbSpeed::UNKNOWN;
128     }
129 
130     if (callback) {
131         Return<void> ret = callback->getUsbSpeedCb(mUsbSpeed);
132 
133         if (!ret.isOk())
134             ALOGE("Call to getUsbSpeedCb failed %s", ret.description().c_str());
135     }
136 
137     return Void();
138 }
139 
tearDownGadget()140 V1_0::Status UsbGadget::tearDownGadget() {
141     if (resetGadget() != Status::SUCCESS)
142         return Status::ERROR;
143 
144     if (monitorFfs.isMonitorRunning()) {
145         monitorFfs.reset();
146     } else {
147         ALOGI("mMonitor not running");
148     }
149     return Status::SUCCESS;
150 }
151 
validateAndSetVidPid(uint64_t functions)152 static V1_0::Status validateAndSetVidPid(uint64_t functions) {
153     V1_0::Status ret = Status::SUCCESS;
154     std::string vendorFunctions = getVendorFunctions();
155 
156     switch (functions) {
157         case static_cast<uint64_t>(GadgetFunction::MTP):
158             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
159                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
160                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
161             } else {
162                 ret = setVidPid("0x18d1", "0x4ee1");
163             }
164             break;
165         case GadgetFunction::ADB | GadgetFunction::MTP:
166             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
167                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
168                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
169             } else {
170                 ret = setVidPid("0x18d1", "0x4ee2");
171             }
172             break;
173         case static_cast<uint64_t>(GadgetFunction::RNDIS):
174         case GadgetFunction::RNDIS | GadgetFunction::NCM:
175             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
176                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
177                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
178             } else {
179                 ret = setVidPid("0x18d1", "0x4ee3");
180             }
181             break;
182         case GadgetFunction::ADB | GadgetFunction::RNDIS:
183         case GadgetFunction::ADB | GadgetFunction::RNDIS | GadgetFunction::NCM:
184             if (vendorFunctions == "dm") {
185                 ret = setVidPid("0x04e8", "0x6862");
186             } else {
187                 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
188                     ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
189                     ret = Status::CONFIGURATION_NOT_SUPPORTED;
190                 } else {
191                     ret = setVidPid("0x18d1", "0x4ee4");
192                 }
193             }
194             break;
195         case static_cast<uint64_t>(GadgetFunction::PTP):
196             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
197                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
198                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
199             } else {
200                 ret = setVidPid("0x18d1", "0x4ee5");
201             }
202             break;
203         case GadgetFunction::ADB | GadgetFunction::PTP:
204             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
205                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
206                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
207             } else {
208                 ret = setVidPid("0x18d1", "0x4ee6");
209             }
210             break;
211         case static_cast<uint64_t>(GadgetFunction::ADB):
212             if (vendorFunctions == "dm") {
213                 ret = setVidPid("0x04e8", "0x6862");
214             } else if (vendorFunctions == "etr_miu") {
215                 ret = setVidPid("0x18d1", "0x4ee2");
216             } else if (vendorFunctions == "uwb_acm"){
217                 ret = setVidPid("0x18d1", "0x4ee2");
218             } else {
219                 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
220                     ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
221                     ret = Status::CONFIGURATION_NOT_SUPPORTED;
222                 } else {
223                     ret = setVidPid("0x18d1", "0x4ee7");
224                 }
225             }
226             break;
227         case static_cast<uint64_t>(GadgetFunction::MIDI):
228             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
229                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
230                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
231             } else {
232                 ret = setVidPid("0x18d1", "0x4ee8");
233             }
234             break;
235         case GadgetFunction::ADB | GadgetFunction::MIDI:
236             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
237                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
238                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
239             } else {
240                 ret = setVidPid("0x18d1", "0x4ee9");
241             }
242             break;
243         case static_cast<uint64_t>(GadgetFunction::ACCESSORY):
244             if (!(vendorFunctions == "user" || vendorFunctions == ""))
245                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
246             ret = setVidPid("0x18d1", "0x2d00");
247             break;
248         case GadgetFunction::ADB | GadgetFunction::ACCESSORY:
249             if (!(vendorFunctions == "user" || vendorFunctions == ""))
250                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
251             ret = setVidPid("0x18d1", "0x2d01");
252             break;
253         case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE):
254             if (!(vendorFunctions == "user" || vendorFunctions == ""))
255                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
256             ret = setVidPid("0x18d1", "0x2d02");
257             break;
258         case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE:
259             if (!(vendorFunctions == "user" || vendorFunctions == ""))
260                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
261             ret = setVidPid("0x18d1", "0x2d03");
262             break;
263         case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
264             if (!(vendorFunctions == "user" || vendorFunctions == ""))
265                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
266             ret = setVidPid("0x18d1", "0x2d04");
267             break;
268         case GadgetFunction::ADB | GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
269             if (!(vendorFunctions == "user" || vendorFunctions == ""))
270                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
271             ret = setVidPid("0x18d1", "0x2d05");
272             break;
273         case static_cast<uint64_t>(GadgetFunction::NCM):
274             if (!(vendorFunctions == "user" || vendorFunctions == ""))
275                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
276             ret = setVidPid("0x18d1", "0x4eeb");
277             break;
278         case GadgetFunction::ADB | GadgetFunction::NCM:
279             if (vendorFunctions == "dm") {
280                 ret = setVidPid("0x04e8", "0x6862");
281             } else {
282                 if (!(vendorFunctions == "user" || vendorFunctions == ""))
283                     ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
284                 ret = setVidPid("0x18d1", "0x4eec");
285             }
286             break;
287         default:
288             ALOGE("Combination not supported");
289             ret = Status::CONFIGURATION_NOT_SUPPORTED;
290     }
291     return ret;
292 }
293 
reset()294 Return<Status> UsbGadget::reset() {
295     ALOGI("USB Gadget reset");
296 
297     if (!WriteStringToFile("none", PULLUP_PATH)) {
298         ALOGI("Gadget cannot be pulled down");
299         return Status::ERROR;
300     }
301 
302     usleep(kDisconnectWaitUs);
303 
304     if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
305         ALOGI("Gadget cannot be pulled up");
306         return Status::ERROR;
307     }
308 
309     return Status::SUCCESS;
310 }
311 
setupFunctions(uint64_t functions,const sp<V1_0::IUsbGadgetCallback> & callback,uint64_t timeout)312 V1_0::Status UsbGadget::setupFunctions(uint64_t functions,
313                                        const sp<V1_0::IUsbGadgetCallback> &callback,
314                                        uint64_t timeout) {
315     bool ffsEnabled = false;
316     int i = 0;
317 
318     if (addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i) !=
319         Status::SUCCESS)
320         return Status::ERROR;
321 
322     std::string vendorFunctions = getVendorFunctions();
323 
324     if (vendorFunctions == "dm") {
325         ALOGI("enable usbradio debug functions");
326         if ((functions & GadgetFunction::RNDIS) != 0) {
327             if (linkFunction("acm.gs6", i++))
328 	        return Status::ERROR;
329             if (linkFunction("dm.gs7", i++))
330                 return Status::ERROR;
331         } else {
332             if (linkFunction("dm.gs7", i++))
333                 return Status::ERROR;
334             if (linkFunction("acm.gs6", i++))
335                 return Status::ERROR;
336 	}
337     } else if (vendorFunctions == "etr_miu") {
338         ALOGI("enable etr_miu functions");
339         if (linkFunction("etr_miu.gs11", i++))
340             return Status::ERROR;
341     } else if (vendorFunctions == "uwb_acm") {
342         ALOGI("enable uwb acm function");
343         if (linkFunction("acm.uwb0", i++))
344             return Status::ERROR;
345     }
346 
347     if ((functions & GadgetFunction::ADB) != 0) {
348         ffsEnabled = true;
349         if (addAdb(&monitorFfs, &i) != Status::SUCCESS)
350             return Status::ERROR;
351     }
352 
353     if ((functions & GadgetFunction::NCM) != 0) {
354         ALOGI("setCurrentUsbFunctions ncm");
355         if (linkFunction("ncm.gs9", i++))
356             return Status::ERROR;
357     }
358 
359     // Pull up the gadget right away when there are no ffs functions.
360     if (!ffsEnabled) {
361         if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
362             return Status::ERROR;
363         mCurrentUsbFunctionsApplied = true;
364         if (callback)
365             callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
366         return Status::SUCCESS;
367     }
368 
369     monitorFfs.registerFunctionsAppliedCallback(&currentFunctionsAppliedCallback, this);
370     // Monitors the ffs paths to pull up the gadget when descriptors are written.
371     // Also takes of the pulling up the gadget again if the userspace process
372     // dies and restarts.
373     monitorFfs.startMonitor();
374 
375     if (kDebug)
376         ALOGI("Mainthread in Cv");
377 
378     if (callback) {
379         bool pullup = monitorFfs.waitForPullUp(timeout);
380         Return<void> ret = callback->setCurrentUsbFunctionsCb(
381             functions, pullup ? Status::SUCCESS : Status::ERROR);
382         if (!ret.isOk())
383             ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str());
384     }
385 
386     return Status::SUCCESS;
387 }
388 
getI2cBusHelper(string * name)389 Status getI2cBusHelper(string *name) {
390     DIR *dp;
391 
392     dp = opendir(kHsi2cPath);
393     if (dp != NULL) {
394         struct dirent *ep;
395 
396         while ((ep = readdir(dp))) {
397             if (ep->d_type == DT_DIR) {
398                 if (string::npos != string(ep->d_name).find("i2c-")) {
399                     std::strtok(ep->d_name, "-");
400                     *name = std::strtok(NULL, "-");
401                 }
402             }
403         }
404         closedir(dp);
405         return Status::SUCCESS;
406     }
407 
408     ALOGE("Failed to open %s", kHsi2cPath);
409     return Status::ERROR;
410 }
411 
setCurrentUsbFunctions(uint64_t functions,const sp<V1_0::IUsbGadgetCallback> & callback,uint64_t timeout)412 Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions,
413                                                const sp<V1_0::IUsbGadgetCallback> &callback,
414                                                uint64_t timeout) {
415     std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
416     std::string current_usb_power_operation_mode, current_usb_type;
417     std::string usb_limit_sink_enable;
418 
419     string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath, path;
420 
421     mCurrentUsbFunctions = functions;
422     mCurrentUsbFunctionsApplied = false;
423 
424     getI2cBusHelper(&path);
425     accessoryCurrentLimitPath = kI2CPath + path + "/" + kAccessoryLimitCurrent;
426     accessoryCurrentLimitEnablePath = kI2CPath + path + "/" + kAccessoryLimitCurrentEnable;
427 
428     // Get the gadget IRQ number before tearDownGadget()
429     if (mGadgetIrqPath.empty())
430         getUsbGadgetIrqPath();
431 
432     // Unlink the gadget and stop the monitor if running.
433     V1_0::Status status = tearDownGadget();
434     if (status != Status::SUCCESS) {
435         goto error;
436     }
437 
438     ALOGI("Returned from tearDown gadget");
439 
440     // Leave the gadget pulled down to give time for the host to sense disconnect.
441     usleep(kDisconnectWaitUs);
442 
443     if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) {
444         if (callback == NULL)
445             return Void();
446         Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
447         if (!ret.isOk())
448             ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
449         return Void();
450     }
451 
452     status = validateAndSetVidPid(functions);
453 
454     if (status != Status::SUCCESS) {
455         goto error;
456     }
457 
458     status = setupFunctions(functions, callback, timeout);
459     if (status != Status::SUCCESS) {
460         goto error;
461     }
462 
463     if (functions & GadgetFunction::NCM) {
464         if (!mGadgetIrqPath.empty()) {
465             if (!WriteStringToFile(BIG_CORE, mGadgetIrqPath))
466                 ALOGI("Cannot move gadget IRQ to big core, path:%s", mGadgetIrqPath.c_str());
467         }
468     } else {
469         if (!mGadgetIrqPath.empty()) {
470             if (!WriteStringToFile(MEDIUM_CORE, mGadgetIrqPath))
471                 ALOGI("Cannot move gadget IRQ to medium core, path:%s", mGadgetIrqPath.c_str());
472         }
473     }
474 
475     if (ReadFileToString(CURRENT_USB_TYPE_PATH, &current_usb_type))
476         current_usb_type = Trim(current_usb_type);
477 
478     if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, &current_usb_power_operation_mode))
479         current_usb_power_operation_mode = Trim(current_usb_power_operation_mode);
480 
481     if (functions & GadgetFunction::ACCESSORY &&
482         current_usb_type == "Unknown SDP [CDP] DCP" &&
483         (current_usb_power_operation_mode == "default" ||
484         current_usb_power_operation_mode == "1.5A")) {
485         if (!WriteStringToFile("1300000", accessoryCurrentLimitPath)) {
486             ALOGI("Write 1.3A to limit current fail");
487         } else {
488             if (!WriteStringToFile("1", accessoryCurrentLimitEnablePath)) {
489                 ALOGI("Enable limit current fail");
490             }
491         }
492     } else {
493         if (!WriteStringToFile("0", accessoryCurrentLimitEnablePath))
494             ALOGI("unvote accessory limit current failed");
495     }
496 
497     ALOGI("Usb Gadget setcurrent functions called successfully");
498     return Void();
499 
500 error:
501     ALOGI("Usb Gadget setcurrent functions failed");
502     if (callback == NULL)
503         return Void();
504     Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status);
505     if (!ret.isOk())
506         ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
507     return Void();
508 }
509 }  // namespace implementation
510 }  // namespace V1_2
511 }  // namespace gadget
512 }  // namespace usb
513 }  // namespace hardware
514 }  // namespace android
515