1 /*
2 * Copyright (c) 2022 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 "ddk_pnp_listener_mgr.h"
17
18 #include <ctype.h>
19 #include <dirent.h>
20
21 #include "ddk_device_manager.h"
22 #include "hdf_base.h"
23 #include "hdf_dlist.h"
24 #include "hdf_log.h"
25 #include "hdf_usb_pnp_manage.h"
26 #include "osal_mem.h"
27 #include "osal_mutex.h"
28 #include "securec.h"
29 #include "usbd_wrapper.h"
30
31 #define HDF_LOG_TAG usb_ddk_listener_mgr
32
33 struct UsbDdkListenerList {
34 bool isInit;
35 struct OsalMutex listMutex;
36 struct DListHead listenerList;
37 };
38
39 struct UsbDdkDeviceHanldePriv {
40 struct HdfDevEventlistener *listener;
41 enum UsbPnpNotifyServiceCmd cmd;
42 };
43
44 static struct UsbDdkListenerList g_ddkListenerList = {.isInit = false};
45
DdkListenerMgrIsExists(const struct HdfDevEventlistener * listener)46 static bool DdkListenerMgrIsExists(const struct HdfDevEventlistener *listener)
47 {
48 OsalMutexLock(&g_ddkListenerList.listMutex);
49 if (DListIsEmpty(&g_ddkListenerList.listenerList)) {
50 HDF_LOGI("%{public}s: the listenerList is empty.", __func__);
51 OsalMutexUnlock(&g_ddkListenerList.listMutex);
52 return false;
53 }
54
55 struct HdfDevEventlistener *pos = NULL;
56 struct HdfDevEventlistener *tmp = NULL;
57 bool findFlag = false;
58 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &g_ddkListenerList.listenerList, struct HdfDevEventlistener, listNode) {
59 if (pos == listener) {
60 findFlag = true;
61 break;
62 }
63 }
64
65 OsalMutexUnlock(&g_ddkListenerList.listMutex);
66 return findFlag;
67 }
68
DdkListenerMgrNotifyOne(const struct UsbPnpNotifyMatchInfoTable * device,void * priv)69 static int32_t DdkListenerMgrNotifyOne(const struct UsbPnpNotifyMatchInfoTable *device, void *priv)
70 {
71 struct UsbDdkDeviceHanldePriv *handlePriv = priv;
72 const struct HdfDevEventlistener *listener = handlePriv->listener;
73 // pack device
74 struct HdfSBuf *data = HdfSbufTypedObtain(SBUF_IPC);
75 if (data == NULL) {
76 HDF_LOGE("%{public}s: get buf failed", __func__);
77 return HDF_DEV_ERR_NO_MEMORY;
78 }
79
80 int32_t ret = HDF_SUCCESS;
81 do {
82 struct HdfSBuf *dataTmp = NULL;
83 if (device != NULL) {
84 if (!HdfSbufWriteBuffer(data, device, sizeof(struct UsbPnpNotifyMatchInfoTable))) {
85 HDF_LOGE("%{public}s: write buf failed", __func__);
86 ret = HDF_FAILURE;
87 break;
88 }
89 dataTmp = data;
90 }
91
92 if (listener->callBack(listener->priv, handlePriv->cmd, dataTmp) != HDF_SUCCESS) {
93 HDF_LOGE("%{public}s:callback failed", __func__);
94 ret = HDF_FAILURE;
95 }
96 } while (0);
97
98 HdfSbufRecycle(data);
99 return ret;
100 }
101
DdkListenerMgrNotifyGadgetOne(void * priv)102 static int32_t DdkListenerMgrNotifyGadgetOne(void *priv)
103 {
104 struct UsbDdkDeviceHanldePriv *handlePriv = (struct UsbDdkDeviceHanldePriv *)priv;
105 const struct HdfDevEventlistener *listener = handlePriv->listener;
106 if (listener->callBack(listener->priv, handlePriv->cmd, NULL) != HDF_SUCCESS) {
107 HDF_LOGE("%{public}s:callback failed", __func__);
108 return HDF_FAILURE;
109 }
110 return HDF_SUCCESS;
111 }
112
DdkListenerMgrNotifyAll(const struct UsbPnpNotifyMatchInfoTable * device,enum UsbPnpNotifyServiceCmd cmd)113 void DdkListenerMgrNotifyAll(const struct UsbPnpNotifyMatchInfoTable *device, enum UsbPnpNotifyServiceCmd cmd)
114 {
115 HDF_LOGI("%{public}s: notify cmd:%{public}d, start.", __func__, cmd);
116 OsalMutexLock(&g_ddkListenerList.listMutex);
117 if (DListIsEmpty(&g_ddkListenerList.listenerList)) {
118 HDF_LOGI("%{public}s: the listenerList is empty.", __func__);
119 OsalMutexUnlock(&g_ddkListenerList.listMutex);
120 return;
121 }
122
123 struct HdfDevEventlistener *pos = NULL;
124 struct HdfDevEventlistener *tmp = NULL;
125 struct UsbDdkDeviceHanldePriv handlePriv = {.cmd = cmd};
126 DLIST_FOR_EACH_ENTRY_SAFE(pos, tmp, &g_ddkListenerList.listenerList, struct HdfDevEventlistener, listNode) {
127 handlePriv.listener = pos;
128 if (DdkListenerMgrNotifyOne(device, &handlePriv) != HDF_SUCCESS) {
129 HDF_LOGW("%{public}s: notify failed cmd:%{public}d", __func__, cmd);
130 }
131 }
132
133 OsalMutexUnlock(&g_ddkListenerList.listMutex);
134 HDF_LOGI("%{public}s: notify cmd:%{public}d, end.", __func__, cmd);
135 }
136
DdkListenerMgrAdd(struct HdfDevEventlistener * listener)137 int32_t DdkListenerMgrAdd(struct HdfDevEventlistener *listener)
138 {
139 if (listener == NULL) {
140 HDF_LOGE("%{public}s: invalid param", __func__);
141 return HDF_ERR_INVALID_PARAM;
142 }
143
144 // notify all device to listener
145 struct UsbDdkDeviceHanldePriv handlePriv = {.listener = listener, .cmd = USB_PNP_NOTIFY_ADD_DEVICE};
146 struct UsbDdkDeviceHanldePriv handlePriv1 = {.listener = listener, .cmd = USB_PNP_DRIVER_GADGET_ADD};
147 if (DdkListenerMgrIsExists(listener)) {
148 HDF_LOGW("%{public}s: add listener repeatedly", __func__);
149 } else {
150 OsalMutexLock(&g_ddkListenerList.listMutex);
151 DListInsertTail(&listener->listNode, &g_ddkListenerList.listenerList);
152 OsalMutexUnlock(&g_ddkListenerList.listMutex);
153 }
154 int32_t ret = DdkDevMgrForEachDeviceSafe(DdkListenerMgrNotifyOne, (void *)&handlePriv);
155 if (ret != HDF_SUCCESS) {
156 HDF_LOGE("%{public}s:DdkDevMgrForEachDeviceSafe failed", __func__);
157 return ret;
158 }
159 ret = DdkDevMgrGetGadgetLinkStatusSafe(DdkListenerMgrNotifyGadgetOne, (void *)&handlePriv1);
160 if (ret != HDF_SUCCESS) {
161 HDF_LOGE("%{public}s:DdkDevMgrGetGadgetLinkStatusSafe failed", __func__);
162 return ret;
163 }
164 return ret;
165 }
166
DdkListenerMgrRemove(struct HdfDevEventlistener * listener)167 int32_t DdkListenerMgrRemove(struct HdfDevEventlistener *listener)
168 {
169 if (!DdkListenerMgrIsExists(listener)) {
170 HDF_LOGE("%{public}s: no listener", __func__);
171 return HDF_DEV_ERR_NO_DEVICE;
172 }
173
174 OsalMutexLock(&g_ddkListenerList.listMutex);
175 DListRemove(&listener->listNode);
176 OsalMutexUnlock(&g_ddkListenerList.listMutex);
177 return HDF_SUCCESS;
178 }
179
DdkListenerMgrInit(void)180 int32_t DdkListenerMgrInit(void)
181 {
182 if (g_ddkListenerList.isInit) {
183 return HDF_SUCCESS;
184 }
185
186 int32_t ret = OsalMutexInit(&g_ddkListenerList.listMutex);
187 if (ret != HDF_SUCCESS) {
188 HDF_LOGE("%{public}s: init mutex failed", __func__);
189 return HDF_FAILURE;
190 }
191
192 DListHeadInit(&g_ddkListenerList.listenerList);
193 g_ddkListenerList.isInit = true;
194 return HDF_SUCCESS;
195 }
196