• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-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 "spi_core.h"
10 #include "hdf_log.h"
11 #include "osal_mem.h"
12 #include "spi_if.h"
13 #include "spi_service.h"
14 
15 #define HDF_LOG_TAG spi_core
16 
SpiCntlrOpen(struct SpiCntlr * cntlr,uint32_t csNum)17 int32_t SpiCntlrOpen(struct SpiCntlr *cntlr, uint32_t csNum)
18 {
19     int32_t ret;
20 
21     if (cntlr == NULL) {
22         HDF_LOGE("%s: invalid parameter", __func__);
23         return HDF_ERR_INVALID_PARAM;
24     }
25     if (cntlr->method == NULL || cntlr->method->Open == NULL) {
26         HDF_LOGE("%s: Open not support", __func__);
27         return HDF_ERR_NOT_SUPPORT;
28     }
29     (void)OsalMutexLock(&(cntlr->lock));
30     cntlr->curCs = csNum;
31     ret = cntlr->method->Open(cntlr);
32     (void)OsalMutexUnlock(&(cntlr->lock));
33     return ret;
34 }
35 
SpiCntlrClose(struct SpiCntlr * cntlr,uint32_t csNum)36 int32_t SpiCntlrClose(struct SpiCntlr *cntlr, uint32_t csNum)
37 {
38     int32_t ret;
39 
40     if (cntlr == NULL) {
41         HDF_LOGE("%s: invalid parameter", __func__);
42         return HDF_ERR_INVALID_PARAM;
43     }
44     if (cntlr->method == NULL || cntlr->method->Close == NULL) {
45         HDF_LOGE("%s: Close not support", __func__);
46         return HDF_ERR_NOT_SUPPORT;
47     }
48     (void)OsalMutexLock(&(cntlr->lock));
49     cntlr->curCs = csNum;
50     ret = cntlr->method->Close(cntlr);
51     (void)OsalMutexUnlock(&(cntlr->lock));
52     return ret;
53 }
54 
SpiCntlrTransfer(struct SpiCntlr * cntlr,uint32_t csNum,struct SpiMsg * msg,uint32_t count)55 int32_t SpiCntlrTransfer(struct SpiCntlr *cntlr, uint32_t csNum, struct SpiMsg *msg, uint32_t count)
56 {
57     int32_t ret;
58 
59     if (cntlr == NULL) {
60         HDF_LOGE("%s: invalid parameter", __func__);
61         return HDF_ERR_INVALID_PARAM;
62     }
63     if (cntlr->method == NULL || cntlr->method->Transfer == NULL) {
64         HDF_LOGE("%s: transfer not support", __func__);
65         return HDF_ERR_NOT_SUPPORT;
66     }
67 
68     (void)OsalMutexLock(&(cntlr->lock));
69     cntlr->curCs = csNum;
70     ret = cntlr->method->Transfer(cntlr, msg, count);
71     (void)OsalMutexUnlock(&(cntlr->lock));
72     return ret;
73 }
74 
SpiCntlrSetCfg(struct SpiCntlr * cntlr,uint32_t csNum,struct SpiCfg * cfg)75 int32_t SpiCntlrSetCfg(struct SpiCntlr *cntlr, uint32_t csNum, struct SpiCfg *cfg)
76 {
77     int32_t ret;
78 
79     if (cntlr == NULL) {
80         HDF_LOGE("%s: invalid parameter", __func__);
81         return HDF_ERR_INVALID_PARAM;
82     }
83 
84     if (cntlr->method == NULL || cntlr->method->SetCfg == NULL) {
85         HDF_LOGE("%s: not support", __func__);
86         return HDF_ERR_NOT_SUPPORT;
87     }
88 
89     (void)OsalMutexLock(&(cntlr->lock));
90     cntlr->curCs = csNum;
91     ret = cntlr->method->SetCfg(cntlr, cfg);
92     (void)OsalMutexUnlock(&(cntlr->lock));
93     return ret;
94 }
95 
SpiCntlrGetCfg(struct SpiCntlr * cntlr,uint32_t csNum,struct SpiCfg * cfg)96 int32_t SpiCntlrGetCfg(struct SpiCntlr *cntlr, uint32_t csNum, struct SpiCfg *cfg)
97 {
98     int32_t ret;
99 
100     if (cntlr == NULL) {
101         HDF_LOGE("%s: invalid parameter", __func__);
102         return HDF_ERR_INVALID_PARAM;
103     }
104 
105     if (cntlr->method == NULL || cntlr->method->GetCfg == NULL) {
106         HDF_LOGE("%s: not support", __func__);
107         return HDF_ERR_NOT_SUPPORT;
108     }
109 
110     (void)OsalMutexLock(&(cntlr->lock));
111     cntlr->curCs = csNum;
112     ret = cntlr->method->GetCfg(cntlr, cfg);
113     (void)OsalMutexUnlock(&(cntlr->lock));
114     return ret;
115 }
116 
SpiMsgsRwProcess(struct HdfSBuf * data,uint32_t count,uint8_t * tmpFlag,struct SpiMsg * msgs,uint32_t * lenReply)117 static int32_t SpiMsgsRwProcess(
118     struct HdfSBuf *data, uint32_t count, uint8_t *tmpFlag, struct SpiMsg *msgs, uint32_t *lenReply)
119 {
120     int32_t i;
121     uint32_t len;
122     uint8_t *buf = NULL;
123     uint32_t rbufLen;
124     struct SpiUserMsg *userMsg = NULL;
125 
126     for (i = 0; i < count; i++) {
127         if ((!HdfSbufReadBuffer(data, (const void **)&userMsg, &len)) || (userMsg == NULL) ||
128             (len != sizeof(struct SpiUserMsg))) {
129             HDF_LOGE("%s: read msg[%d] userMsg fail!", __func__, i);
130             return HDF_ERR_IO;
131         }
132 
133         msgs[i].len = userMsg->len;
134         msgs[i].speed = userMsg->speed;
135         msgs[i].delayUs = userMsg->delayUs;
136         msgs[i].keepCs = userMsg->keepCs;
137         msgs[i].rbuf = NULL;
138         msgs[i].wbuf = NULL;
139         if ((userMsg->rwFlag & SPI_USER_MSG_READ) == SPI_USER_MSG_READ) {
140             (*lenReply) += msgs[i].len;
141             msgs[i].rbuf = tmpFlag; // tmpFlag is not mainpulated, only to mark rbuf not NULL
142         }
143         if ((userMsg->rwFlag & SPI_USER_MSG_WRITE) == SPI_USER_MSG_WRITE) {
144             if ((!HdfSbufReadBuffer(data, (const void **)&buf, &len)) || (buf == NULL) || (len != msgs[i].len)) {
145                 HDF_LOGE("%s: read msg[%d] wbuf fail, len[%u], msgs[i].len[%u]!", __func__, i, len, msgs[i].len);
146             } else {
147                 msgs[i].wbuf = buf;
148             }
149         }
150     }
151 
152     if ((!HdfSbufReadUint32(data, &rbufLen)) || (rbufLen != *lenReply)) {
153         HDF_LOGE("%s: read rbufLen failed %u != %u!", __func__, rbufLen, *lenReply);
154         return HDF_ERR_IO;
155     }
156 
157     return HDF_SUCCESS;
158 }
159 
160 // data format:csNum -- count -- count data records:SpiUserMsg( if write data has write buffer data) -- rbufLen
SpiTransferRebuildMsgs(struct HdfSBuf * data,struct SpiMsg ** ppmsgs,uint32_t * pcount,uint8_t ** ppbuf)161 static int32_t SpiTransferRebuildMsgs(struct HdfSBuf *data, struct SpiMsg **ppmsgs, uint32_t *pcount, uint8_t **ppbuf)
162 {
163     uint32_t count;
164     int32_t i;
165     uint32_t lenReply = 0;
166     uint8_t *buf = NULL;
167     uint8_t tmpFlag = 0;
168     uint8_t *bufReply = NULL;
169     struct SpiMsg *msgs = NULL;
170 
171     if (!HdfSbufReadUint32(data, &count) || (count == 0)) {
172         HDF_LOGE("%s: read count failed!", __func__);
173         return HDF_ERR_IO;
174     }
175 
176     msgs = OsalMemCalloc(sizeof(struct SpiMsg) * count);
177     if (msgs == NULL) {
178         return HDF_ERR_MALLOC_FAIL;
179     }
180 
181     if (SpiMsgsRwProcess(data, count, &tmpFlag, msgs, &lenReply) != HDF_SUCCESS) {
182         HDF_LOGE("%s: SpiMsgsRwProcess fail!", __func__);
183         return HDF_FAILURE;
184     }
185 
186     if (lenReply > 0) {
187         bufReply = OsalMemCalloc(lenReply);
188         if (bufReply == NULL) {
189             return HDF_ERR_MALLOC_FAIL;
190         }
191         for (i = 0, buf = bufReply; i < count && buf < (bufReply + lenReply); i++) {
192             if (msgs[i].rbuf == &tmpFlag) {
193                 msgs[i].rbuf = buf;
194                 buf += msgs[i].len;
195             }
196         }
197     }
198 
199     *ppmsgs = msgs;
200     *pcount = count;
201     *ppbuf = bufReply;
202 
203     return HDF_SUCCESS;
204 }
205 
SpiTransferWriteBackMsgs(struct HdfSBuf * reply,struct SpiMsg * msgs,uint32_t count)206 static int32_t SpiTransferWriteBackMsgs(struct HdfSBuf *reply, struct SpiMsg *msgs, uint32_t count)
207 {
208     uint32_t i;
209 
210     for (i = 0; i < count; i++) {
211         if (msgs[i].rbuf == NULL) {
212             continue;
213         }
214 
215         if (!HdfSbufWriteBuffer(reply, msgs[i].rbuf, msgs[i].len)) {
216             HDF_LOGE("%s: write msg[%u] reply failed!", __func__, i);
217             return HDF_ERR_IO;
218         }
219     }
220 
221     return HDF_SUCCESS;
222 }
223 
SpiIoTransfer(struct SpiCntlr * cntlr,uint32_t csNum,struct HdfSBuf * data,struct HdfSBuf * reply)224 static int32_t SpiIoTransfer(struct SpiCntlr *cntlr, uint32_t csNum, struct HdfSBuf *data, struct HdfSBuf *reply)
225 {
226     int32_t ret;
227     uint32_t count;
228     struct SpiMsg *msgs = NULL;
229     uint8_t *bufReply = NULL;
230 
231     if (data == NULL || reply == NULL) {
232         return HDF_ERR_INVALID_PARAM;
233     }
234 
235     ret = SpiTransferRebuildMsgs(data, &msgs, &count, &bufReply);
236     if (ret != HDF_SUCCESS) {
237         HDF_LOGE("%s: rebuild msgs fail:%d", __func__, ret);
238         goto EXIT;
239     }
240 
241     ret = SpiCntlrTransfer(cntlr, csNum, msgs, count);
242     if (ret != HDF_SUCCESS) {
243         HDF_LOGE("%s: do transfer failed:%d", __func__, ret);
244         goto EXIT;
245     }
246 
247     ret = SpiTransferWriteBackMsgs(reply, msgs, count);
248 
249 EXIT:
250     OsalMemFree(bufReply);
251     OsalMemFree(msgs);
252     return ret;
253 }
254 
SpiIoOpen(struct SpiCntlr * cntlr,uint32_t csNum)255 static inline int32_t SpiIoOpen(struct SpiCntlr *cntlr, uint32_t csNum)
256 {
257     return SpiCntlrOpen(cntlr, csNum);
258 }
259 
SpiIoClose(struct SpiCntlr * cntlr,uint32_t csNum)260 static inline int32_t SpiIoClose(struct SpiCntlr *cntlr, uint32_t csNum)
261 {
262     return SpiCntlrClose(cntlr, csNum);
263 }
264 
SpiIoSetConfig(struct SpiCntlr * cntlr,uint32_t csNum,struct HdfSBuf * data)265 static int32_t SpiIoSetConfig(struct SpiCntlr *cntlr, uint32_t csNum, struct HdfSBuf *data)
266 {
267     uint32_t len;
268     struct SpiCfg *cfg = NULL;
269 
270     if (!HdfSbufReadBuffer(data, (const void **)&cfg, &len) || sizeof(*cfg) != len) {
271         HDF_LOGE("%s: read buffer failed!", __func__);
272         return HDF_ERR_IO;
273     }
274     return SpiCntlrSetCfg(cntlr, csNum, cfg);
275 }
276 
SpiIoGetConfig(struct SpiCntlr * cntlr,uint32_t csNum,struct HdfSBuf * reply)277 static int32_t SpiIoGetConfig(struct SpiCntlr *cntlr, uint32_t csNum, struct HdfSBuf *reply)
278 {
279     int32_t ret;
280     struct SpiCfg cfg;
281 
282     ret = SpiCntlrGetCfg(cntlr, csNum, &cfg);
283     if (ret != HDF_SUCCESS) {
284         HDF_LOGE("%s: get cfg failed!", __func__);
285         return ret;
286     }
287 
288     if (!HdfSbufWriteBuffer(reply, &cfg, sizeof(cfg))) {
289         HDF_LOGE("%s: write buffer failed!", __func__);
290         return HDF_FAILURE;
291     }
292     return HDF_SUCCESS;
293 }
294 
SpiIoDispatch(struct HdfDeviceIoClient * client,int cmd,struct HdfSBuf * data,struct HdfSBuf * reply)295 static int32_t SpiIoDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
296 {
297     int32_t ret;
298     uint32_t csNum;
299     struct SpiCntlr *cntlr = NULL;
300 
301     if (client == NULL || client->device == NULL || client->device->service == NULL) {
302         HDF_LOGE("%s: invalid client", __func__);
303         return HDF_ERR_INVALID_OBJECT;
304     }
305 
306     cntlr = (struct SpiCntlr *)client->device->service;
307     if (data == NULL) {
308         HDF_LOGE("%s: data is NULL", __func__);
309         return HDF_ERR_INVALID_PARAM;
310     }
311 
312     if (!HdfSbufReadUint32(data, &csNum)) {
313         HDF_LOGE("%s: read csNum failed!", __func__);
314         return HDF_ERR_IO;
315     }
316 
317     switch (cmd) {
318         case SPI_IO_OPEN:
319             return SpiIoOpen(cntlr, csNum);
320         case SPI_IO_CLOSE:
321             return SpiIoClose(cntlr, csNum);
322         case SPI_IO_SET_CONFIG:
323             return SpiIoSetConfig(cntlr, csNum, data);
324         case SPI_IO_GET_CONFIG:
325             return SpiIoGetConfig(cntlr, csNum, reply);
326         case SPI_IO_TRANSFER:
327             return SpiIoTransfer(cntlr, csNum, data, reply);
328         default:
329             ret = HDF_ERR_NOT_SUPPORT;
330             break;
331     }
332     return ret;
333 }
334 
SpiCntlrDestroy(struct SpiCntlr * cntlr)335 void SpiCntlrDestroy(struct SpiCntlr *cntlr)
336 {
337     if (cntlr == NULL) {
338         return;
339     }
340     (void)OsalMutexDestroy(&(cntlr->lock));
341     OsalMemFree(cntlr);
342 }
343 
SpiCntlrCreate(struct HdfDeviceObject * device)344 struct SpiCntlr *SpiCntlrCreate(struct HdfDeviceObject *device)
345 {
346     struct SpiCntlr *cntlr = NULL;
347 
348     if (device == NULL) {
349         HDF_LOGE("%s: invalid parameter", __func__);
350         return NULL;
351     }
352 
353     cntlr = (struct SpiCntlr *)OsalMemCalloc(sizeof(*cntlr));
354     if (cntlr == NULL) {
355         HDF_LOGE("%s: OsalMemCalloc error", __func__);
356         return NULL;
357     }
358     cntlr->device = device;
359     device->service = &(cntlr->service);
360     device->service->Dispatch = SpiIoDispatch;
361     (void)OsalMutexInit(&cntlr->lock);
362     DListHeadInit(&cntlr->list);
363     cntlr->priv = NULL;
364     return cntlr;
365 }
366