• 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 "i2c_if.h"
10 #include "hdf_base.h"
11 #include "hdf_io_service_if.h"
12 #include "hdf_log.h"
13 #include "osal_mem.h"
14 #include "securec.h"
15 
16 #define HDF_LOG_TAG i2c_if_u
17 
18 #define I2C_SERVICE_NAME "HDF_PLATFORM_I2C_MANAGER"
19 
I2cManagerGetService(void)20 static void *I2cManagerGetService(void)
21 {
22     static void *manager = NULL;
23 
24     if (manager != NULL) {
25         return manager;
26     }
27     manager = (void *)HdfIoServiceBind(I2C_SERVICE_NAME);
28     if (manager == NULL) {
29         HDF_LOGE("I2cManagerGetService: fail to get i2c manager!");
30     }
31     return manager;
32 }
33 
I2cOpen(int16_t number)34 DevHandle I2cOpen(int16_t number)
35 {
36     int32_t ret;
37     struct HdfIoService *service = NULL;
38     struct HdfSBuf *data = NULL;
39     struct HdfSBuf *reply = NULL;
40     uint32_t handle = 0;
41 
42     service = (struct HdfIoService *)I2cManagerGetService();
43     if (service == NULL ||service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
44         HDF_LOGE("I2cOpen: service is invalid!");
45         return NULL;
46     }
47     data = HdfSbufObtainDefaultSize();
48     if (data == NULL) {
49         HDF_LOGE("I2cOpen: obtain data fail!");
50         return NULL;
51     }
52     reply = HdfSbufObtainDefaultSize();
53     if (reply == NULL) {
54         HDF_LOGE("I2cOpen: obtain reply fail!");
55         HdfSbufRecycle(data);
56         return NULL;
57     }
58 
59     if (!HdfSbufWriteUint16(data, (uint16_t)number)) {
60         HDF_LOGE("I2cOpen: write number fail!");
61         goto EXIT;
62     }
63 
64     ret = service->dispatcher->Dispatch(&service->object, I2C_IO_OPEN, data, reply);
65     if (ret != HDF_SUCCESS) {
66         HDF_LOGE("I2cOpen: service call open fail:%d", ret);
67         goto EXIT;
68     }
69 
70     if (!HdfSbufReadUint32(reply, &handle)) {
71         HDF_LOGE("I2cOpen: read handle fail!");
72         goto EXIT;
73     }
74 EXIT:
75     HdfSbufRecycle(data);
76     HdfSbufRecycle(reply);
77     return (handle == 0) ? NULL : (DevHandle)(uintptr_t)handle;
78 }
79 
I2cClose(DevHandle handle)80 void I2cClose(DevHandle handle)
81 {
82     int32_t ret;
83     struct HdfIoService *service = NULL;
84     struct HdfSBuf *data = NULL;
85 
86     service = (struct HdfIoService *)I2cManagerGetService();
87     if (service == NULL ||service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
88         HDF_LOGE("I2cOpen: service is invalid!");
89         return;
90     }
91 
92     data = HdfSbufObtainDefaultSize();
93     if (data == NULL) {
94         return;
95     }
96 
97     if (!HdfSbufWriteUint32(data, (uint32_t)(uintptr_t)handle)) {
98         HDF_LOGE("I2cClose: write handle fail!");
99         HdfSbufRecycle(data);
100         return;
101     }
102 
103     ret = service->dispatcher->Dispatch(&service->object, I2C_IO_CLOSE, data, NULL);
104     if (ret != HDF_SUCCESS) {
105         HDF_LOGE("I2cClose: close handle fail:%d", ret);
106     }
107     HdfSbufRecycle(data);
108 }
109 
I2cMsgWriteArray(DevHandle handle,struct HdfSBuf * data,struct I2cMsg * msgs,int16_t count)110 static int32_t I2cMsgWriteArray(DevHandle handle, struct HdfSBuf *data, struct I2cMsg *msgs, int16_t count)
111 {
112     int16_t i;
113 
114     if (!HdfSbufWriteUint32(data, (uint32_t)(uintptr_t)handle)) {
115         HDF_LOGE("I2cMsgWriteArray: write handle fail!");
116         return HDF_ERR_IO;
117     }
118     if (!HdfSbufWriteInt16(data, count)) {
119         HDF_LOGE("I2cMsgWriteArray: write count fail!");
120         return HDF_ERR_IO;
121     }
122 
123     for (i = 0; i < count; i++) {
124         if (!HdfSbufWriteUint16(data, msgs[i].addr)) {
125             HDF_LOGE("I2cMsgWriteArray: write addr fail!");
126             return HDF_ERR_IO;
127         }
128         if (!HdfSbufWriteUint16(data, msgs[i].flags)) {
129             HDF_LOGE("I2cMsgWriteArray: write flags fail!");
130             return HDF_ERR_IO;
131         }
132         if (!HdfSbufWriteUint16(data, msgs[i].len)) {
133             HDF_LOGE("I2cMsgWriteArray: write len fail!");
134             return HDF_ERR_IO;
135         }
136         if ((msgs[i].flags & I2C_FLAG_READ) != 0) {
137             continue;
138         }
139         if (!HdfSbufWriteBuffer(data, (uint8_t *)msgs[i].buf, msgs[i].len)) {
140             HDF_LOGE("I2cMsgWriteArray: write msg[%d] buf fail!", i);
141             return HDF_ERR_IO;
142         }
143     }
144 
145     return HDF_SUCCESS;
146 }
147 
I2cMsgReadBack(struct HdfSBuf * data,struct I2cMsg * msg)148 static int32_t I2cMsgReadBack(struct HdfSBuf *data, struct I2cMsg *msg)
149 {
150     uint32_t rLen;
151     const void *rBuf = NULL;
152 
153     if ((msg->flags & I2C_FLAG_READ) == 0) {
154         return HDF_SUCCESS; /* write msg no need to read back */
155     }
156 
157     if (!HdfSbufReadBuffer(data, &rBuf, &rLen)) {
158         HDF_LOGE("I2cMsgReadBack: read rBuf fail!");
159         return HDF_ERR_IO;
160     }
161     if (msg->len != rLen) {
162         HDF_LOGE("I2cMsgReadBack: err len:%u, rLen:%u", msg->len, rLen);
163         if (rLen > msg->len) {
164             rLen = msg->len;
165         }
166     }
167     if (memcpy_s(msg->buf, msg->len, rBuf, rLen) != EOK) {
168         HDF_LOGE("I2cMsgReadBack: memcpy rBuf fail!");
169         return HDF_ERR_IO;
170     }
171 
172     return HDF_SUCCESS;
173 }
174 
I2cMsgReadArray(struct HdfSBuf * reply,struct I2cMsg * msgs,int16_t count)175 static inline int32_t I2cMsgReadArray(struct HdfSBuf *reply, struct I2cMsg *msgs, int16_t count)
176 {
177     int16_t i;
178     int32_t ret;
179 
180     for (i = 0; i < count; i++) {
181         ret = I2cMsgReadBack(reply, &msgs[i]);
182         if (ret != HDF_SUCCESS) {
183             return ret;
184         }
185     }
186     return HDF_SUCCESS;
187 }
188 
I2cServiceTransfer(DevHandle handle,struct I2cMsg * msgs,int16_t count)189 static int32_t I2cServiceTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t count)
190 {
191     int16_t i;
192     int32_t ret;
193     uint32_t recvLen = 0;
194     struct HdfSBuf *data = NULL;
195     struct HdfSBuf *reply = NULL;
196     struct HdfIoService *service = NULL;
197 
198     data = HdfSbufObtainDefaultSize();
199     if (data == NULL) {
200         HDF_LOGE("I2cServiceTransfer: failed to obtain data!");
201         return HDF_ERR_MALLOC_FAIL;
202     }
203 
204     ret = I2cMsgWriteArray(handle, data, msgs, count);
205     if (ret != HDF_SUCCESS) {
206         HDF_LOGE("I2cServiceTransfer: failed to write msgs!");
207         goto EXIT;
208     }
209 
210     for (i = 0; i < count; i++) {
211         recvLen += ((msgs[i].flags & I2C_FLAG_READ) == 0) ? 0 : (msgs[i].len + sizeof(uint64_t));
212     }
213     reply = (recvLen == 0) ? HdfSbufObtainDefaultSize() : HdfSbufObtain(recvLen);
214     if (reply == NULL) {
215         HDF_LOGE("I2cServiceTransfer: failed to obtain reply!");
216         ret = HDF_ERR_MALLOC_FAIL;
217         goto EXIT;
218     }
219 
220     service = (struct HdfIoService *)I2cManagerGetService();
221     if (service == NULL ||service->dispatcher == NULL || service->dispatcher->Dispatch == NULL) {
222         ret = HDF_ERR_NOT_SUPPORT;
223         goto EXIT;
224     }
225     ret = service->dispatcher->Dispatch(&service->object, I2C_IO_TRANSFER, data, reply);
226     if (ret != HDF_SUCCESS) {
227         HDF_LOGE("I2cServiceTransfer: failed to send service call:%d", ret);
228         goto EXIT;
229     }
230 
231     ret = I2cMsgReadArray(reply, msgs, count);
232     if (ret != HDF_SUCCESS) {
233         goto EXIT;
234     }
235 
236     ret = count;
237 EXIT:
238     if (data != NULL) {
239         HdfSbufRecycle(data);
240     }
241     if (reply != NULL) {
242         HdfSbufRecycle(reply);
243     }
244     return ret;
245 }
246 
I2cTransfer(DevHandle handle,struct I2cMsg * msgs,int16_t count)247 int32_t I2cTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t count)
248 {
249     if (handle == NULL) {
250         return HDF_ERR_INVALID_OBJECT;
251     }
252 
253     if (msgs == NULL || count <= 0) {
254         HDF_LOGE("I2cTransfer: err params! msgs:%s, count:%d",
255             (msgs == NULL) ? "0" : "x", count);
256         return HDF_ERR_INVALID_PARAM;
257     }
258 
259     return I2cServiceTransfer(handle, msgs, count);
260 }
261 
262