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 "libusbconfigfs"
18 
19 #include "include/UsbGadgetCommon.h"
20 
21 namespace android {
22 namespace hardware {
23 namespace usb {
24 namespace gadget {
25 
unlinkFunctions(const char * path)26 int unlinkFunctions(const char* path) {
27     DIR* config = opendir(path);
28     struct dirent* function;
29     char filepath[kMaxFilePathLength];
30     int ret = 0;
31 
32     if (config == NULL) return -1;
33 
34     // d_type does not seems to be supported in /config
35     // so filtering by name.
36     while (((function = readdir(config)) != NULL)) {
37         if ((strstr(function->d_name, FUNCTION_NAME) == NULL)) continue;
38         // build the path for each file in the folder.
39         sprintf(filepath, "%s/%s", path, function->d_name);
40         ret = remove(filepath);
41         if (ret) {
42             ALOGE("Unable  remove file %s errno:%d", filepath, errno);
43             break;
44         }
45     }
46 
47     closedir(config);
48     return ret;
49 }
50 
addEpollFd(const unique_fd & epfd,const unique_fd & fd)51 int addEpollFd(const unique_fd& epfd, const unique_fd& fd) {
52     struct epoll_event event;
53     int ret;
54 
55     event.data.fd = fd;
56     event.events = EPOLLIN;
57 
58     ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
59     if (ret) ALOGE("epoll_ctl error %d", errno);
60 
61     return ret;
62 }
63 
linkFunction(const char * function,int index)64 int linkFunction(const char* function, int index) {
65     char functionPath[kMaxFilePathLength];
66     char link[kMaxFilePathLength];
67 
68     sprintf(functionPath, "%s%s", FUNCTIONS_PATH, function);
69     sprintf(link, "%s%d", FUNCTION_PATH, index);
70     if (symlink(functionPath, link)) {
71         ALOGE("Cannot create symlink %s -> %s errno:%d", link, functionPath, errno);
72         return -1;
73     }
74     return 0;
75 }
76 
setVidPid(const char * vid,const char * pid)77 Status setVidPid(const char* vid, const char* pid) {
78     if (!WriteStringToFile(vid, VENDOR_ID_PATH)) return Status::ERROR;
79 
80     if (!WriteStringToFile(pid, PRODUCT_ID_PATH)) return Status::ERROR;
81 
82     return Status::SUCCESS;
83 }
84 
getVendorFunctions()85 std::string getVendorFunctions() {
86     if (GetProperty(kBuildType, "") == "user") return "user";
87 
88     std::string bootMode = GetProperty(PERSISTENT_BOOT_MODE, "");
89     std::string persistVendorFunctions = GetProperty(kPersistentVendorConfig, "");
90     std::string vendorFunctions = GetProperty(kVendorConfig, "");
91     std::string ret = "";
92 
93     if (vendorFunctions != "") {
94         ret = vendorFunctions;
95     } else if (bootMode == "usbradio" || bootMode == "factory" || bootMode == "ffbm-00" ||
96                bootMode == "ffbm-01") {
97         if (persistVendorFunctions != "")
98             ret = persistVendorFunctions;
99         else
100             ret = "diag";
101         // vendor.usb.config will reflect the current configured functions
102         SetProperty(kVendorConfig, ret);
103     }
104 
105     return ret;
106 }
107 
resetGadget()108 Status resetGadget() {
109     ALOGI("setCurrentUsbFunctions None");
110 
111     if (!WriteStringToFile("none", PULLUP_PATH)) ALOGI("Gadget cannot be pulled down");
112 
113     if (!WriteStringToFile("0", DEVICE_CLASS_PATH)) return Status::ERROR;
114 
115     if (!WriteStringToFile("0", DEVICE_SUB_CLASS_PATH)) return Status::ERROR;
116 
117     if (!WriteStringToFile("0", DEVICE_PROTOCOL_PATH)) return Status::ERROR;
118 
119     if (!WriteStringToFile("0", DESC_USE_PATH)) return Status::ERROR;
120 
121     if (unlinkFunctions(CONFIG_PATH)) return Status::ERROR;
122 
123     return Status::SUCCESS;
124 }
125 
addGenericAndroidFunctions(MonitorFfs * monitorFfs,uint64_t functions,bool * ffsEnabled,int * functionCount)126 Status addGenericAndroidFunctions(MonitorFfs* monitorFfs, uint64_t functions, bool* ffsEnabled,
127                                   int* functionCount) {
128     if (((functions & GadgetFunction::MTP) != 0)) {
129         *ffsEnabled = true;
130         ALOGI("setCurrentUsbFunctions mtp");
131         if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR;
132 
133         if (!monitorFfs->addInotifyFd("/dev/usb-ffs/mtp/")) return Status::ERROR;
134 
135         if (linkFunction("ffs.mtp", (*functionCount)++)) return Status::ERROR;
136 
137         // Add endpoints to be monitored.
138         monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep1");
139         monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep2");
140         monitorFfs->addEndPoint("/dev/usb-ffs/mtp/ep3");
141     } else if (((functions & GadgetFunction::PTP) != 0)) {
142         *ffsEnabled = true;
143         ALOGI("setCurrentUsbFunctions ptp");
144         if (!WriteStringToFile("1", DESC_USE_PATH)) return Status::ERROR;
145 
146         if (!monitorFfs->addInotifyFd("/dev/usb-ffs/ptp/")) return Status::ERROR;
147 
148         if (linkFunction("ffs.ptp", (*functionCount)++)) return Status::ERROR;
149 
150         // Add endpoints to be monitored.
151         monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep1");
152         monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep2");
153         monitorFfs->addEndPoint("/dev/usb-ffs/ptp/ep3");
154     }
155 
156     if ((functions & GadgetFunction::MIDI) != 0) {
157         ALOGI("setCurrentUsbFunctions MIDI");
158         if (linkFunction("midi.gs5", (*functionCount)++)) return Status::ERROR;
159     }
160 
161     if ((functions & GadgetFunction::ACCESSORY) != 0) {
162         ALOGI("setCurrentUsbFunctions Accessory");
163         if (linkFunction("accessory.gs2", (*functionCount)++)) return Status::ERROR;
164     }
165 
166     if ((functions & GadgetFunction::AUDIO_SOURCE) != 0) {
167         ALOGI("setCurrentUsbFunctions Audio Source");
168         if (linkFunction("audio_source.gs3", (*functionCount)++)) return Status::ERROR;
169     }
170 
171     if ((functions & GadgetFunction::RNDIS) != 0) {
172         ALOGI("setCurrentUsbFunctions rndis");
173         if (linkFunction("gsi.rndis", (*functionCount)++)) return Status::ERROR;
174     }
175 
176     return Status::SUCCESS;
177 }
178 
addAdb(MonitorFfs * monitorFfs,int * functionCount)179 Status addAdb(MonitorFfs* monitorFfs, int* functionCount) {
180     ALOGI("setCurrentUsbFunctions Adb");
181     if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR;
182 
183     if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR;
184     monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep1");
185     monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep2");
186     ALOGI("Service started");
187     return Status::SUCCESS;
188 }
189 
190 }  // namespace gadget
191 }  // namespace usb
192 }  // namespace hardware
193 }  // namespace android
194