1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include <assert.h>
6 #include <ulog/ulog.h>
7 #include "device/aos_device.h"
8 #include <drivers/u_ld.h>
9 #include <devicevfs/devicevfs.h>
10 #include <stdlib.h>
11
12 #include "k_api.h"
13
14 #define TAG "aos_device_bridge"
15
16 #define device_init (dev->init)
17 #define device_open (dev->open)
18 #define device_close (dev->close)
19 #define device_read (dev->read)
20 #define device_write (dev->write)
21 #define device_control (dev->control)
22
23 extern struct file_ops m_dev_fops;
24 extern void aos_object_detach(aos_object_t object);
25
26 #ifndef AOS_DEVICE_BRIDGE_USE_VFS
27
bridge_device_probe(struct u_platform_device * pdev)28 static int bridge_device_probe (struct u_platform_device *pdev) {
29 LOGW(TAG, "%s", __func__);
30 return 0;
31 }
32
bridge_device_remove(struct u_platform_device * pdev)33 static int bridge_device_remove (struct u_platform_device *pdev) {
34 LOGW(TAG, "%s", __func__);
35 return 0;
36 }
37
bridge_device_shutdown(struct u_platform_device * pdev)38 static void bridge_device_shutdown (struct u_platform_device *pdev) {
39 LOGW(TAG, "%s", __func__);
40 return;
41 }
42
bridge_device_suspend(struct u_platform_device * pdev,int state)43 static int bridge_device_suspend (struct u_platform_device *pdev, int /*pm_message_t */state) {
44 LOGW(TAG, "%s", __func__);
45 return 0;
46 }
47
bridge_device_resume(struct u_platform_device * pdev)48 static int bridge_device_resume (struct u_platform_device *pdev) {
49 LOGW(TAG, "%s", __func__);
50 return 0;
51 }
52
bridge_device_init(struct u_platform_device * pdev)53 int bridge_device_init (struct u_platform_device *pdev) {
54 return 0;
55 }
56
bridge_device_deinit(struct u_platform_device * pdev)57 int bridge_device_deinit (struct u_platform_device *pdev) {
58 return 0;
59 }
60
bridge_device_pm(struct u_platform_device * pdev,u_pm_ops_t state)61 int bridge_device_pm (struct u_platform_device *pdev, u_pm_ops_t state) {
62 return 0;
63 }
64
65 static struct subsys_drv bridge_device_drv = {
66 .drv_name = "bridge_drv",
67 .init = bridge_device_init,
68 .deinit = bridge_device_deinit,
69 .pm = bridge_device_pm,
70 #if 0
71 .probe = bridge_device_probe,
72 .remove = bridge_device_remove,
73 .shutdown = bridge_device_shutdown,
74 .suspend = bridge_device_suspend,
75 .resume = bridge_device_resume,
76 #endif
77 };
78
aos_device_bridge_reg(const char * name,subsys_file_ops_t * fops,aos_device_t udata)79 static int aos_device_bridge_reg(const char *name, subsys_file_ops_t *fops, aos_device_t udata)
80 {
81 int ret = 0;
82 int node_name_len = 0;
83 struct subsys_dev *ppsdev = NULL;
84
85 LOGI(TAG, "vfs driver init starts");
86
87 node_name_len = strlen(name) + 2 + 1; // 2 for %d, 1 for '\0'
88 LOGI(TAG, "node_name_len:%d", node_name_len);
89
90 ppsdev = malloc(sizeof(struct subsys_dev) + node_name_len);
91 if (!ppsdev) {
92 LOGI(TAG, "malloc failed, ppsdev:%p", ppsdev);
93 goto err;
94 }
95
96 memset(ppsdev, 0x0, sizeof(struct subsys_dev)+node_name_len);
97
98 ppsdev->node_name = (char *)((ppsdev) + 1);
99 snprintf((ppsdev)->node_name, node_name_len, "%s", name);
100 LOGD(TAG, "ppsdev:%p, (ppsdev) + 1:%p, node_name:%s, sizeof(struct subsys_dev):%d",
101 ppsdev, (ppsdev) + 1, (ppsdev)->node_name, sizeof(struct subsys_dev));
102 ppsdev->permission = 0;
103 // please refer to definitions in enum SUBSYS_BUS_TYPE
104 ppsdev->type = BUS_TYPE_PLATFORM;
105 // user_data will be passed to open operation via node->i_arg
106 ppsdev->user_data = (void *)udata;
107 udata->user_data2 = ppsdev;
108
109 ret = aos_dev_reg(ppsdev, fops, &bridge_device_drv);
110 if (ret) {
111 LOGE(TAG, "aos_dev_reg for failed, ret:%d", ret);
112 goto err;
113 }
114
115 LOGI(TAG, "%s vfs driver init finish, ret:%d", __func__, ret);
116 return 0;
117
118 err:
119 if (ppsdev) {
120 // shall uninstall devices who are already registered
121 aos_dev_unreg(ppsdev);
122 LOGI(TAG, "free memory");
123 free(ppsdev);
124 ppsdev = NULL;
125 }
126
127 LOGE(TAG, "%s vfs driver init failed, ret:%d", __func__, ret);
128
129 return ret;
130 }
131 #endif
132
133 /**
134 * This function registers a device driver with specified name.
135 *
136 * @param dev the pointer of device driver structure
137 * @param name the device's name
138 * @param flags the capabilities flag of device
139 *
140 * @return the error code, 0 on initialization successfully.
141 */
aos_device_register(aos_device_t dev,const char * name,uint16_t flags)142 int aos_device_register(aos_device_t dev,
143 const char *name,
144 uint16_t flags)
145 {
146 if (dev == NULL)
147 return -1;
148
149 if (aos_device_find(name) != NULL)
150 return -1;
151
152 aos_object_init(&(dev->parent), AOS_Object_Class_Device, name);
153 dev->flag = flags;
154 dev->ref_count = 0;
155 dev->open_flag = 0;
156
157 #ifdef AOS_DEVICE_BRIDGE_USE_VFS
158 if (0 != aos_register_driver(name, &m_dev_fops, (void *)dev)) {
159 #else
160 LOGD(TAG, "%s dev %p name %s", __func__, dev, name);
161 if (0 != aos_device_bridge_reg(name, &m_dev_fops, dev)) {
162 #endif
163 return -1;
164 }
165
166 return 0;
167 }
168
169 /**
170 * This function removes a previously registered device driver
171 *
172 * @param dev the pointer of device driver structure
173 *
174 * @return the error code, 0 on successfully.
175 */
176 int aos_device_unregister(aos_device_t dev)
177 {
178 struct subsys_dev *ppsdev;
179
180 DEV_ASSERT(dev != NULL);
181 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
182 DEV_ASSERT(aos_object_is_systemobject(&dev->parent));
183
184 ppsdev = dev->user_data2;
185 if (ppsdev) {
186 aos_dev_unreg(ppsdev);
187 free(ppsdev);
188 ppsdev = NULL;
189 }
190
191 aos_object_detach(&(dev->parent));
192
193 return 0;
194 }
195
196 /**
197 * This function finds a device driver by specified name.
198 *
199 * @param name the device driver's name
200 *
201 * @return the registered device driver on successful, or NULL on failure.
202 */
203 aos_device_t aos_device_find(const char *name)
204 {
205 struct aos_object *object;
206 dlist_t *node;
207 struct aos_object_information *information;
208
209 CPSR_ALLOC();
210
211 RHINO_CRITICAL_ENTER();
212
213 /* try to find device object */
214 information = aos_object_get_information(AOS_Object_Class_Device);
215 DEV_ASSERT(information != NULL);
216 for (node = information->object_list.next;
217 node != &(information->object_list);
218 node = node->next)
219 {
220 object = dlist_entry(node, struct aos_object, list);
221 if (strncmp(object->name, name, AOS_OBJ_NAME_MAX) == 0)
222 {
223 /* leave critical */
224 RHINO_CRITICAL_EXIT();
225
226 return (aos_device_t)object;
227 }
228 }
229
230 /* leave critical */
231 RHINO_CRITICAL_EXIT();
232
233 /* not found */
234 return NULL;
235 }
236
237 /**
238 * This function creates a device object with user data size.
239 *
240 * @param type, the kind type of this device object.
241 * @param attach_size, the size of user data.
242 *
243 * @return the allocated device object, or NULL when failed.
244 */
245 aos_device_t aos_device_create(int type, int attach_size)
246 {
247 int size;
248 aos_device_t device;
249
250 size = AOS_ALIGN(sizeof(struct aos_device), AOS_ALIGN_SIZE);
251 attach_size = AOS_ALIGN(attach_size, AOS_ALIGN_SIZE);
252 /* use the total size */
253 size += attach_size;
254
255 device = (aos_device_t)aos_malloc(size);
256 if (device)
257 {
258 memset(device, 0x0, sizeof(struct aos_device));
259 device->type = (enum aos_device_class_type)type;
260 }
261
262 return device;
263 }
264
265 /**
266 * This function destroy the specific device object.
267 *
268 * @param dev, the specific device object.
269 */
270 void aos_device_destroy(aos_device_t dev)
271 {
272 DEV_ASSERT(dev != NULL);
273 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
274 DEV_ASSERT(aos_object_is_systemobject(&dev->parent) == false);
275
276 aos_object_detach(&(dev->parent));
277
278 /* release this device object */
279 aos_free(dev);
280 }
281
282 /**
283 * This function will initialize the specified device
284 *
285 * @param dev the pointer of device driver structure
286 *
287 * @return the result
288 */
289 int aos_device_init(aos_device_t dev)
290 {
291 int result = 0;
292
293 DEV_ASSERT(dev != NULL);
294
295 /* get device_init handler */
296 if (device_init != NULL)
297 {
298 if (!(dev->flag & AOS_DEVICE_FLAG_ACTIVATED))
299 {
300 result = device_init(dev);
301 if (result != 0)
302 {
303 LOGD(TAG,"To initialize device:%s failed. The error code is %d",
304 dev->parent.name, result);
305 }
306 else
307 {
308 dev->flag |= AOS_DEVICE_FLAG_ACTIVATED;
309 }
310 }
311 }
312
313 return result;
314 }
315
316 /**
317 * This function will open a device
318 *
319 * @param dev the pointer of device driver structure
320 * @param oflag the flags for device open
321 *
322 * @return the result
323 */
324 int aos_device_open(aos_device_t dev, uint16_t oflag)
325 {
326 int result = 0;
327
328 DEV_ASSERT(dev != NULL);
329 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
330
331 /* if device is not initialized, initialize it. */
332 if (!(dev->flag & AOS_DEVICE_FLAG_ACTIVATED))
333 {
334 if (device_init != NULL)
335 {
336 result = device_init(dev);
337 if (result != 0)
338 {
339 //printf("To initialize device:%s failed. The error code is %d\n",dev->parent.name, result);
340 return result;
341 }
342 }
343
344 dev->flag |= AOS_DEVICE_FLAG_ACTIVATED;
345 }
346
347 /* device is a stand alone device and opened */
348 if ((dev->flag & AOS_DEVICE_FLAG_STANDALONE) &&
349 (dev->open_flag & AOS_DEVICE_OFLAG_OPEN))
350 {
351 return -1; // EBUSY
352 }
353
354 /* call device_open interface */
355 if (device_open != NULL)
356 {
357 result = device_open(dev, oflag);
358 } else {
359 /* set open flag */
360 dev->open_flag = (oflag & AOS_DEVICE_OFLAG_MASK);
361 }
362
363 /* set open flag */
364 if (result == 0) {
365 dev->open_flag |= AOS_DEVICE_OFLAG_OPEN;
366
367 dev->ref_count++;
368 /* don't let bad things happen silently. If you are bitten by this assert,
369 * please set the ref_count to a bigger type. */
370 DEV_ASSERT(dev->ref_count != 0);
371 }
372
373 return result;
374 }
375
376 /**
377 * This function will close a device
378 *
379 * @param dev the pointer of device driver structure
380 *
381 * @return the result
382 */
383 int aos_device_close(aos_device_t dev)
384 {
385 int result = 0;
386
387 DEV_ASSERT(dev != NULL);
388 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
389
390 if (dev->ref_count == 0)
391 return -1;
392
393 dev->ref_count--;
394
395 if (dev->ref_count != 0)
396 return 0;
397
398 /* call device_close interface */
399 if (device_close != NULL) {
400 result = device_close(dev);
401 }
402
403 /* set open flag */
404 if (result == 0)
405 dev->open_flag = AOS_DEVICE_OFLAG_CLOSE;
406
407 return result;
408 }
409
410 /**
411 * This function will read some data from a device.
412 *
413 * @param dev the pointer of device driver structure
414 * @param pos the position of reading
415 * @param buffer the data buffer to save read data
416 * @param size the size of buffer
417 *
418 * @return the actually read size on successful, otherwise negative returned.
419 *
420 * @note since 0.4.0, the unit of size/pos is a block for block device.
421 */
422 size_t aos_device_read(aos_device_t dev,
423 long pos,
424 void *buffer,
425 size_t size)
426 {
427 DEV_ASSERT(dev != NULL);
428 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
429
430 if (dev->ref_count == 0) {
431 return 0;
432 }
433
434 /* call device_read interface */
435 if (device_read != NULL)
436 {
437 return device_read(dev, pos, buffer, size);
438 }
439
440 return 0;
441 }
442
443 /**
444 * This function will write some data to a device.
445 *
446 * @param dev the pointer of device driver structure
447 * @param pos the position of written
448 * @param buffer the data buffer to be written to device
449 * @param size the size of buffer
450 *
451 * @return the actually written size on successful, otherwise negative returned.
452 *
453 * @note since 0.4.0, the unit of size/pos is a block for block device.
454 */
455 size_t aos_device_write(aos_device_t dev,
456 long pos,
457 const void *buffer,
458 size_t size)
459 {
460 DEV_ASSERT(dev != NULL);
461 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
462
463 if (dev->ref_count == 0) {
464 /* set error code -ENOSYS */
465 return 0;
466 }
467
468 /* call device_write interface */
469 if (device_write != NULL) {
470 return device_write(dev, pos, buffer, size);
471 }
472
473 /* set error code -ENOSYS */
474
475 return 0;
476 }
477
478 /**
479 * This function will perform a variety of control functions on devices.
480 *
481 * @param dev the pointer of device driver structure
482 * @param cmd the command sent to device
483 * @param arg the argument of command
484 *
485 * @return the result
486 */
487 int aos_device_control(aos_device_t dev, int cmd, void *arg)
488 {
489 LOGD(TAG, "%s entry, cmd %d, dev %p", __func__, cmd, dev);
490 DEV_ASSERT(dev != NULL);
491 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
492
493 /* call device_write interface */
494 if (device_control != NULL)
495 {
496 return device_control(dev, cmd, arg);
497 } else {
498 LOGD(TAG, "%s dev %p device_control is NULL\r\n", __func__, dev);
499 }
500
501 return -1;
502 }
503
504 /**
505 * This function will set the reception indication callback function. This callback function
506 * is invoked when this device receives data.
507 *
508 * @param dev the pointer of device driver structure
509 * @param rx_ind the indication callback function
510 *
511 * @return 0
512 */
513 int aos_device_set_rx_indicate(aos_device_t dev,
514 int (*rx_ind)(aos_device_t dev, size_t size))
515 {
516 DEV_ASSERT(dev != NULL);
517 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
518
519 dev->rx_indicate = rx_ind;
520
521 return 0;
522 }
523
524
525 /**
526 * This function will set the indication callback function when device has
527 * written data to physical hardware.
528 *
529 * @param dev the pointer of device driver structure
530 * @param tx_done the indication callback function
531 *
532 * @return 0
533 */
534 int aos_device_set_tx_complete(aos_device_t dev,
535 int (*tx_done)(aos_device_t dev, void *buffer))
536 {
537 DEV_ASSERT(dev != NULL);
538 DEV_ASSERT(aos_object_get_type(&dev->parent) == AOS_Object_Class_Device);
539
540 dev->tx_complete = tx_done;
541
542 return 0;
543 }
544