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 *devid = MK_DEVID(HOSTID(device->deviceId), DEVICEID(device->deviceId), nodeId);
71
72 return HDF_SUCCESS;
73 }
74
HdfDeviceAttach(struct IHdfDevice * devInst,struct HdfDeviceNode * devNode)75 static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
76 {
77 int ret;
78 struct HdfDevice *device = (struct HdfDevice *)devInst;
79 struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode;
80
81 if (device == NULL || nodeIf == NULL || nodeIf->LaunchNode == NULL) {
82 HDF_LOGE("failed to attach device, input params invalid");
83 return HDF_ERR_INVALID_PARAM;
84 }
85
86 // for dynamic added device node, assign device id here
87 if (devNode->devId == 0 && AcquireNodeDeivceId(device, &devNode->devId) != HDF_SUCCESS) {
88 HDF_LOGE("failed to attach device, invalid device id");
89 return HDF_ERR_INVALID_PARAM;
90 }
91 devNode->token->devid = devNode->devId;
92 ret = nodeIf->LaunchNode(devNode);
93 if (ret == HDF_SUCCESS) {
94 DListInsertTail(&devNode->entry, &device->devNodes);
95 UpdateDeivceNodeIdIndex(device, devNode->devId);
96 }
97
98 return ret;
99 }
100
HdfDeviceDetach(struct IHdfDevice * devInst,struct HdfDeviceNode * devNode)101 int HdfDeviceDetach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
102 {
103 struct HdfDevice *device = NULL;
104 if (devInst == NULL || devNode == NULL) {
105 return HDF_ERR_INVALID_PARAM;
106 }
107
108 device = CONTAINER_OF(devInst, struct HdfDevice, super);
109 if (DEVICEID(device->deviceId) != DEVICEID(devNode->devId)) {
110 HDF_LOGE("%s: device %x detach unknown devnode %x", __func__, device->deviceId, devNode->devId);
111 return HDF_DEV_ERR_NO_DEVICE;
112 }
113
114 if (devNode->entry.next != NULL) {
115 DListRemove(&devNode->entry);
116 }
117 if (devNode->super.UnlaunchNode != NULL) {
118 devNode->super.UnlaunchNode(devNode);
119 }
120
121 return HDF_SUCCESS;
122 }
123
HdfDeviceGetDeviceNode(struct IHdfDevice * device,devid_t devid)124 static struct HdfDeviceNode *HdfDeviceGetDeviceNode(struct IHdfDevice *device, devid_t devid)
125 {
126 struct HdfDeviceNode *devNode = NULL;
127 struct HdfDevice *dev = CONTAINER_OF(device, struct HdfDevice, super);
128 DLIST_FOR_EACH_ENTRY(devNode, &dev->devNodes, struct HdfDeviceNode, entry) {
129 if (devNode->devId == devid) {
130 return devNode;
131 };
132 }
133 return NULL;
134 }
135
HdfDeviceDetachWithDevid(struct IHdfDevice * device,devid_t devid)136 static int HdfDeviceDetachWithDevid(struct IHdfDevice *device, devid_t devid)
137 {
138 struct HdfDevice *dev = CONTAINER_OF(device, struct HdfDevice, super);
139 struct HdfDeviceNode *devNode = HdfDeviceGetDeviceNode(device, devid);
140 if (devNode == NULL) {
141 HDF_LOGE("detach device node %x not in device %x", devid, dev->deviceId);
142 return HDF_DEV_ERR_NO_DEVICE;
143 }
144
145 return HdfDeviceDetach(device, devNode);
146 }
147
HdfDeviceConstruct(struct HdfDevice * device)148 void HdfDeviceConstruct(struct HdfDevice *device)
149 {
150 device->super.Attach = HdfDeviceAttach;
151 device->super.Detach = HdfDeviceDetach;
152 device->super.DetachWithDevid = HdfDeviceDetachWithDevid;
153 device->super.GetDeviceNode = HdfDeviceGetDeviceNode;
154
155 DListHeadInit(&device->devNodes);
156 }
157
HdfDeviceDestruct(struct HdfDevice * device)158 void HdfDeviceDestruct(struct HdfDevice *device)
159 {
160 struct HdfDeviceNode *devNode = NULL;
161 struct HdfDeviceNode *tmp = NULL;
162 DLIST_FOR_EACH_ENTRY_SAFE(devNode, tmp, &device->devNodes, struct HdfDeviceNode, entry) {
163 HdfDeviceNodeFreeInstance(devNode);
164 }
165 DListHeadInit(&device->devNodes);
166 }
167
HdfDeviceCreate(void)168 struct HdfObject *HdfDeviceCreate(void)
169 {
170 struct HdfDevice *device = (struct HdfDevice *)OsalMemCalloc(sizeof(struct HdfDevice));
171 if (device != NULL) {
172 HdfDeviceConstruct(device);
173 }
174 return (struct HdfObject *)device;
175 }
176
HdfDeviceRelease(struct HdfObject * object)177 void HdfDeviceRelease(struct HdfObject *object)
178 {
179 struct HdfDevice *device = (struct HdfDevice *)object;
180 if (device != NULL) {
181 HdfDeviceDestruct(device);
182 OsalMemFree(device);
183 }
184 }
185
HdfDeviceNewInstance(void)186 struct HdfDevice *HdfDeviceNewInstance(void)
187 {
188 return (struct HdfDevice *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVICE);
189 }
190
HdfDeviceFreeInstance(struct HdfDevice * device)191 void HdfDeviceFreeInstance(struct HdfDevice *device)
192 {
193 if (device != NULL) {
194 HdfObjectManagerFreeObject(&device->super.object);
195 }
196 }
197