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