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 "hdf_io_service_if.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "securec.h"
13 #include "spi_if.h"
14
15 #define HDF_LOG_TAG spi_if_u
16 #define HOST_NAME_LEN 32
17
18 struct SpiObject {
19 struct SpiCntlr *cntlr;
20 uint32_t csNum;
21 };
22
SpiGetCntlrByBusNum(uint32_t num)23 static struct HdfIoService *SpiGetCntlrByBusNum(uint32_t num)
24 {
25 int ret;
26 char *name = NULL;
27 struct HdfIoService *service = NULL;
28
29 name = (char *)OsalMemCalloc(HOST_NAME_LEN + 1);
30 if (name == NULL) {
31 return NULL;
32 }
33 ret = snprintf_s(name, HOST_NAME_LEN + 1, HOST_NAME_LEN, "HDF_PLATFORM_SPI_%u", num);
34 if (ret < 0) {
35 HDF_LOGE("%s: snprintf_s failed", __func__);
36 OsalMemFree(name);
37 return NULL;
38 }
39 service = HdfIoServiceBind(name);
40 OsalMemFree(name);
41
42 return service;
43 }
44
SpiMsgWriteArray(struct SpiObject * object,struct HdfSBuf * data,struct SpiMsg * msgs,uint32_t count)45 static int32_t SpiMsgWriteArray(struct SpiObject *object, struct HdfSBuf *data, struct SpiMsg *msgs, uint32_t count)
46 {
47 uint32_t i;
48
49 if (!HdfSbufWriteUint32(data, object->csNum)) {
50 HDF_LOGE("%s: write csNum failed!", __func__);
51 return HDF_ERR_IO;
52 }
53
54 if (!HdfSbufWriteBuffer(data, (uint8_t *)msgs, sizeof(*msgs) * count)) {
55 HDF_LOGE("%s: write msgs array failed!", __func__);
56 return HDF_ERR_IO;
57 }
58
59 for (i = 0; i < count; i++) {
60 if (msgs[i].wbuf == NULL) {
61 continue;
62 }
63
64 if (!HdfSbufWriteBuffer(data, (uint8_t *)msgs[i].wbuf, msgs[i].len)) {
65 HDF_LOGE("%s: write msg[%d] buf failed!", __func__, i);
66 return HDF_ERR_IO;
67 }
68 }
69
70 return HDF_SUCCESS;
71 }
72
SpiMsgReadBack(struct HdfSBuf * data,struct SpiMsg * msg)73 static int32_t SpiMsgReadBack(struct HdfSBuf *data, struct SpiMsg *msg)
74 {
75 uint32_t rLen;
76 const void *rBuf = NULL;
77
78 if (!HdfSbufReadBuffer(data, &rBuf, &rLen)) {
79 HDF_LOGE("%s: read rBuf failed!", __func__);
80 return HDF_ERR_IO;
81 }
82 if (msg->len != rLen) {
83 HDF_LOGE("%s: err len:%u, rLen:%u", __func__, msg->len, rLen);
84 if (rLen > msg->len) {
85 rLen = msg->len;
86 }
87 }
88 if (memcpy_s(msg->rbuf, msg->len, rBuf, rLen) != EOK) {
89 HDF_LOGE("%s: memcpy rBuf failed!", __func__);
90 return HDF_ERR_IO;
91 }
92
93 return HDF_SUCCESS;
94 }
95
SpiMsgReadArray(struct HdfSBuf * reply,struct SpiMsg * msgs,uint32_t count)96 static int32_t SpiMsgReadArray(struct HdfSBuf *reply, struct SpiMsg *msgs, uint32_t count)
97 {
98 uint32_t i;
99 int32_t ret;
100
101 for (i = 0; i < count; i++) {
102 if (msgs[i].rbuf == NULL) {
103 continue;
104 }
105 ret = SpiMsgReadBack(reply, &msgs[i]);
106 if (ret != HDF_SUCCESS) {
107 return ret;
108 }
109 }
110 return HDF_SUCCESS;
111 }
112
SpiTransfer(DevHandle handle,struct SpiMsg * msgs,uint32_t count)113 int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count)
114 {
115 int32_t ret;
116 uint32_t i;
117 uint32_t len = 0;
118 struct HdfSBuf *data = NULL;
119 struct HdfSBuf *reply = NULL;
120 struct HdfIoService *service = NULL;
121 struct SpiObject *object = NULL;
122
123 if (handle == NULL || msgs == NULL) {
124 HDF_LOGE("%s: invalid handle or msgs", __func__);
125 return HDF_ERR_INVALID_OBJECT;
126 }
127 object = (struct SpiObject *)handle;
128
129 for (i = 0; i < count; i++) {
130 len += ((msgs[i].wbuf == NULL) ? 0 : msgs[i].len) + sizeof(uint64_t) + sizeof(*msgs) + sizeof(uint32_t);
131 }
132 data = HdfSbufObtain(len);
133 if (data == NULL) {
134 HDF_LOGE("%s: failed to obtain data!", __func__);
135 return HDF_ERR_MALLOC_FAIL;
136 }
137
138 for (i = 0; i < count; i++) {
139 len += (msgs[i].rbuf == NULL) ? 0 : (msgs[i].len + sizeof(uint64_t));
140 }
141 reply = (len == 0) ? HdfSbufObtainDefaultSize() : HdfSbufObtain(len);
142 if (reply == NULL) {
143 HDF_LOGE("%s: failed to obtain reply!", __func__);
144 ret = HDF_ERR_MALLOC_FAIL;
145 goto EXIT;
146 }
147
148 ret = SpiMsgWriteArray(object, data, msgs, count);
149 if (ret != HDF_SUCCESS) {
150 HDF_LOGE("%s: failed to write msgs!", __func__);
151 goto EXIT;
152 }
153
154 service = (struct HdfIoService *)object->cntlr;
155 if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
156 HDF_LOGE("%s: service is invalid", __func__);
157 ret = HDF_FAILURE;
158 goto EXIT;
159 }
160 ret = service->dispatcher->Dispatch(&service->object, SPI_IO_TRANSFER, data, reply);
161 if (ret != HDF_SUCCESS) {
162 HDF_LOGE("%s: failed to send service call:%d", __func__, ret);
163 goto EXIT;
164 }
165
166 ret = SpiMsgReadArray(reply, msgs, count);
167 if (ret != HDF_SUCCESS) {
168 goto EXIT;
169 }
170
171 ret = HDF_SUCCESS;
172 EXIT:
173 HdfSbufRecycle(data);
174 HdfSbufRecycle(reply);
175 return ret;
176 }
177
SpiRead(DevHandle handle,uint8_t * buf,uint32_t len)178 int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len)
179 {
180 struct SpiMsg msg = {0};
181
182 msg.wbuf = NULL;
183 msg.rbuf = buf;
184 msg.len = len;
185 return SpiTransfer(handle, &msg, 1);
186 }
187
SpiWrite(DevHandle handle,uint8_t * buf,uint32_t len)188 int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len)
189 {
190 struct SpiMsg msg = {0};
191
192 msg.wbuf = buf;
193 msg.rbuf = NULL;
194 msg.len = len;
195 return SpiTransfer(handle, &msg, 1);
196 }
197
SpiSetCfg(DevHandle handle,struct SpiCfg * cfg)198 int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg)
199 {
200 int32_t ret;
201 struct SpiObject *object = NULL;
202 struct HdfSBuf *data = NULL;
203 struct HdfIoService *service = NULL;
204
205 if (handle == NULL || cfg == NULL) {
206 HDF_LOGE("%s: invalid handle", __func__);
207 return HDF_ERR_INVALID_OBJECT;
208 }
209 object = (struct SpiObject *)handle;
210 data = HdfSbufObtainDefaultSize();
211 if (data == NULL) {
212 HDF_LOGE("%s: failed to obtain data", __func__);
213 return HDF_ERR_MALLOC_FAIL;
214 }
215
216 if (!HdfSbufWriteUint32(data, object->csNum)) {
217 HDF_LOGE("%s: write csNum failed!", __func__);
218 HdfSbufRecycle(data);
219 return HDF_FAILURE;
220 }
221
222 if (!HdfSbufWriteBuffer(data, cfg, sizeof(*cfg))) {
223 HDF_LOGE("%s: write cfg failed!", __func__);
224 HdfSbufRecycle(data);
225 return HDF_FAILURE;
226 }
227
228 service = (struct HdfIoService *)object->cntlr;
229 if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
230 HDF_LOGE("%s: service is invalid", __func__);
231 HdfSbufRecycle(data);
232 return HDF_FAILURE;
233 }
234 ret = service->dispatcher->Dispatch(&service->object, SPI_IO_SET_CONFIG, data, NULL);
235 if (ret != HDF_SUCCESS) {
236 HDF_LOGE("%s: failed, ret is %d", __func__, ret);
237 HdfSbufRecycle(data);
238 return HDF_ERR_IO;
239 }
240 HdfSbufRecycle(data);
241
242 return HDF_SUCCESS;
243 }
244
SpiGetCfg(DevHandle handle,struct SpiCfg * cfg)245 int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg)
246 {
247 int32_t ret;
248 uint32_t len;
249 const void *rBuf = NULL;
250 struct HdfSBuf *data = NULL;
251 struct HdfSBuf *reply = NULL;
252 struct SpiObject *object = NULL;
253 struct HdfIoService *service = NULL;
254
255 if (handle == NULL || cfg == NULL) {
256 HDF_LOGE("%s: invalid handle", __func__);
257 return HDF_ERR_INVALID_OBJECT;
258 }
259 object = (struct SpiObject *)handle;
260
261 data = HdfSbufObtainDefaultSize();
262 if (data == NULL) {
263 HDF_LOGE("%s: failed to obtain data", __func__);
264 return HDF_ERR_MALLOC_FAIL;
265 }
266 reply = HdfSbufObtainDefaultSize();
267 if (reply == NULL) {
268 HDF_LOGE("%s: failed to obtain reply", __func__);
269 HdfSbufRecycle(data);
270 return HDF_ERR_MALLOC_FAIL;
271 }
272 if (!HdfSbufWriteUint32(data, object->csNum)) {
273 HDF_LOGE("%s: write csNum failed!", __func__);
274 ret = HDF_ERR_IO;
275 goto EXIT;
276 }
277 service = (struct HdfIoService *)object->cntlr;
278 if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
279 HDF_LOGE("%s: service is invalid", __func__);
280 ret = HDF_ERR_MALLOC_FAIL;
281 goto EXIT;
282 }
283 ret = service->dispatcher->Dispatch(&service->object, SPI_IO_GET_CONFIG, data, reply);
284 if (ret != HDF_SUCCESS) {
285 HDF_LOGE("%s: failed, ret is %d", __func__, ret);
286 goto EXIT;
287 }
288 if (!HdfSbufReadBuffer(reply, &rBuf, &len) || rBuf == NULL) {
289 HDF_LOGE("%s: read buffer failed", __func__);
290 goto EXIT;
291 }
292 if (memcpy_s(cfg, sizeof(struct SpiCfg), rBuf, len) != EOK) {
293 HDF_LOGE("%s: memcpy rBuf failed", __func__);
294 ret = HDF_ERR_IO;
295 goto EXIT;
296 }
297 EXIT:
298 HdfSbufRecycle(data);
299 HdfSbufRecycle(reply);
300 return ret;
301 }
302
SpiClose(DevHandle handle)303 void SpiClose(DevHandle handle)
304 {
305 int32_t ret;
306 struct SpiObject *object = NULL;
307 struct HdfSBuf *data = NULL;
308 struct HdfIoService *service = NULL;
309
310 if (handle == NULL) {
311 HDF_LOGE("%s: handle is invalid", __func__);
312 return;
313 }
314 object = (struct SpiObject *)handle;
315
316 data = HdfSbufObtainDefaultSize();
317 if (data == NULL) {
318 HDF_LOGE("%s: failed to obtain data", __func__);
319 goto EXIT;
320 }
321 if (!HdfSbufWriteUint32(data, object->csNum)) {
322 HDF_LOGE("%s: write csNum failed!", __func__);
323 goto EXIT;
324 }
325
326 service = (struct HdfIoService *)object->cntlr;
327 if (service == NULL || service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
328 HDF_LOGE("%s: service is invalid", __func__);
329 goto EXIT;
330 }
331 ret = service->dispatcher->Dispatch(&service->object, SPI_IO_CLOSE, data, NULL);
332 if (ret != HDF_SUCCESS) {
333 HDF_LOGE("%s: failed, ret is %d", __func__, ret);
334 }
335 EXIT:
336 HdfSbufRecycle(data);
337 HdfIoServiceRecycle(service);
338 OsalMemFree(object);
339 }
340
SpiOpen(const struct SpiDevInfo * info)341 DevHandle SpiOpen(const struct SpiDevInfo *info)
342 {
343 int32_t ret;
344 struct SpiObject *object = NULL;
345 struct HdfSBuf *data = NULL;
346 struct HdfIoService *service = NULL;
347
348 if (info == NULL) {
349 HDF_LOGE("%s: error, info is NULL", __func__);
350 return NULL;
351 }
352 service = SpiGetCntlrByBusNum(info->busNum);
353 if (service == NULL) {
354 HDF_LOGE("%s: service is null", __func__);
355 return NULL;
356 }
357 data = HdfSbufObtainDefaultSize();
358 if (data == NULL) {
359 HDF_LOGE("%s: failed to obtain data", __func__);
360 HdfIoServiceRecycle(service);
361 return NULL;
362 }
363 if (!HdfSbufWriteUint32(data, info->csNum)) {
364 HDF_LOGE("%s: write csNum failed!", __func__);
365 HdfSbufRecycle(data);
366 HdfIoServiceRecycle(service);
367 return NULL;
368 }
369
370 if (service == NULL ||service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
371 HDF_LOGE("%s: service is invalid", __func__);
372 HdfSbufRecycle(data);
373 HdfIoServiceRecycle(service);
374 return NULL;
375 }
376 ret = service->dispatcher->Dispatch(&service->object, SPI_IO_OPEN, data, NULL);
377 if (ret != HDF_SUCCESS) {
378 HDF_LOGE("%s: failed, ret is %d", __func__, ret);
379 HdfSbufRecycle(data);
380 HdfIoServiceRecycle(service);
381 return NULL;
382 }
383
384 object = (struct SpiObject *)OsalMemCalloc(sizeof(*object));
385 if (object == NULL) {
386 HDF_LOGE("%s: object malloc failed", __func__);
387 HdfSbufRecycle(data);
388 HdfIoServiceRecycle(service);
389 return NULL;
390 }
391 object->cntlr = (struct SpiCntlr *)service;
392 object->csNum = info->csNum;
393 HdfSbufRecycle(data);
394 return (DevHandle)object;
395 }
396