• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include "can/can_manager.h"
10 #include "osal_time.h"
11 #include "securec.h"
12 #include "can/can_core.h"
13 
14 #define HDF_LOG_TAG can_manager
15 
16 #define CAN_NUMBER_MAX 32
17 #define CAN_MSG_POOL_SIZE_DFT 8
18 #define CAN_IRQ_STACK_SIZE (1024 * 8)
19 
20 static struct PlatformManager *g_manager;
21 
CanManagerGet(void)22 static struct PlatformManager *CanManagerGet(void)
23 {
24     int32_t ret;
25 
26     if (g_manager == NULL) {
27         ret = PlatformManagerCreate("CAN_BUS_MANAGER", &g_manager);
28         if (ret != HDF_SUCCESS) {
29             HDF_LOGE("CanManagerGet: create can manager fail, ret: %d!", ret);
30         }
31     }
32     return g_manager;
33 }
34 
CanManagerDestroyIfNeed(void)35 static void CanManagerDestroyIfNeed(void)
36 {
37     if (g_manager != NULL && DListIsEmpty(&g_manager->devices)) {
38         PlatformManagerDestroy(g_manager);
39         g_manager = NULL;
40     }
41 }
42 
CanIrqThreadWorker(void * data)43 static int32_t CanIrqThreadWorker(void *data)
44 {
45     int32_t ret;
46     struct CanCntlr *cntlr = (struct CanCntlr *)data;
47 
48     if (cntlr == NULL) {
49         HDF_LOGE("CanIrqThreadWorker: cntlr is null!");
50         return HDF_ERR_INVALID_OBJECT;
51     }
52 
53     cntlr->threadStatus |= CAN_THREAD_RUNNING;
54     while ((cntlr->threadStatus & CAN_THREAD_RUNNING) != 0) {
55         /* wait event */
56         ret = OsalSemWait(&cntlr->sem, HDF_WAIT_FOREVER);
57         if (ret != HDF_SUCCESS) {
58             continue;
59         }
60         if ((cntlr->threadStatus & CAN_THREAD_RUNNING) == 0) {
61             break;  // exit thread
62         }
63         ret = CanCntlrOnNewMsg(cntlr, cntlr->irqMsg);
64         if (ret != HDF_SUCCESS) {
65             HDF_LOGE("CanIrqThreadWorker: CanCntlrOnNewMsg fail!");
66         }
67         cntlr->irqMsg = NULL;
68         cntlr->threadStatus &= ~CAN_THREAD_PENDING;
69     }
70 
71     cntlr->threadStatus |= CAN_THREAD_STOPPED;
72     return HDF_SUCCESS;
73 }
74 
CanCntlrCreateThread(struct CanCntlr * cntlr)75 static int32_t CanCntlrCreateThread(struct CanCntlr *cntlr)
76 {
77     int32_t ret;
78     struct OsalThreadParam config;
79 
80     if (memset_s(&config, sizeof(config), 0, sizeof(config)) != EOK) {
81         HDF_LOGE("CanCntlrCreateThread: memset_s fail!");
82         return HDF_ERR_IO;
83     }
84     ret = OsalSemInit(&cntlr->sem, 0);
85     if (ret != HDF_SUCCESS) {
86         HDF_LOGE("CanCntlrCreateThread: sem init fail!");
87         return ret;
88     }
89 
90     ret = OsalThreadCreate(&cntlr->thread, (OsalThreadEntry)CanIrqThreadWorker, cntlr);
91     if (ret != HDF_SUCCESS) {
92         HDF_LOGE("CanCntlrCreateThread: thread create fail!");
93         (void)OsalSemDestroy(&cntlr->sem);
94         return ret;
95     }
96 
97     config.name = "CanIrqThread";
98     config.priority = OSAL_THREAD_PRI_HIGH;
99     config.stackSize = CAN_IRQ_STACK_SIZE;
100     cntlr->threadStatus = 0;
101     ret = OsalThreadStart(&cntlr->thread, &config);
102     if (ret != HDF_SUCCESS) {
103         HDF_LOGE("CanCntlrCreateThread: thread start fail!");
104         OsalThreadDestroy(&cntlr->thread);
105         (void)OsalSemDestroy(&cntlr->sem);
106         return ret;
107     }
108 
109     return HDF_SUCCESS;
110 }
111 
CanCntlrCheckAndInit(struct CanCntlr * cntlr)112 static int32_t CanCntlrCheckAndInit(struct CanCntlr *cntlr)
113 {
114     if (cntlr == NULL || cntlr->ops == NULL) {
115         return HDF_ERR_INVALID_OBJECT;
116     }
117 
118     if (cntlr->number < 0 || cntlr->number >= CAN_NUMBER_MAX) {
119         HDF_LOGE("CanCntlrCheckAndInit: invlaid can num:%d!", cntlr->number);
120         return HDF_ERR_INVALID_OBJECT;
121     }
122 
123     DListHeadInit(&cntlr->rxBoxList);
124 
125     if (CanCntlrCreateThread(cntlr) != HDF_SUCCESS) {
126         HDF_LOGE("CanCntlrCheckAndInit: create thread fail!");
127         return HDF_FAILURE;
128     }
129     if (OsalMutexInit(&cntlr->lock) != HDF_SUCCESS) {
130         HDF_LOGE("CanCntlrCheckAndInit: init lock fail!");
131         return HDF_FAILURE;
132     }
133 
134     if (OsalMutexInit(&cntlr->rboxListLock) != HDF_SUCCESS) {
135         HDF_LOGE("CanCntlrCheckAndInit: init rx box list lock fail!");
136         (void)OsalMutexDestroy(&cntlr->lock);
137         return HDF_FAILURE;
138     }
139 
140     if (cntlr->msgPoolSize <= 0) {
141         cntlr->msgPoolSize = CAN_MSG_POOL_SIZE_DFT;
142     }
143 
144     cntlr->msgPool = CanMsgPoolCreate(cntlr->msgPoolSize);
145     if (cntlr->msgPool == NULL) {
146         HDF_LOGE("CanCntlrCheckAndInit: create can msg pool fail!");
147         (void)OsalMutexDestroy(&cntlr->rboxListLock);
148         (void)OsalMutexDestroy(&cntlr->lock);
149         return HDF_FAILURE;
150     }
151 
152     return HDF_SUCCESS;
153 }
154 
CanCntlrDestroyThread(struct CanCntlr * cntlr)155 static void CanCntlrDestroyThread(struct CanCntlr *cntlr)
156 {
157     int t = 0;
158 
159     cntlr->threadStatus &= ~CAN_THREAD_RUNNING;
160     cntlr->irqMsg = NULL;
161     (void)OsalSemPost(&cntlr->sem);
162     while ((cntlr->threadStatus & CAN_THREAD_STOPPED) == 0) {
163         OsalMSleep(1);
164         if (t++ > THREAD_EXIT_TIMEOUT) {
165             break;
166         }
167     }
168     (void)OsalThreadDestroy(&cntlr->thread);
169     (void)OsalSemDestroy(&cntlr->sem);
170 }
171 
CanCntlrDeInit(struct CanCntlr * cntlr)172 static void CanCntlrDeInit(struct CanCntlr *cntlr)
173 {
174     HDF_LOGD("CanCntlrDeInit: enter!");
175     CanCntlrDestroyThread(cntlr);
176     CanMsgPoolDestroy(cntlr->msgPool);
177     cntlr->msgPool = NULL;
178     (void)OsalMutexDestroy(&cntlr->rboxListLock);
179     (void)OsalMutexDestroy(&cntlr->lock);
180     HDF_LOGD("CanCntlrDeInit: exit!");
181 }
182 
CanCntlrAdd(struct CanCntlr * cntlr)183 int32_t CanCntlrAdd(struct CanCntlr *cntlr)
184 {
185     int32_t ret;
186 
187     ret = CanCntlrCheckAndInit(cntlr);
188     if (ret != HDF_SUCCESS) {
189         HDF_LOGE("CanCntlrAdd: can cntlr check and init fail!");
190         return ret;
191     }
192 
193     cntlr->device.number = cntlr->number;
194     ret = PlatformDeviceSetName(&cntlr->device, "CAN%d", cntlr->number);
195     if (ret != HDF_SUCCESS) {
196         CanCntlrDeInit(cntlr);
197         HDF_LOGE("CanCntlrAdd: set name for platform device fail!");
198         return ret;
199     }
200 
201     cntlr->device.manager = CanManagerGet();
202     if (cntlr->device.manager == NULL) {
203         PlatformDeviceClearName(&cntlr->device);
204         CanCntlrDeInit(cntlr);
205         HDF_LOGE("CanCntlrAdd: get can manager fail!");
206         return HDF_PLT_ERR_DEV_GET;
207     }
208 
209     if ((ret = PlatformDeviceAdd(&cntlr->device)) != HDF_SUCCESS) {
210         PlatformDeviceClearName(&cntlr->device);
211         CanCntlrDeInit(cntlr);
212         HDF_LOGE("CanCntlrAdd: add platform device fail!");
213         return ret;
214     }
215 
216     HDF_LOGI("CanCntlrAdd: add controller %d success!", cntlr->number);
217     return HDF_SUCCESS;
218 }
219 
CanCntlrDel(struct CanCntlr * cntlr)220 int32_t CanCntlrDel(struct CanCntlr *cntlr)
221 {
222     if (cntlr == NULL) {
223         HDF_LOGE("CanCntlrDel: cntlr is null!");
224         return HDF_ERR_INVALID_OBJECT;
225     }
226 
227     PlatformDeviceDel(&cntlr->device);
228     PlatformDeviceClearName(&cntlr->device);
229 
230     CanCntlrDeInit(cntlr);
231 
232     CanManagerDestroyIfNeed();
233     HDF_LOGI("CanCntlrDel: del controller %d success!", cntlr->number);
234     return HDF_SUCCESS;
235 }
236 
CanCntlrFromPlatformDevice(const struct PlatformDevice * pdevice)237 static struct CanCntlr *CanCntlrFromPlatformDevice(const struct PlatformDevice *pdevice)
238 {
239     return CONTAINER_OF(pdevice, struct CanCntlr, device);
240 }
241 
CanCntlrGetByName(const char * name)242 struct CanCntlr *CanCntlrGetByName(const char *name)
243 {
244     static struct PlatformManager *manager = NULL;
245     struct PlatformDevice *pdevice = NULL;
246 
247     manager = CanManagerGet();
248     if (manager == NULL) {
249         HDF_LOGE("CanCntlrGetByName: get can manager fail!");
250         return NULL;
251     }
252 
253     pdevice = PlatformManagerGetDeviceByName(manager, name);
254     if (pdevice == NULL) {
255         HDF_LOGE("CanCntlrGetByName: get platform device fail!");
256         return NULL;
257     }
258 
259     return CanCntlrFromPlatformDevice(pdevice);
260 }
261 
CanCntlrGetByNumber(int32_t number)262 struct CanCntlr *CanCntlrGetByNumber(int32_t number)
263 {
264     static struct PlatformManager *manager = NULL;
265     struct PlatformDevice *pdevice = NULL;
266 
267     manager = CanManagerGet();
268     if (manager == NULL) {
269         HDF_LOGE("CanCntlrGetByNumber: get can manager fail!");
270         return NULL;
271     }
272 
273     pdevice = PlatformManagerGetDeviceByNumber(manager, number);
274     if (pdevice == NULL) {
275         HDF_LOGE("CanCntlrGetByNumber: get platform device fail!");
276         return NULL;
277     }
278 
279     return CanCntlrFromPlatformDevice(pdevice);
280 }
281 
CanCntlrPut(struct CanCntlr * cntlr)282 void CanCntlrPut(struct CanCntlr *cntlr)
283 {
284     if (cntlr != NULL) {
285         PlatformDevicePut(&cntlr->device);
286     }
287 }
288