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