• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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