1 /*
2  * Copyright (c) 2022-2023 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 "device_resource_if.h"
10 #include "hdf_log.h"
11 #include "osal_io.h"
12 #include "osal_mem.h"
13 #include "pin/pin_core.h"
14 
15 #define HDF_LOG_TAG pin_virtual
16 
17 #define VIRTUAL_PIN_FUNC_MAX  6
18 #define VIRTUAL_PIN_MAX_NUMBER 16
19 #define VIRTUAL_PIN_MAX_PIN_COUNT 32
20 
21 
22 struct VirtualPinDesc {
23     const char *pinName;
24     uint32_t init;
25     uint32_t index;
26     int32_t pullType;
27     int32_t strength;
28     const char *curFunc;
29     const char *func[VIRTUAL_PIN_FUNC_MAX];
30 };
31 
32 struct VirtualPinCntlr {
33     struct PinCntlr cntlr;
34     struct VirtualPinDesc *desc;
35     uint16_t number;
36     uint32_t pinCount;
37 };
38 
VirtualPinSetPull(struct PinCntlr * cntlr,uint32_t index,enum PinPullType pullType)39 static int32_t VirtualPinSetPull(struct PinCntlr *cntlr, uint32_t index, enum PinPullType pullType)
40 {
41     struct VirtualPinCntlr *virtual = NULL;
42 
43     if (cntlr == NULL) {
44         HDF_LOGE("VirtualPinSetPull: cntlr is null!");
45         return HDF_ERR_INVALID_OBJECT;
46     }
47 
48     if (index >= cntlr->pinCount) {
49         HDF_LOGE("VirtualPinSetPull: invalid index:%u!", index);
50         return HDF_ERR_INVALID_PARAM;
51     }
52 
53     virtual = (struct VirtualPinCntlr *)cntlr;
54     virtual->desc[index].pullType = pullType;
55     return HDF_SUCCESS;
56 }
57 
VirtualPinGetPull(struct PinCntlr * cntlr,uint32_t index,enum PinPullType * pullType)58 static int32_t VirtualPinGetPull(struct PinCntlr *cntlr, uint32_t index, enum PinPullType *pullType)
59 {
60     struct VirtualPinCntlr *virtual = NULL;
61 
62     if (cntlr == NULL || pullType == NULL) {
63         HDF_LOGE("VirtualPinGetPull: cntlr or pullType is null!");
64         return HDF_ERR_INVALID_OBJECT;
65     }
66 
67     if (index >= cntlr->pinCount) {
68         HDF_LOGE("VirtualPinGetPull: invalid index:%u!", index);
69         return HDF_ERR_INVALID_PARAM;
70     }
71 
72     virtual = (struct VirtualPinCntlr *)cntlr;
73     *pullType = virtual->desc[index].pullType;
74     return HDF_SUCCESS;
75 }
76 
VirtualPinSetStrength(struct PinCntlr * cntlr,uint32_t index,uint32_t strength)77 static int32_t VirtualPinSetStrength(struct PinCntlr *cntlr, uint32_t index, uint32_t strength)
78 {
79     struct VirtualPinCntlr *virtual = NULL;
80 
81     if (cntlr == NULL) {
82         HDF_LOGE("VirtualPinSetStrength: cntlr is null!");
83         return HDF_ERR_INVALID_OBJECT;
84     }
85 
86     if (index >= cntlr->pinCount) {
87         HDF_LOGE("VirtualPinSetStrength: invalid index:%u!", index);
88         return HDF_ERR_INVALID_PARAM;
89     }
90 
91     virtual = (struct VirtualPinCntlr *)cntlr;
92     virtual->desc[index].strength = strength;
93     return HDF_SUCCESS;
94 }
95 
VirtualPinGetStrength(struct PinCntlr * cntlr,uint32_t index,uint32_t * strength)96 static int32_t VirtualPinGetStrength(struct PinCntlr *cntlr, uint32_t index, uint32_t *strength)
97 {
98     struct VirtualPinCntlr *virtual = NULL;
99 
100     if (cntlr == NULL || strength == NULL) {
101         HDF_LOGE("VirtualPinGetStrength: cntlr or strength is null!");
102         return HDF_ERR_INVALID_OBJECT;
103     }
104 
105     if (index >= cntlr->pinCount) {
106         HDF_LOGE("VirtualPinGetStrength: invalid index:%u!", index);
107         return HDF_ERR_INVALID_PARAM;
108     }
109 
110     virtual = (struct VirtualPinCntlr *)cntlr;
111     *strength = virtual->desc[index].strength;
112     return HDF_SUCCESS;
113 }
114 
VirtualPinSetFunc(struct PinCntlr * cntlr,uint32_t index,const char * funcName)115 static int32_t VirtualPinSetFunc(struct PinCntlr *cntlr, uint32_t index, const char *funcName)
116 {
117     int ret;
118     uint32_t funcNum;
119     struct VirtualPinCntlr *virtual = NULL;
120 
121     if (cntlr == NULL || funcName == NULL) {
122         HDF_LOGE("VirtualPinSetFunc: cntlr or funcName is null!");
123         return HDF_ERR_INVALID_OBJECT;
124     }
125 
126     if (index >= cntlr->pinCount) {
127         HDF_LOGE("VirtualPinSetFunc: invalid index:%u!", index);
128         return HDF_ERR_INVALID_PARAM;
129     }
130 
131     virtual = (struct VirtualPinCntlr *)cntlr;
132 
133     for (funcNum = 0; funcNum < VIRTUAL_PIN_FUNC_MAX; funcNum++) {
134         ret = strcmp(funcName, virtual->desc[index].func[funcNum]);
135         if (ret == 0) {
136             virtual->desc[index].curFunc = virtual->desc[index].func[funcNum];
137             return HDF_SUCCESS;
138         }
139     }
140     HDF_LOGE("VirtualPinSetFunc: set pin function fail!");
141     return HDF_ERR_IO;
142 }
143 
VirtualPinGetFunc(struct PinCntlr * cntlr,uint32_t index,const char ** funcName)144 static int32_t VirtualPinGetFunc(struct PinCntlr *cntlr, uint32_t index, const char **funcName)
145 {
146     struct VirtualPinCntlr *virtual = NULL;
147 
148     if (cntlr == NULL || funcName == NULL) {
149         HDF_LOGE("VirtualPinGetFunc: cntlr or funcName is null!");
150         return HDF_ERR_INVALID_OBJECT;
151     }
152 
153     if (index >= cntlr->pinCount) {
154         HDF_LOGE("VirtualPinGetFunc: invalid index:%u!", index);
155         return HDF_ERR_INVALID_PARAM;
156     }
157 
158     virtual = (struct VirtualPinCntlr *)cntlr;
159     *funcName = virtual->desc[index].curFunc;
160     HDF_LOGD("VirtualPinGetFunc: get pin function success!");
161     return HDF_SUCCESS;
162 }
163 
164 static struct PinCntlrMethod g_method = {
165     .SetPinPull = VirtualPinSetPull,
166     .GetPinPull = VirtualPinGetPull,
167     .SetPinStrength = VirtualPinSetStrength,
168     .GetPinStrength = VirtualPinGetStrength,
169     .SetPinFunc = VirtualPinSetFunc,
170     .GetPinFunc = VirtualPinGetFunc,
171 };
172 
VirtualPinReadFunc(struct VirtualPinDesc * desc,const struct DeviceResourceNode * node,struct DeviceResourceIface * drsOps)173 static int32_t VirtualPinReadFunc(struct VirtualPinDesc *desc,
174     const struct DeviceResourceNode *node, struct DeviceResourceIface *drsOps)
175 {
176     int32_t ret;
177     uint32_t funcNum = 0;
178 
179     ret = drsOps->GetString(node, "F0", &desc->func[funcNum], "NULL");
180     if (ret != HDF_SUCCESS) {
181         HDF_LOGE("VirtualPinReadFunc: read F0 fail, ret: %d!", ret);
182         return ret;
183     }
184 
185     funcNum++;
186     ret = drsOps->GetString(node, "F1", &desc->func[funcNum], "NULL");
187     if (ret != HDF_SUCCESS) {
188         HDF_LOGE("VirtualPinReadFunc: read F1 fail, ret: %d!", ret);
189         return ret;
190     }
191 
192     funcNum++;
193     ret = drsOps->GetString(node, "F2", &desc->func[funcNum], "NULL");
194     if (ret != HDF_SUCCESS) {
195         HDF_LOGE("VirtualPinReadFunc: read F2 fail, ret: %d!", ret);
196         return ret;
197     }
198 
199     funcNum++;
200     ret = drsOps->GetString(node, "F3", &desc->func[funcNum], "NULL");
201     if (ret != HDF_SUCCESS) {
202         HDF_LOGE("VirtualPinReadFunc: read F3 fail, ret: %d!", ret);
203         return ret;
204     }
205 
206     funcNum++;
207     ret = drsOps->GetString(node, "F4", &desc->func[funcNum], "NULL");
208     if (ret != HDF_SUCCESS) {
209         HDF_LOGE("VirtualPinReadFunc: read F4 fail, ret: %d!", ret);
210         return ret;
211     }
212 
213     funcNum++;
214     ret = drsOps->GetString(node, "F5", &desc->func[funcNum], "NULL");
215     if (ret != HDF_SUCCESS) {
216         HDF_LOGE("VirtualPinReadFunc: read F5 fail, ret: %d!", ret);
217         return ret;
218     }
219     return HDF_SUCCESS;
220 }
221 
VirtualPinParsePinNode(const struct DeviceResourceNode * node,struct VirtualPinCntlr * virtual,int32_t index)222 static int32_t VirtualPinParsePinNode(const struct DeviceResourceNode *node,
223     struct VirtualPinCntlr *virtual, int32_t index)
224 {
225     int32_t ret;
226     struct DeviceResourceIface *drsOps = NULL;
227 
228     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
229     if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
230         HDF_LOGE("VirtualPinParsePinNode: invalid drs or ops!");
231         return HDF_FAILURE;
232     }
233     ret = drsOps->GetString(node, "pinName", &virtual->desc[index].pinName, "NULL");
234     if (ret != HDF_SUCCESS) {
235         HDF_LOGE("VirtualPinParsePinNode: read pinName fail, ret: %d!", ret);
236         return ret;
237     }
238 
239     ret = drsOps->GetUint32(node, "init", &virtual->desc[index].init, 0);
240     if (ret != HDF_SUCCESS) {
241         HDF_LOGE("VirtualPinParsePinNode: read init fail, ret: %d!", ret);
242         return ret;
243     }
244 
245     ret = VirtualPinReadFunc(&virtual->desc[index], node, drsOps);
246     if (ret != HDF_SUCCESS) {
247         HDF_LOGE("VirtualPinParsePinNode: pin read func fail, ret: %d!", ret);
248         return ret;
249     }
250     virtual->cntlr.pins[index].pinName = virtual->desc[index].pinName;
251     virtual->cntlr.pins[index].priv = (void *)node;
252     virtual->desc[index].curFunc = virtual->desc[index].func[0]; // default func
253     HDF_LOGD("VirtualPinParsePinNode: pin parse pin node %s success!", virtual->cntlr.pins[index].pinName);
254     return HDF_SUCCESS;
255 }
256 
VirtualPinCntlrInit(struct HdfDeviceObject * device,struct VirtualPinCntlr * virtual)257 static int32_t VirtualPinCntlrInit(struct HdfDeviceObject *device, struct VirtualPinCntlr *virtual)
258 {
259     struct DeviceResourceIface *drsOps = NULL;
260     int32_t ret;
261 
262     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
263     if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
264         HDF_LOGE("VirtualPinCntlrInit: invalid drs ops fail!");
265         return HDF_FAILURE;
266     }
267 
268     ret = drsOps->GetUint16(device->property, "number", &virtual->number, 0);
269     if (ret != HDF_SUCCESS) {
270         HDF_LOGE("VirtualPinCntlrInit: read number fail, ret: %d!", ret);
271         return ret;
272     }
273     if (virtual->number > VIRTUAL_PIN_MAX_NUMBER) {
274         HDF_LOGE("VirtualPinCntlrInit: invalid number:%hu!", virtual->number);
275         return HDF_ERR_INVALID_PARAM;
276     }
277 
278     ret = drsOps->GetUint32(device->property, "pinCount", &virtual->pinCount, 0);
279     if (ret != HDF_SUCCESS) {
280         HDF_LOGE("VirtualPinCntlrInit: read pinCount fail, ret: %d!", ret);
281         return ret;
282     }
283     if (virtual->pinCount >= VIRTUAL_PIN_MAX_PIN_COUNT) {
284         HDF_LOGE("VirtualPinCntlrInit: invalid pinCount:%u!", virtual->pinCount);
285         return HDF_ERR_INVALID_PARAM;
286     }
287 
288     virtual->cntlr.pinCount = virtual->pinCount;
289     virtual->cntlr.number = virtual->number;
290     virtual->desc = (struct VirtualPinDesc *)OsalMemCalloc(sizeof(struct VirtualPinDesc) * virtual->pinCount);
291     if (virtual->desc == NULL) {
292         HDF_LOGE("VirtualPinCntlrInit: memcalloc virtual desc fail!");
293         return HDF_ERR_MALLOC_FAIL;
294     }
295     virtual->cntlr.pins = (struct PinDesc *)OsalMemCalloc(sizeof(struct PinDesc) * virtual->pinCount);
296     if (virtual->cntlr.pins == NULL) {
297         HDF_LOGE("VirtualPinCntlrInit: memcalloc virtual cntlr pins fail!");
298         OsalMemFree(virtual->desc);
299         return HDF_ERR_MALLOC_FAIL;
300     }
301     return HDF_SUCCESS;
302 }
303 
VirtualPinBind(struct HdfDeviceObject * device)304 static int32_t VirtualPinBind(struct HdfDeviceObject *device)
305 {
306     (void)device;
307     return HDF_SUCCESS;
308 }
309 
VirtualPinInit(struct HdfDeviceObject * device)310 static int32_t VirtualPinInit(struct HdfDeviceObject *device)
311 {
312     int32_t ret;
313     int32_t index = 0;
314     const struct DeviceResourceNode *childNode = NULL;
315     struct VirtualPinCntlr *virtual = NULL;
316 
317     virtual = (struct VirtualPinCntlr *)OsalMemCalloc(sizeof(*virtual));
318     if (virtual == NULL) {
319         HDF_LOGE("VirtualPinInit: memcalloc virtual fail!");
320         return HDF_ERR_MALLOC_FAIL;
321     }
322 
323     ret = VirtualPinCntlrInit(device, virtual);
324     if (ret != HDF_SUCCESS) {
325         HDF_LOGE("VirtualPinInit: pin cntlr init fail, ret: %d!", ret);
326         OsalMemFree(virtual);
327         return ret;
328     }
329 
330     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
331         ret = VirtualPinParsePinNode(childNode, virtual, index);
332         if (ret != HDF_SUCCESS) {
333             HDF_LOGE("VirtualPinInit: pin parse node fail, ret: %d!", ret);
334             OsalMemFree(virtual);
335             OsalMemFree(virtual->desc);
336             OsalMemFree(virtual->cntlr.pins);
337             return ret;
338         }
339         index++;
340     }
341 
342     virtual->cntlr.method = &g_method;
343     ret = PinCntlrAdd(&virtual->cntlr);
344     if (ret != HDF_SUCCESS) {
345         HDF_LOGE("VirtualPinInit: add pin cntlr fail, ret: %d!", ret);
346         OsalMemFree(virtual);
347         OsalMemFree(virtual->desc);
348         OsalMemFree(virtual->cntlr.pins);
349         return ret;
350     }
351     HDF_LOGI("VirtualPinInit: pin init success!");
352     return HDF_SUCCESS;
353 }
354 
VirtualPinRelease(struct HdfDeviceObject * device)355 static void VirtualPinRelease(struct HdfDeviceObject *device)
356 {
357     int32_t ret;
358     uint16_t number;
359     struct PinCntlr *cntlr = NULL;
360     struct VirtualPinCntlr *virtual = NULL;
361     struct DeviceResourceIface *drsOps = NULL;
362 
363     HDF_LOGI("VirtualPinRelease: enter!");
364     if (device == NULL || device->property == NULL) {
365         HDF_LOGE("VirtualPinRelease: device or property is null!");
366         return;
367     }
368     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
369     if (drsOps == NULL || drsOps->GetUint16 == NULL) {
370         HDF_LOGE("VirtualPinRelease: invalid drs ops!");
371         return;
372     }
373 
374     ret = drsOps->GetUint16(device->property, "number", &number, 0);
375     if (ret != HDF_SUCCESS) {
376         HDF_LOGE("VirtualPinRelease: read cntlr number fail, ret: %d!", ret);
377         return;
378     }
379 
380     cntlr = PinCntlrGetByNumber(number);
381     if (cntlr == NULL) {
382         HDF_LOGE("VirtualPinRelease: cntlr is null!");
383         return;
384     }
385 
386     PinCntlrRemove(cntlr);
387     virtual = (struct VirtualPinCntlr *)cntlr;
388     OsalMemFree(virtual->desc);
389     OsalMemFree(virtual->cntlr.pins);
390     OsalMemFree(virtual);
391 }
392 
393 static struct HdfDriverEntry g_virtualPinDriverEntry = {
394     .moduleVersion = 1,
395     .Bind = VirtualPinBind,
396     .Init = VirtualPinInit,
397     .Release = VirtualPinRelease,
398     .moduleName = "virtual_pin_driver",
399 };
400 HDF_INIT(g_virtualPinDriverEntry);
401