• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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