1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "usb_pnp_manager.h"
17 #include <pthread.h>
18 #include <unistd.h>
19
20 #include "ddk_device_manager.h"
21 #include "ddk_pnp_listener_mgr.h"
22 #include "ddk_uevent_handle.h"
23 #include "device_resource_if.h"
24 #include "hdf_base.h"
25 #include "hdf_device_desc.h"
26 #include "hdf_device_object.h"
27 #include "hdf_io_service_if.h"
28 #include "hdf_log.h"
29 #include "osal_mem.h"
30 #include "securec.h"
31 #include "usb_ddk_pnp_loader.h"
32 #include "usbd_wrapper.h"
33 #include "usb_accessory_uevent_handle.h"
34
35 #define HDF_LOG_TAG usb_pnp_manager
36 #define MODULENAMESIZE 128
37 const char USB_ACCESSORY_UEVENT_PATH[] = "usb_accessory_uevent_path";
38 const char USB_ACCESSORY_DEFAULT_PATH[] = "/devices/virtual/misc/usb_accessory";
39 #define USB_GADGET_UEVENT_PATH "gadget_uevent_path"
40 #define USB_GADGET_STATE_PATH "gadget_state_path"
41
42 #ifdef USB_EMULATOR_MODE
43 const char USB_EMULATOR_DEFAULT_STATE_PATH[] = "/sys/class/gadget_usb/gadget0/state";
44 const char USB_EMULATOR_DEFAULT_UEVENT_PATH[] = "/devices/virtual/gadget_usb/gadget0";
45 #endif
46
UsbPnpManagerWriteModuleName(struct HdfSBuf * sbuf,const char * moduleName)47 bool UsbPnpManagerWriteModuleName(struct HdfSBuf *sbuf, const char *moduleName)
48 {
49 char modName[MODULENAMESIZE] = {0};
50 if (sprintf_s(modName, MODULENAMESIZE, "lib%s.z.so", moduleName) < 0) {
51 HDF_LOGE("%{public}s: sprintf_s modName failed", __func__);
52 return false;
53 }
54
55 return HdfSbufWriteString(sbuf, modName);
56 }
57
UsbPnpManagerDispatch(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)58 static int32_t UsbPnpManagerDispatch(
59 struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
60 {
61 (void)client;
62 (void)cmd;
63 (void)data;
64 (void)reply;
65
66 HDF_LOGI("received cmd = %{public}d", cmd);
67 return HDF_SUCCESS;
68 }
69
UsbPnpManagerBind(struct HdfDeviceObject * device)70 static int32_t UsbPnpManagerBind(struct HdfDeviceObject *device)
71 {
72 static struct IDeviceIoService pnpLoaderService = {
73 .Dispatch = UsbPnpManagerDispatch,
74 };
75
76 if (device == NULL) {
77 return HDF_ERR_INVALID_OBJECT;
78 }
79
80 device->service = &pnpLoaderService;
81 HDF_LOGI("usb pnp manager bind success");
82
83 return HDF_SUCCESS;
84 }
85
86 #ifdef USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
UsbPnpManagerStartUeventThread(void)87 int32_t UsbPnpManagerStartUeventThread(void)
88 {
89 pthread_t tid;
90 int32_t ret = pthread_create(&tid, NULL, DdkUeventMain, NULL);
91 if (ret != 0) {
92 HDF_LOGE("%{public}s: create thread failed:%{public}d", __func__, ret);
93 return ret;
94 }
95
96 ret = pthread_setname_np(tid, "usbpnpUeventThd");
97 if (ret != 0) {
98 HDF_LOGE("%{public}s: set thread name failed:%{public}d", __func__, ret);
99 }
100 return ret;
101 }
102 #endif
103
UsbPnpMgrGetGadgetPath(struct HdfDeviceObject * device,const char * attrName)104 static const char *UsbPnpMgrGetGadgetPath(struct HdfDeviceObject *device, const char *attrName)
105 {
106 struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
107 if (iface == NULL) {
108 HDF_LOGE("%{public}s: DeviceResourceGetIfaceInstance failed", __func__);
109 return NULL;
110 }
111
112 const char *path = NULL;
113 const char *pathDef = NULL;
114 if (device == NULL) {
115 HDF_LOGE("%{public}s: device is empty", __func__);
116 return NULL;
117 }
118 #ifdef USB_EMULATOR_MODE
119 if (iface->GetString(device->property, attrName, &path, pathDef) != HDF_SUCCESS) {
120 HDF_LOGW("%{public}s: emulator read %{public}s failed", __func__, attrName);
121
122 if (strncmp(attrName, USB_GADGET_STATE_PATH, strlen(USB_GADGET_STATE_PATH)) == 0) {
123 path = USB_EMULATOR_DEFAULT_STATE_PATH;
124 } else if (strncmp(attrName, USB_ACCESSORY_UEVENT_PATH, strlen(USB_ACCESSORY_UEVENT_PATH)) == 0) {
125 path = USB_ACCESSORY_DEFAULT_PATH;
126 } else {
127 path = USB_EMULATOR_DEFAULT_UEVENT_PATH;
128 }
129 }
130 #else
131 if (iface->GetString(device->property, attrName, &path, pathDef) != HDF_SUCCESS) {
132 HDF_LOGW("%{public}s: emulator read %{public}s failed", __func__, attrName);
133 if (strncmp(attrName, USB_ACCESSORY_UEVENT_PATH, strlen(USB_ACCESSORY_UEVENT_PATH)) == 0) {
134 path = USB_ACCESSORY_DEFAULT_PATH;
135 }
136 }
137 #endif
138 return path;
139 }
140
DdkUeventAndAccessoryInit(struct HdfDeviceObject * device)141 static int32_t DdkUeventAndAccessoryInit(struct HdfDeviceObject *device)
142 {
143 if (device == NULL) {
144 HDF_LOGE("%{public}s: device is NULL", __func__);
145 return HDF_FAILURE;
146 }
147 int32_t ret = DdkUeventInit(UsbPnpMgrGetGadgetPath(device, USB_GADGET_UEVENT_PATH));
148 if (ret != HDF_SUCCESS) {
149 HDF_LOGE("%{public}s: DdkUeventInit error", __func__);
150 return ret;
151 }
152
153 ret = UsbAccessoryUeventInit(UsbPnpMgrGetGadgetPath(device, USB_ACCESSORY_UEVENT_PATH));
154 if (ret != HDF_SUCCESS) {
155 HDF_LOGD("%{public}s: UsbAccessoryUeventInit error, ret=%{public}d", __func__, ret);
156 return ret;
157 }
158
159 return HDF_SUCCESS;
160 }
161
UsbPnpManagerInit(struct HdfDeviceObject * device)162 static int32_t UsbPnpManagerInit(struct HdfDeviceObject *device)
163 {
164 HDF_LOGD("%{public}s: enter", __func__);
165 static struct HdfDevEventlistener usbPnpListener = {
166 .callBack = UsbDdkPnpLoaderEventReceived,
167 };
168 usbPnpListener.priv = (void *)(device);
169
170 int32_t ret = DdkDevMgrInit(UsbPnpMgrGetGadgetPath(device, "gadget_state_path"));
171 if (ret != HDF_SUCCESS) {
172 HDF_LOGE("%{public}s: DdkDevMgrInit error", __func__);
173 return HDF_FAILURE;
174 }
175
176 ret = DdkListenerMgrInit();
177 if (ret != HDF_SUCCESS) {
178 HDF_LOGE("%{public}s: DdkListenerMgrInit error", __func__);
179 return HDF_FAILURE;
180 }
181
182 ret = DdkUeventAndAccessoryInit(device);
183 if (ret != HDF_SUCCESS) {
184 HDF_LOGE("%{public}s: DdkUeventAndAccessoryInit error, ret=%{public}d", __func__, ret);
185 return ret;
186 }
187
188 #ifdef USB_EVENT_NOTIFY_LINUX_NATIVE_MODE
189 if (UsbPnpManagerStartUeventThread() != HDF_SUCCESS) {
190 HDF_LOGE("%{public}s: start uevent thread failed", __func__);
191 return HDF_FAILURE;
192 }
193 #endif
194
195 #ifdef USB_EMULATOR_MODE
196 ret = UsbDdkPnpLoaderEventHandle();
197 if (ret != HDF_SUCCESS) {
198 HDF_LOGW("%{public}s: emulator, UsbDdkPnpLoaderEventHandle failed", __func__);
199 }
200 if (DdkListenerMgrAdd(&usbPnpListener) != HDF_SUCCESS) {
201 HDF_LOGW("%{public}s: emulator, add listener failed", __func__);
202 }
203 #else
204 ret = UsbDdkPnpLoaderEventHandle();
205 if (ret != HDF_SUCCESS) {
206 HDF_LOGE("%{public}s: UsbDdkPnpLoaderEventHandle failed", __func__);
207 return ret;
208 }
209 if (DdkListenerMgrAdd(&usbPnpListener) != HDF_SUCCESS) {
210 HDF_LOGE("%{public}s: add listener failed", __func__);
211 return HDF_FAILURE;
212 }
213 #endif
214 HDF_LOGI("UsbPnpManagerInit done");
215 return HDF_SUCCESS;
216 }
217
UsbPnpManagerRelease(struct HdfDeviceObject * device)218 static void UsbPnpManagerRelease(struct HdfDeviceObject *device)
219 {
220 (void)device;
221 return;
222 }
223
224 struct HdfDriverEntry g_usbPnpManagerEntry = {
225 .moduleVersion = 1,
226 .Bind = UsbPnpManagerBind,
227 .Init = UsbPnpManagerInit,
228 .Release = UsbPnpManagerRelease,
229 .moduleName = "HDF_USB_PNP_MANAGER",
230 };
231
232 HDF_INIT(g_usbPnpManagerEntry);
233