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 std::string rndisFunction = GetProperty(kVendorRndisConfig, "");
175 if (rndisFunction != "") {
176 if (linkFunction(rndisFunction.c_str(), (*functionCount)++)) return Status::ERROR;
177 } else {
178 // link gsi.rndis for older pixel projects
179 if (linkFunction("gsi.rndis", (*functionCount)++)) return Status::ERROR;
180 }
181 }
182
183 if ((functions & GadgetFunction::NCM) != 0) {
184 ALOGI("setCurrentUsbFunctions ncm");
185 if (linkFunction("ncm.gs6", (*functionCount)++)) return Status::ERROR;
186 }
187
188 return Status::SUCCESS;
189 }
190
addAdb(MonitorFfs * monitorFfs,int * functionCount)191 Status addAdb(MonitorFfs* monitorFfs, int* functionCount) {
192 ALOGI("setCurrentUsbFunctions Adb");
193 if (!monitorFfs->addInotifyFd("/dev/usb-ffs/adb/")) return Status::ERROR;
194
195 if (linkFunction("ffs.adb", (*functionCount)++)) return Status::ERROR;
196 monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep1");
197 monitorFfs->addEndPoint("/dev/usb-ffs/adb/ep2");
198 ALOGI("Service started");
199 return Status::SUCCESS;
200 }
201
202 } // namespace gadget
203 } // namespace usb
204 } // namespace hardware
205 } // namespace android
206