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_core.h"
10 #include "can/can_mail.h"
11 #include "can/can_msg.h"
12
CanCntlrLock(struct CanCntlr * cntlr)13 static int32_t CanCntlrLock(struct CanCntlr *cntlr)
14 {
15 if (cntlr->ops != NULL && cntlr->ops->lock != NULL) {
16 return cntlr->ops->lock(cntlr);
17 } else {
18 return OsalMutexLock(&cntlr->lock);
19 }
20 }
21
CanCntlrUnlock(struct CanCntlr * cntlr)22 static void CanCntlrUnlock(struct CanCntlr *cntlr)
23 {
24 if (cntlr->ops != NULL && cntlr->ops->unlock != NULL) {
25 cntlr->ops->unlock(cntlr);
26 } else {
27 (void)OsalMutexUnlock(&cntlr->lock);
28 }
29 }
30
CanCntlrWriteMsg(struct CanCntlr * cntlr,const struct CanMsg * msg)31 int32_t CanCntlrWriteMsg(struct CanCntlr *cntlr, const struct CanMsg *msg)
32 {
33 int32_t ret;
34
35 if (cntlr == NULL) {
36 HDF_LOGE("CanCntlrWriteMsg: cntlr is null!");
37 return HDF_ERR_INVALID_OBJECT;
38 }
39 if (cntlr->ops == NULL || cntlr->ops->sendMsg == NULL) {
40 HDF_LOGE("CanCntlrWriteMsg: ops or sendMsg is null!");
41 return HDF_ERR_NOT_SUPPORT;
42 }
43
44 if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
45 HDF_LOGE("CanCntlrWriteMsg: can cntlr lock fail!");
46 return ret;
47 }
48 ret = cntlr->ops->sendMsg(cntlr, msg);
49 CanCntlrUnlock(cntlr);
50 return ret;
51 }
52
CanCntlrSetCfg(struct CanCntlr * cntlr,const struct CanConfig * cfg)53 int32_t CanCntlrSetCfg(struct CanCntlr *cntlr, const struct CanConfig *cfg)
54 {
55 int32_t ret;
56
57 if (cntlr == NULL) {
58 HDF_LOGE("CanCntlrSetCfg: cntlr is null!");
59 return HDF_ERR_INVALID_OBJECT;
60 }
61 if (cntlr->ops == NULL || cntlr->ops->setCfg == NULL) {
62 HDF_LOGE("CanCntlrSetCfg: ops or setCfg is null!");
63 return HDF_ERR_NOT_SUPPORT;
64 }
65
66 if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
67 HDF_LOGE("CanCntlrSetCfg: can cntlr lock fail!");
68 return ret;
69 }
70 ret = cntlr->ops->setCfg(cntlr, cfg);
71 CanCntlrUnlock(cntlr);
72 return ret;
73 }
74
CanCntlrGetCfg(struct CanCntlr * cntlr,struct CanConfig * cfg)75 int32_t CanCntlrGetCfg(struct CanCntlr *cntlr, struct CanConfig *cfg)
76 {
77 int32_t ret;
78
79 if (cntlr == NULL) {
80 HDF_LOGE("CanCntlrGetCfg: cntlr is null!");
81 return HDF_ERR_INVALID_OBJECT;
82 }
83 if (cntlr->ops == NULL || cntlr->ops->getCfg == NULL) {
84 HDF_LOGE("CanCntlrGetCfg: ops or setCfg is null!");
85 return HDF_ERR_NOT_SUPPORT;
86 }
87
88 if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
89 HDF_LOGE("CanCntlrGetCfg: can cntlr lock fail!");
90 return ret;
91 }
92 ret = cntlr->ops->getCfg(cntlr, cfg);
93 CanCntlrUnlock(cntlr);
94 return ret;
95 }
96
CanCntlrGetState(struct CanCntlr * cntlr)97 int32_t CanCntlrGetState(struct CanCntlr *cntlr)
98 {
99 int32_t ret;
100
101 if (cntlr == NULL) {
102 HDF_LOGE("CanCntlrGetState: cntlr is null!");
103 return HDF_ERR_INVALID_OBJECT;
104 }
105 if (cntlr->ops == NULL || cntlr->ops->getState == NULL) {
106 HDF_LOGE("CanCntlrGetState: ops or setCfg is null!");
107 return HDF_ERR_NOT_SUPPORT;
108 }
109
110 if ((ret = CanCntlrLock(cntlr)) != HDF_SUCCESS) {
111 HDF_LOGE("CanCntlrGetState: can cntlr lock fail!");
112 return ret;
113 }
114 ret = cntlr->ops->getState(cntlr);
115 CanCntlrUnlock(cntlr);
116 return ret;
117 }
118
CanCntlrAddRxBox(struct CanCntlr * cntlr,struct CanRxBox * rxBox)119 int32_t CanCntlrAddRxBox(struct CanCntlr *cntlr, struct CanRxBox *rxBox)
120 {
121 if (cntlr == NULL) {
122 HDF_LOGE("CanCntlrAddRxBox: cntlr is null!");
123 return HDF_ERR_INVALID_OBJECT;
124 }
125 if (rxBox == NULL) {
126 HDF_LOGE("CanCntlrAddRxBox: rxBox is null!");
127 return HDF_ERR_INVALID_PARAM;
128 }
129 (void)OsalMutexLock(&cntlr->rboxListLock);
130 DListInsertTail(&rxBox->node, &cntlr->rxBoxList);
131 (void)OsalMutexUnlock(&cntlr->rboxListLock);
132 return HDF_SUCCESS;
133 }
134
CanCntlrDelRxBox(struct CanCntlr * cntlr,struct CanRxBox * rxBox)135 int32_t CanCntlrDelRxBox(struct CanCntlr *cntlr, struct CanRxBox *rxBox)
136 {
137 struct CanRxBox *tmp = NULL;
138 struct CanRxBox *toRmv = NULL;
139
140 if (cntlr == NULL) {
141 HDF_LOGE("CanCntlrDelRxBox: cntlr is null!");
142 return HDF_ERR_INVALID_OBJECT;
143 }
144 if (rxBox == NULL) {
145 HDF_LOGE("CanCntlrDelRxBox: rxBox is null!");
146 return HDF_ERR_INVALID_PARAM;
147 }
148 (void)OsalMutexLock(&cntlr->rboxListLock);
149 DLIST_FOR_EACH_ENTRY_SAFE(toRmv, tmp, &cntlr->rxBoxList, struct CanRxBox, node) {
150 if (toRmv == rxBox) {
151 DListRemove(&toRmv->node);
152 (void)OsalMutexUnlock(&cntlr->rboxListLock);
153 return HDF_SUCCESS;
154 }
155 }
156 (void)OsalMutexUnlock(&cntlr->rboxListLock);
157 HDF_LOGE("CanCntlrDelRxBox: del rxBox is not support!");
158 return HDF_ERR_NOT_SUPPORT;
159 }
160
CanCntlrMsgDispatch(struct CanCntlr * cntlr,struct CanMsg * msg)161 static int32_t CanCntlrMsgDispatch(struct CanCntlr *cntlr, struct CanMsg *msg)
162 {
163 struct CanRxBox *rxBox = NULL;
164
165 (void)OsalMutexLock(&cntlr->rboxListLock);
166 DLIST_FOR_EACH_ENTRY(rxBox, &cntlr->rxBoxList, struct CanRxBox, node) {
167 (void)CanRxBoxAddMsg(rxBox, msg);
168 }
169 (void)OsalMutexUnlock(&cntlr->rboxListLock);
170 CanMsgPut(msg);
171
172 return HDF_SUCCESS;
173 }
174
CanCntlrOnNewMsg(struct CanCntlr * cntlr,const struct CanMsg * msg)175 int32_t CanCntlrOnNewMsg(struct CanCntlr *cntlr, const struct CanMsg *msg)
176 {
177 struct CanMsg *copy = NULL;
178
179 if (cntlr == NULL) {
180 HDF_LOGE("CanCntlrOnNewMsg: cntlr is null!");
181 return HDF_ERR_INVALID_OBJECT;
182 }
183
184 if (msg == NULL) {
185 HDF_LOGE("CanCntlrOnNewMsg: msg is null!");
186 return HDF_ERR_INVALID_PARAM;
187 }
188
189 copy = CanMsgPoolObtainMsg(cntlr->msgPool);
190 if (copy == NULL) {
191 HDF_LOGE("CanCntlrOnNewMsg: can msg pool obtain msg fail!");
192 return HDF_FAILURE;
193 }
194 *copy = *msg;
195
196 return CanCntlrMsgDispatch(cntlr, copy); // gona call in thread context later ...
197 }
198
CanCntlrOnNewMsgIrqSafe(struct CanCntlr * cntlr,const struct CanMsg * msg)199 int32_t CanCntlrOnNewMsgIrqSafe(struct CanCntlr *cntlr, const struct CanMsg *msg)
200 {
201 if (cntlr == NULL) {
202 HDF_LOGE("CanCntlrOnNewMsgIrqSafe: cntlr is null!");
203 return HDF_ERR_INVALID_OBJECT;
204 }
205
206 if (msg == NULL) {
207 HDF_LOGE("CanCntlrOnNewMsgIrqSafe: msg is null!");
208 return HDF_ERR_INVALID_PARAM;
209 }
210
211 if ((cntlr->threadStatus & CAN_THREAD_RUNNING) == 0 || (cntlr->threadStatus & CAN_THREAD_PENDING) != 0) {
212 HDF_LOGE("CanCntlrOnNewMsgIrqSafe: device is busy!");
213 return HDF_ERR_DEVICE_BUSY;
214 }
215 cntlr->irqMsg = msg;
216 cntlr->threadStatus |= CAN_THREAD_PENDING;
217 (void)OsalSemPost(&cntlr->sem);
218 return HDF_SUCCESS;
219 }
220