1 /*
2 * Copyright (c) 2020-2021 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_device.h"
10 #include "hdf_base.h"
11 #include "hdf_device_node.h"
12 #include "hdf_device_token.h"
13 #include "hdf_log.h"
14 #include "hdf_object_manager.h"
15 #include "osal_mem.h"
16
17 #define HDF_LOG_TAG hdf_device
18
19 // device node id less than 129 is configured in hcs, dynamic allocation ID starts from 129
20 #define DYNAMIC_ALLOC_ID 129
21
UpdateDeivceNodeIdIndex(struct HdfDevice * device,devid_t nodeDevid)22 static void UpdateDeivceNodeIdIndex(struct HdfDevice *device, devid_t nodeDevid)
23 {
24 if (device->devidIndex < DEVNODEID(nodeDevid)) {
25 device->devidIndex = DEVNODEID(nodeDevid);
26 }
27 }
28
FindUsableDevNodeId(struct HdfDevice * device)29 static devid_t FindUsableDevNodeId(struct HdfDevice *device)
30 {
31 uint16_t nodeId = DYNAMIC_ALLOC_ID;
32 bool find = false;
33 struct HdfDeviceNode *devNode = NULL;
34 for (; nodeId <= device->devidIndex; nodeId++) {
35 find = false;
36 DLIST_FOR_EACH_ENTRY(devNode, &device->devNodes, struct HdfDeviceNode, entry) {
37 if (DEVNODEID(devNode->devId) == nodeId) {
38 find = true;
39 break;
40 }
41 }
42 if (!find) {
43 return nodeId;
44 }
45 }
46 return nodeId;
47 }
48
AcquireNodeDeivceId(struct HdfDevice * device,devid_t * devid)49 static int AcquireNodeDeivceId(struct HdfDevice *device, devid_t *devid)
50 {
51 devid_t nodeId;
52 devid_t usableId;
53 if (device->devidIndex >= DEVNODEID_MASK) {
54 return HDF_FAILURE;
55 }
56
57 if (device->devidIndex < DYNAMIC_ALLOC_ID) {
58 device->devidIndex = DYNAMIC_ALLOC_ID;
59 nodeId = device->devidIndex;
60 } else {
61 usableId = FindUsableDevNodeId(device);
62 if (usableId <= device->devidIndex) {
63 nodeId = usableId;
64 } else {
65 device->devidIndex++;
66 nodeId = device->devidIndex;
67 }
68 }
69
70 if (devid == NULL) {
71 HDF_LOGE("params invalid *devid");
72 return HDF_ERR_INVALID_PARAM;
73 }
74 *devid = MK_DEVID(HOSTID(device->deviceId), DEVICEID(device->deviceId), nodeId);
75
76 return HDF_SUCCESS;
77 }
78
HdfDeviceAttach(struct IHdfDevice * devInst,struct HdfDeviceNode * devNode)79 static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
80 {
81 int ret;
82 struct HdfDevice *device = (struct HdfDevice *)devInst;
83 struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode;
84
85 if (device == NULL || nodeIf == NULL || nodeIf->LaunchNode == NULL) {
86 HDF_LOGE("failed to attach device, input params invalid");
87 return HDF_ERR_INVALID_PARAM;
88 }
89
90 // for dynamic added device node, assign device id here
91 if (devNode->devId == 0 && AcquireNodeDeivceId(device, &devNode->devId) != HDF_SUCCESS) {
92 HDF_LOGE("failed to attach device, invalid device id");
93 return HDF_ERR_INVALID_PARAM;
94 }
95 devNode->token->devid = devNode->devId;
96 ret = nodeIf->LaunchNode(devNode);
97 if (ret == HDF_SUCCESS) {
98 DListInsertTail(&devNode->entry, &device->devNodes);
99 UpdateDeivceNodeIdIndex(device, devNode->devId);
100 }
101
102 return ret;
103 }
104
HdfDeviceDetach(struct IHdfDevice * devInst,struct HdfDeviceNode * devNode)105 int HdfDeviceDetach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
106 {
107 struct HdfDevice *device = NULL;
108 if (devInst == NULL || devNode == NULL) {
109 return HDF_ERR_INVALID_PARAM;
110 }
111
112 device = CONTAINER_OF(devInst, struct HdfDevice, super);
113 if (DEVICEID(device->deviceId) != DEVICEID(devNode->devId)) {
114 HDF_LOGE("%{public}s: device detach unknown devnode ",
115 __func__);
116 return HDF_DEV_ERR_NO_DEVICE;
117 }
118
119 if (devNode->entry.next != NULL) {
120 DListRemove(&devNode->entry);
121 }
122 if (devNode->super.UnlaunchNode != NULL) {
123 devNode->super.UnlaunchNode(devNode);
124 }
125
126 return HDF_SUCCESS;
127 }
128
HdfDeviceGetDeviceNode(struct IHdfDevice * device,devid_t devid)129 static struct HdfDeviceNode *HdfDeviceGetDeviceNode(struct IHdfDevice *device, devid_t devid)
130 {
131 struct HdfDeviceNode *devNode = NULL;
132 struct HdfDevice *dev = CONTAINER_OF(device, struct HdfDevice, super);
133 DLIST_FOR_EACH_ENTRY(devNode, &dev->devNodes, struct HdfDeviceNode, entry) {
134 if (devNode->devId == devid) {
135 return devNode;
136 };
137 }
138 return NULL;
139 }
140
HdfDeviceDetachWithDevid(struct IHdfDevice * device,devid_t devid)141 static int HdfDeviceDetachWithDevid(struct IHdfDevice *device, devid_t devid)
142 {
143 struct HdfDevice *dev = CONTAINER_OF(device, struct HdfDevice, super);
144 (void)dev;
145 struct HdfDeviceNode *devNode = HdfDeviceGetDeviceNode(device, devid);
146 if (devNode == NULL) {
147 HDF_LOGE("devNode is NULL");
148 return HDF_DEV_ERR_NO_DEVICE;
149 }
150
151 return HdfDeviceDetach(device, devNode);
152 }
153
HdfDeviceConstruct(struct HdfDevice * device)154 void HdfDeviceConstruct(struct HdfDevice *device)
155 {
156 device->super.Attach = HdfDeviceAttach;
157 device->super.Detach = HdfDeviceDetach;
158 device->super.DetachWithDevid = HdfDeviceDetachWithDevid;
159 device->super.GetDeviceNode = HdfDeviceGetDeviceNode;
160
161 DListHeadInit(&device->devNodes);
162 }
163
HdfDeviceDestruct(struct HdfDevice * device)164 void HdfDeviceDestruct(struct HdfDevice *device)
165 {
166 struct HdfDeviceNode *devNode = NULL;
167 struct HdfDeviceNode *tmp = NULL;
168 DLIST_FOR_EACH_ENTRY_SAFE(devNode, tmp, &device->devNodes, struct HdfDeviceNode, entry) {
169 HdfDeviceNodeFreeInstance(devNode);
170 }
171 DListHeadInit(&device->devNodes);
172 }
173
HdfDeviceCreate(void)174 struct HdfObject *HdfDeviceCreate(void)
175 {
176 struct HdfDevice *device = (struct HdfDevice *)OsalMemCalloc(sizeof(struct HdfDevice));
177 if (device != NULL) {
178 HdfDeviceConstruct(device);
179 }
180 return (struct HdfObject *)device;
181 }
182
HdfDeviceRelease(struct HdfObject * object)183 void HdfDeviceRelease(struct HdfObject *object)
184 {
185 struct HdfDevice *device = (struct HdfDevice *)object;
186 if (device != NULL) {
187 HdfDeviceDestruct(device);
188 OsalMemFree(device);
189 }
190 }
191
HdfDeviceNewInstance(void)192 struct HdfDevice *HdfDeviceNewInstance(void)
193 {
194 return (struct HdfDevice *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVICE);
195 }
196
HdfDeviceFreeInstance(struct HdfDevice * device)197 void HdfDeviceFreeInstance(struct HdfDevice *device)
198 {
199 if (device != NULL) {
200 HdfObjectManagerFreeObject(&device->super.object);
201 }
202 }
203