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 #include "allocator.h"
16 #include "cmd/hci_cmd.h"
17 #include "log.h"
18 #include "platform/include/list.h"
19 #include "platform/include/mutex.h"
20 #include "hci_vendor_if.h"
21
22 typedef struct {
23 const HCIVendorEventCallback *callback;
24 void *context;
25 } HCIVendorEventCallbackBlock;
26
27 static List *g_hciVendorCallbackList = NULL;
28 static Mutex *g_hciVendorCallbackListLock = NULL;
29
HCIVendorAllocCallbackBlock(const HCIVendorEventCallback * callback,void * context)30 static HCIVendorEventCallbackBlock *HCIVendorAllocCallbackBlock(const HCIVendorEventCallback *callback, void *context)
31 {
32 HCIVendorEventCallbackBlock *block = MEM_MALLOC.alloc(sizeof(HCIVendorEventCallbackBlock));
33 if (block != NULL) {
34 block->callback = (HCIVendorEventCallback *)callback;
35 block->context = context;
36 }
37 return block;
38 }
39
HCIVendorFreeCallbacksBlock(void * block)40 static void HCIVendorFreeCallbacksBlock(void *block)
41 {
42 MEM_MALLOC.free(block);
43 }
44
HciVendorClosed(void)45 NO_SANITIZE("cfi") void HciVendorClosed(void)
46 {
47 if (g_hciVendorCallbackListLock == NULL) {
48 LOG_ERROR("g_hciVendorCallbackListLock is null");
49 return;
50 }
51 HCIVendorEventCallbackBlock *block = NULL;
52 MutexLock(g_hciVendorCallbackListLock);
53 ListNode *node = ListGetFirstNode(g_hciVendorCallbackList);
54 while (node != NULL) {
55 block = ListGetNodeData(node);
56 if (block->callback != NULL && block->callback->hciVendorClosed != NULL) {
57 block->callback->hciVendorClosed(block->context);
58 }
59 node = ListGetNextNode(node);
60 }
61 MutexUnlock(g_hciVendorCallbackListLock);
62 }
63
HciVendorInit(void)64 void HciVendorInit(void)
65 {
66 g_hciVendorCallbackList = ListCreate(HCIVendorFreeCallbacksBlock);
67 if (g_hciVendorCallbackList == NULL) {
68 LOG_ERROR("%{public}s:malloc error.", __FUNCTION__);
69 }
70
71 g_hciVendorCallbackListLock = MutexCreate();
72 if (g_hciVendorCallbackListLock == NULL) {
73 LOG_ERROR("%{public}s:create mutex error.", __FUNCTION__);
74 }
75 }
76
HciVendorClose(void)77 void HciVendorClose(void)
78 {
79 HciVendorClosed();
80 if (g_hciVendorCallbackListLock != NULL) {
81 MutexDelete(g_hciVendorCallbackListLock);
82 g_hciVendorCallbackListLock = NULL;
83 }
84
85 if (g_hciVendorCallbackList != NULL) {
86 ListDelete(g_hciVendorCallbackList);
87 g_hciVendorCallbackList = NULL;
88 }
89 }
90
HCIVIF_RegisterVendorEventCallback(const HCIVendorEventCallback * callback,void * context)91 int HCIVIF_RegisterVendorEventCallback(
92 const HCIVendorEventCallback *callback, void *context)
93 {
94 if (callback == NULL) {
95 LOG_ERROR("%{public}s: callback is null", __FUNCTION__);
96 return BT_BAD_PARAM;
97 }
98
99 if ((g_hciVendorCallbackList == NULL) || ((g_hciVendorCallbackListLock == NULL))) {
100 LOG_ERROR("%{public}s: hci vendor not ready", __FUNCTION__);
101 return BT_BAD_STATUS;
102 }
103
104 HCIVendorEventCallbackBlock *block = HCIVendorAllocCallbackBlock(callback, context);
105 if (block == NULL) {
106 return BT_NO_MEMORY;
107 }
108
109 MutexLock(g_hciVendorCallbackListLock);
110 ListAddLast(g_hciVendorCallbackList, block);
111 MutexUnlock(g_hciVendorCallbackListLock);
112
113 return BT_SUCCESS;
114 }
115
HCIVIF_DeregisterVendorEventCallback(const HCIVendorEventCallback * callback)116 int HCIVIF_DeregisterVendorEventCallback(const HCIVendorEventCallback *callback)
117 {
118 if (callback == NULL) {
119 return BT_BAD_PARAM;
120 }
121
122 if ((g_hciVendorCallbackList == NULL) || ((g_hciVendorCallbackListLock == NULL))) {
123 LOG_ERROR("%{public}s: hci vendor not ready", __FUNCTION__);
124 return BT_BAD_STATUS;
125 }
126
127 MutexLock(g_hciVendorCallbackListLock);
128
129 HCIVendorEventCallbackBlock *block = NULL;
130 ListNode *node = ListGetFirstNode(g_hciVendorCallbackList);
131 while (node != NULL) {
132 block = ListGetNodeData(node);
133 if (block != NULL) {
134 if (block->callback == callback) {
135 ListRemoveNode(g_hciVendorCallbackList, block);
136 break;
137 }
138 }
139 node = ListGetNextNode(node);
140 }
141
142 MutexUnlock(g_hciVendorCallbackListLock);
143
144 return BT_SUCCESS;
145 }
146
HCIVIF_SendCmd(uint16_t opCode,const void * param,size_t paramLength)147 int HCIVIF_SendCmd(uint16_t opCode, const void *param, size_t paramLength)
148 {
149 HciCmd *cmd = HciAllocCmd(opCode, param, paramLength);
150 return HciSendCmd(cmd);
151 }
152
HciEventOnVendorCommandComplete(uint16_t opCode,const void * param,uint8_t paramLength)153 NO_SANITIZE("cfi") void HciEventOnVendorCommandComplete(uint16_t opCode, const void *param, uint8_t paramLength)
154 {
155 if (g_hciVendorCallbackListLock == NULL) {
156 LOG_ERROR("g_hciVendorCallbackListLock is null");
157 return;
158 }
159 HCIVendorEventCallbackBlock *block = NULL;
160 MutexLock(g_hciVendorCallbackListLock);
161 ListNode *node = ListGetFirstNode(g_hciVendorCallbackList);
162 while (node != NULL) {
163 block = ListGetNodeData(node);
164 if (block->callback != NULL && block->callback->hciCommandCompleteEvent != NULL) {
165 block->callback->hciCommandCompleteEvent(opCode, param, paramLength, block->context);
166 }
167 node = ListGetNextNode(node);
168 }
169 MutexUnlock(g_hciVendorCallbackListLock);
170 }
171