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