1 /*
2 * Copyright (c) 2022 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 "can/can_core.h"
11
12 #define HDF_LOG_TAG can_manager
13
14 #define CAN_NUMBER_MAX 32
15 #define CAN_MSG_POOL_SIZE_DFT 8
16
17 static struct PlatformManager *g_manager;
18
CanManagerGet(void)19 static struct PlatformManager *CanManagerGet(void)
20 {
21 int32_t ret;
22
23 if (g_manager == NULL) {
24 ret = PlatformManagerCreate("CAN_BUS_MANAGER", &g_manager);
25 if (ret != HDF_SUCCESS) {
26 HDF_LOGE("CanManagerGet: careate can manager failed:%d", ret);
27 }
28 }
29 return g_manager;
30 }
31
CanManagerDestroyIfNeed(void)32 static void CanManagerDestroyIfNeed(void)
33 {
34 if (g_manager != NULL && DListIsEmpty(&g_manager->devices)) {
35 PlatformManagerDestroy(g_manager);
36 g_manager = NULL;
37 }
38 }
39
CanCntlrCheckAndInit(struct CanCntlr * cntlr)40 static int32_t CanCntlrCheckAndInit(struct CanCntlr *cntlr)
41 {
42 if (cntlr == NULL || cntlr->ops == NULL) {
43 return HDF_ERR_INVALID_OBJECT;
44 }
45
46 if (cntlr->number < 0 || cntlr->number >= CAN_NUMBER_MAX) {
47 HDF_LOGE("CanCntlrCheckAndInit: invlaid can num:%d", cntlr->number);
48 return HDF_ERR_INVALID_OBJECT;
49 }
50
51 DListHeadInit(&cntlr->rxBoxList);
52
53 if (OsalMutexInit(&cntlr->lock) != HDF_SUCCESS) {
54 HDF_LOGE("CanCntlrCheckAndInit: init lock failed");
55 return HDF_FAILURE;
56 }
57
58 if (OsalMutexInit(&cntlr->rboxListLock) != HDF_SUCCESS) {
59 HDF_LOGE("CanCntlrCheckAndInit: init rx box list lock failed");
60 (void)OsalMutexDestroy(&cntlr->lock);
61 return HDF_FAILURE;
62 }
63
64 if (cntlr->msgPoolSize <= 0) {
65 cntlr->msgPoolSize = CAN_MSG_POOL_SIZE_DFT;
66 }
67
68 cntlr->msgPool = CanMsgPoolCreate(cntlr->msgPoolSize);
69 if (cntlr->msgPool == NULL) {
70 HDF_LOGE("CanCntlrCheckAndInit: create can msg pool failed");
71 (void)OsalMutexDestroy(&cntlr->rboxListLock);
72 (void)OsalMutexDestroy(&cntlr->lock);
73 return HDF_FAILURE;
74 }
75
76 return HDF_SUCCESS;
77 }
78
CanCntlrDeInit(struct CanCntlr * cntlr)79 static void CanCntlrDeInit(struct CanCntlr *cntlr)
80 {
81 HDF_LOGD("CanCntlrDeInit: enter");
82 CanMsgPoolDestroy(cntlr->msgPool);
83 cntlr->msgPool = NULL;
84 (void)OsalMutexDestroy(&cntlr->rboxListLock);
85 (void)OsalMutexDestroy(&cntlr->lock);
86 HDF_LOGD("CanCntlrDeInit: exit");
87 }
88
CanCntlrAdd(struct CanCntlr * cntlr)89 int32_t CanCntlrAdd(struct CanCntlr *cntlr)
90 {
91 int32_t ret;
92
93 ret = CanCntlrCheckAndInit(cntlr);
94 if (ret != HDF_SUCCESS) {
95 return ret;
96 }
97
98 cntlr->device.number = cntlr->number;
99 ret = PlatformDeviceSetName(&cntlr->device, "CAN%d", cntlr->number);
100 if (ret != HDF_SUCCESS) {
101 CanCntlrDeInit(cntlr);
102 return ret;
103 }
104
105 cntlr->device.manager = CanManagerGet();
106 if (cntlr->device.manager == NULL) {
107 PlatformDeviceClearName(&cntlr->device);
108 CanCntlrDeInit(cntlr);
109 return HDF_PLT_ERR_DEV_GET;
110 }
111
112 if ((ret = PlatformDeviceAdd(&cntlr->device)) != HDF_SUCCESS) {
113 PlatformDeviceClearName(&cntlr->device);
114 CanCntlrDeInit(cntlr);
115 return ret;
116 }
117
118 HDF_LOGI("CanCntlrAdd: add controller %d success", cntlr->number);
119 return HDF_SUCCESS;
120 }
121
CanCntlrDel(struct CanCntlr * cntlr)122 int32_t CanCntlrDel(struct CanCntlr *cntlr)
123 {
124 if (cntlr == NULL) {
125 return HDF_ERR_INVALID_OBJECT;
126 }
127
128 PlatformDeviceDel(&cntlr->device);
129 PlatformDeviceClearName(&cntlr->device);
130
131 CanCntlrDeInit(cntlr);
132
133 CanManagerDestroyIfNeed();
134 HDF_LOGI("CanCntlrDel: del controller %d success", cntlr->number);
135 return HDF_SUCCESS;
136 }
137
CanCntlrFromPlatformDevice(const struct PlatformDevice * pdevice)138 static struct CanCntlr *CanCntlrFromPlatformDevice(const struct PlatformDevice *pdevice)
139 {
140 return CONTAINER_OF(pdevice, struct CanCntlr, device);
141 }
142
CanCntlrGetByName(const char * name)143 struct CanCntlr *CanCntlrGetByName(const char *name)
144 {
145 static struct PlatformManager *manager = NULL;
146 struct PlatformDevice *pdevice = NULL;
147
148 manager = CanManagerGet();
149 if (manager == NULL) {
150 return NULL;
151 }
152
153 pdevice = PlatformManagerGetDeviceByName(manager, name);
154 if (pdevice == NULL) {
155 return NULL;
156 }
157
158 return CanCntlrFromPlatformDevice(pdevice);
159 }
160
CanCntlrGetByNumber(int32_t number)161 struct CanCntlr *CanCntlrGetByNumber(int32_t number)
162 {
163 static struct PlatformManager *manager = NULL;
164 struct PlatformDevice *pdevice = NULL;
165
166 manager = CanManagerGet();
167 if (manager == NULL) {
168 return NULL;
169 }
170
171 pdevice = PlatformManagerGetDeviceByNumber(manager, number);
172 if (pdevice == NULL) {
173 return NULL;
174 }
175
176 return CanCntlrFromPlatformDevice(pdevice);
177 }
178
CanCntlrPut(struct CanCntlr * cntlr)179 void CanCntlrPut(struct CanCntlr *cntlr)
180 {
181 if (cntlr != NULL) {
182 PlatformDevicePut(&cntlr->device);
183 }
184 }
185