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
UpdateDeivceNodeIdIndex(struct HdfDevice * device,devid_t nodeDevid)19 static void UpdateDeivceNodeIdIndex(struct HdfDevice *device, devid_t nodeDevid)
20 {
21 if (device->devidIndex < DEVICEID(nodeDevid)) {
22 device->devidIndex = DEVICEID(nodeDevid);
23 }
24 }
25
AcquireNodeDeivceId(struct HdfDevice * device,devid_t * devid)26 static int AcquireNodeDeivceId(struct HdfDevice *device, devid_t *devid)
27 {
28 if (device->devidIndex >= DEVICEID_MASK) {
29 return HDF_FAILURE;
30 }
31 device->devidIndex++;
32 *devid = MK_DEVID(HOSTID(device->deviceId), DEVICEID(device->deviceId), device->devidIndex);
33
34 return HDF_SUCCESS;
35 }
36
HdfDeviceAttach(struct IHdfDevice * devInst,struct HdfDeviceNode * devNode)37 static int HdfDeviceAttach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
38 {
39 int ret;
40 struct HdfDevice *device = (struct HdfDevice *)devInst;
41 struct IDeviceNode *nodeIf = (struct IDeviceNode *)devNode;
42
43 if (device == NULL || nodeIf == NULL || nodeIf->LaunchNode == NULL) {
44 HDF_LOGE("failed to attach device, input params invalid");
45 return HDF_ERR_INVALID_PARAM;
46 }
47
48 // for dynamic added device node, assign device id here
49 if (devNode->devId == 0 && AcquireNodeDeivceId(device, &devNode->devId) != HDF_SUCCESS) {
50 HDF_LOGE("failed to attach device, invalid device id");
51 return HDF_ERR_INVALID_PARAM;
52 }
53 devNode->token->devid = devNode->devId;
54 ret = nodeIf->LaunchNode(devNode);
55 if (ret == HDF_SUCCESS) {
56 DListInsertTail(&devNode->entry, &device->devNodes);
57 UpdateDeivceNodeIdIndex(device, devNode->devId);
58 }
59
60 return ret;
61 }
62
HdfDeviceDetach(struct IHdfDevice * devInst,struct HdfDeviceNode * devNode)63 int HdfDeviceDetach(struct IHdfDevice *devInst, struct HdfDeviceNode *devNode)
64 {
65 struct HdfDevice *device = NULL;
66 if (devInst == NULL || devNode == NULL) {
67 return HDF_ERR_INVALID_PARAM;
68 }
69
70 device = CONTAINER_OF(devInst, struct HdfDevice, super);
71 if (DEVICEID(device->deviceId) != DEVICEID(devNode->devId)) {
72 HDF_LOGE("%s: device %x detach unknown devnode %x", __func__, device->deviceId, devNode->devId);
73 return HDF_DEV_ERR_NO_DEVICE;
74 }
75
76 if (devNode->entry.next != NULL) {
77 DListRemove(&devNode->entry);
78 }
79 if (devNode->super.UnlaunchNode != NULL) {
80 devNode->super.UnlaunchNode(devNode);
81 }
82
83 return HDF_SUCCESS;
84 }
85
HdfDeviceGetDeviceNode(struct IHdfDevice * device,devid_t devid)86 static struct HdfDeviceNode *HdfDeviceGetDeviceNode(struct IHdfDevice *device, devid_t devid)
87 {
88 struct HdfDeviceNode *devNode = NULL;
89 struct HdfDevice *dev = CONTAINER_OF(device, struct HdfDevice, super);
90 DLIST_FOR_EACH_ENTRY(devNode, &dev->devNodes, struct HdfDeviceNode, entry) {
91 if (devNode->devId == devid) {
92 return devNode;
93 };
94 }
95 return NULL;
96 }
97
HdfDeviceDetachWithDevid(struct IHdfDevice * device,devid_t devid)98 static int HdfDeviceDetachWithDevid(struct IHdfDevice *device, devid_t devid)
99 {
100 struct HdfDevice *dev = CONTAINER_OF(device, struct HdfDevice, super);
101 struct HdfDeviceNode *devNode = HdfDeviceGetDeviceNode(device, devid);
102 if (devNode == NULL) {
103 HDF_LOGE("detach device node %x not in device %x", devid, dev->deviceId);
104 return HDF_DEV_ERR_NO_DEVICE;
105 }
106
107 return HdfDeviceDetach(device, devNode);
108 }
109
HdfDeviceConstruct(struct HdfDevice * device)110 void HdfDeviceConstruct(struct HdfDevice *device)
111 {
112 device->super.Attach = HdfDeviceAttach;
113 device->super.Detach = HdfDeviceDetach;
114 device->super.DetachWithDevid = HdfDeviceDetachWithDevid;
115 device->super.GetDeviceNode = HdfDeviceGetDeviceNode;
116
117 DListHeadInit(&device->devNodes);
118 }
119
HdfDeviceDestruct(struct HdfDevice * device)120 void HdfDeviceDestruct(struct HdfDevice *device)
121 {
122 struct HdfDeviceNode *devNode = NULL;
123 struct HdfDeviceNode *tmp = NULL;
124 DLIST_FOR_EACH_ENTRY_SAFE(devNode, tmp, &device->devNodes, struct HdfDeviceNode, entry) {
125 HdfDeviceNodeFreeInstance(devNode);
126 }
127 DListHeadInit(&device->devNodes);
128 }
129
HdfDeviceCreate(void)130 struct HdfObject *HdfDeviceCreate(void)
131 {
132 struct HdfDevice *device = (struct HdfDevice *)OsalMemCalloc(sizeof(struct HdfDevice));
133 if (device != NULL) {
134 HdfDeviceConstruct(device);
135 }
136 return (struct HdfObject *)device;
137 }
138
HdfDeviceRelease(struct HdfObject * object)139 void HdfDeviceRelease(struct HdfObject *object)
140 {
141 struct HdfDevice *device = (struct HdfDevice *)object;
142 if (device != NULL) {
143 HdfDeviceDestruct(device);
144 OsalMemFree(device);
145 }
146 }
147
HdfDeviceNewInstance(void)148 struct HdfDevice *HdfDeviceNewInstance(void)
149 {
150 return (struct HdfDevice *)HdfObjectManagerGetObject(HDF_OBJECT_ID_DEVICE);
151 }
152
HdfDeviceFreeInstance(struct HdfDevice * device)153 void HdfDeviceFreeInstance(struct HdfDevice *device)
154 {
155 if (device != NULL) {
156 HdfObjectManagerFreeObject(&device->super.object);
157 }
158 }
159