Explorar o código

device: add ref_count support

This is a simple work around to the current device stack design. A
ref_count could let different modules to open/close the same device
independently without interfere others in some degree.

But there is still some data shared between the modules, like flag,
open_flag and user_data. Moreover, it won't yield an error if A open a
device, and B read from it before open it in B. Maybe alloc a new handle
in rt_device_open will be the ultimate solution. But that is much bigger
change and we may leave it to future development.
Grissiom %!s(int64=12) %!d(string=hai) anos
pai
achega
7bcce9e87f
Modificáronse 2 ficheiros con 29 adicións e 1 borrados
  1. 1 0
      include/rtdef.h
  2. 28 1
      src/device.c

+ 1 - 0
include/rtdef.h

@@ -779,6 +779,7 @@ struct rt_device
     rt_uint16_t               flag;                     /**< device flag */
     rt_uint16_t               open_flag;                /**< device open flag */
 
+    rt_uint8_t                ref_count;                /**< reference count */
     rt_uint8_t                device_id;                /**< 0 - 255 */
 
     /* device call back */

+ 28 - 1
src/device.c

@@ -1,7 +1,7 @@
 /*
  * File      : device.c
  * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
+ * COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
  * 2012-10-20     Bernard      add device check in register function,
  *                             provided by Rob <rdent@iinet.net.au>
  * 2012-12-25     Bernard      return RT_EOK if the device interface not exist.
+ * 2013-07-09     Grissiom     add ref_count support
  */
 
 #include <rtthread.h>
@@ -51,6 +52,7 @@ rt_err_t rt_device_register(rt_device_t dev,
 
     rt_object_init(&(dev->parent), RT_Object_Class_Device, name);
     dev->flag = flags;
+    dev->ref_count = 0;
 
     return RT_EOK;
 }
@@ -237,6 +239,11 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
         return -RT_EBUSY;
     }
 
+    dev->ref_count++;
+    /* don't let bad things happen silently. If you are bitten by this assert,
+     * please set the ref_count to a bigger type. */
+    RT_ASSERT(dev->ref_count != 0);
+
     /* call device open interface */
     if (dev->open != RT_NULL)
     {
@@ -264,6 +271,14 @@ rt_err_t rt_device_close(rt_device_t dev)
 
     RT_ASSERT(dev != RT_NULL);
 
+    if (dev->ref_count == 0)
+        return -RT_ERROR;
+
+    dev->ref_count--;
+
+    if (dev->ref_count != 0)
+        return RT_EOK;
+
     /* call device close interface */
     if (dev->close != RT_NULL)
     {
@@ -297,6 +312,12 @@ rt_size_t rt_device_read(rt_device_t dev,
 {
     RT_ASSERT(dev != RT_NULL);
 
+    if (dev->ref_count == 0)
+    {
+        rt_set_errno(-RT_ERROR);
+        return 0;
+    }
+
     /* call device read interface */
     if (dev->read != RT_NULL)
     {
@@ -329,6 +350,12 @@ rt_size_t rt_device_write(rt_device_t dev,
 {
     RT_ASSERT(dev != RT_NULL);
 
+    if (dev->ref_count == 0)
+    {
+        rt_set_errno(-RT_ERROR);
+        return 0;
+    }
+
     /* call device write interface */
     if (dev->write != RT_NULL)
     {