MCU模拟Linux注册驱动


MCU模拟Linux注册驱动

jianqiang.xue

ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl() 命令的方式实现。

ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的调用个数如下:
int ioctl(int fd, ind cmd, …);
其中fd是用户程序打开设备时使用open函数返回的文件标示符,cmd是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,这个参数的有无和cmd的意义相关。
ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就可以在用户程序中使用ioctl函数来控制设备的I/O通道。

ioctl的必要性
如果不用ioctl的话,也可以实现对设备I/O通道的控制,但那是蛮拧了。
例如,我们可以在驱动程序中实现write的时候检查一下是否有特殊约定的数 据流通过,如果有的话,那么后面就跟着控制命令(一般在socket编程中常常这样做)。但是如果这样做的话,会导致代码分工不明,程序结构混乱,程序员 自己也会头昏眼花的。所以,我们就使用ioctl来实现控制的功能。要记住,用户程序所作的只是通过命令码(cmd)告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。

![bb0c568a0d58408ead3e7f72b2e014b3.jpg][1]
在计算机中,ioctl(input/output control)是一个专用于设备输入输出操作的系统调用,该调用传入一个跟设备有关的请求码,系统调用的功能完全取决于请求码。举个例子,CD-ROM驱动程序可以弹出光驱,它就提供了一个对应的Ioctl请求码。设备无关的请求码则提供了内核调用权限。ioctl这名字第一次出现在Unix第七版中,他在很多类unix系统(比如Linux、Mac OSX等)都有提供,不过不同系统的请求码对应的设备有所不同。Microsoft Windows在Win32 API里提供了相似的函数,叫做DeviceIoControl。

功能和接口基本相同,名字发生了变化.
ioctl既可以往内核读也可以写,read/write在执行大数据量读/写时比较有优势。
在应用层调用ioctl函数时,内核会调用对应驱动中的ublocked_ioctl函数,向内核读写数据。

operations set for device object
*/
struct device_ops_s
{
int32_t (*open)(device_t *dev);
int32_t (*close)(device_t *dev);
xssize_t (*read)(device_t *dev, char *buffer, xsize_t size, xloff_t *pos);
xssize_t (*write)(device_t *dev, const char *buffer, xsize_t size, xloff_t *pos);
int32_t (*ioctl)(device_t *dev, uint32_t cmd, void *args);
};
#include "errorno.h"

#include "device.h"

#define DEVICE_ENTER_CRITICAL()
#define DEVICE_EXIT_CRITICAL()

#define device_ops_open             (dev->dev_ops->open)
#define device_ops_close            (dev->dev_ops->close)
#define device_ops_read             (dev->dev_ops->read)
#define device_ops_write            (dev->dev_ops->write)
#define device_ops_ioctl            (dev->dev_ops->ioctl)

/**

 * This function finds a device driver by specified name.
   *
 * @param name the device driver's name
   *
 * @return the registered device driver on successful, or NULL on failure.
   */
   device_t* device_find(const char *name)
   {
   device_t *obj;
   obj = (device_t*)object_find(OBJECT_CLASS_DEVICE, name);
   return obj;
   }

/**

 * This function registers a device driver with specified name.
   *

 * @param dev the pointer of device driver structure

 * @param name the device driver's name

 * @param flags the capabilities flag of device
   *

 * @return the error code, EOK on initialization successfully.
   */
   int32_t device_register(device_t *dev, const char *name, xflag_t flags)
   {
   int32_t ret;

   if (dev == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (device_find(name) != NULL)
   {
       return RETVAL(E_FAIL);
   }

   dev->flag = flags;
   dev->oflag = DEVICE_OFLAG_CLOSE;
   dev->ref_cnt = 0;

   ret = object_attack(&(dev->obj), OBJECT_CLASS_DEVICE, name);

   return ret;
   }

/**

 * This function removes a previously registered device driver
   *

 * @param dev the pointer of device driver structure
   *

 * @return the error code, EOK on successfully.
   */
   int32_t device_unregister(device_t *dev)
   {
   int32_t ret;

   if (dev == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_get_type(&(dev->obj)) != OBJECT_CLASS_DEVICE)
   {
       return RETVAL(E_NO_DEV);
   }

   ret = object_detach(&(dev->obj));

   return ret;
   }

/**

 * This function will open a device
   *

 * @param dev the pointer of device driver structure

 * @param oflag the flags for device open
   *

 * @return the result
   */
   int32_t device_open(device_t *dev, xflag_t oflag)
   {
   int32_t ret = RETVAL(E_OK);

   if (dev == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_get_type(&(dev->obj)) != OBJECT_CLASS_DEVICE)
   {
       return RETVAL(E_NO_DEV);
   }

   /* device is a stand alone device and opened */
   if ((dev->flag & DEVICE_FLAG_STANDALONE) &&
       (dev->oflag & DEVICE_OFLAG_OPEN))
   {
       return RETVAL(E_BUSY);
   }

   /* call device_open interface */
   if (device_ops_open != NULL)
   {
       ret = device_ops_open(dev);
   }
   else
   {
       /* set open flag */
       dev->oflag = (oflag & DEVICE_OFLAG_MASK);
   }

   /* set open flag */
   if (ret == RETVAL(E_OK))
   {
       dev->oflag |= DEVICE_OFLAG_OPEN;
       dev->ref_cnt ++;
   }

   return ret;
   }

/**

 * This function will close a device
   *

 * @param dev the pointer of device driver structure
   *

 * @return the result
   */
   int32_t device_close(device_t *dev)
   {
   int32_t ret = RETVAL(E_OK);

   if (dev == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_get_type(&(dev->obj)) != OBJECT_CLASS_DEVICE)
   {
       return RETVAL(E_NO_DEV);
   }

   if (dev->ref_cnt == 0)
   {
       return RETVAL(E_STATE);
   }

   dev->ref_cnt --;
   if (dev->ref_cnt != 0)
   {
       return RETVAL(E_OK);
   }

   /* call device_close interface */
   if (device_ops_close != NULL)
   {
       ret = device_ops_close(dev);
   }

   /* set open flag */
   if (ret == RETVAL(E_OK))
   {
       dev->oflag = DEVICE_OFLAG_CLOSE;
   }

   return ret;
   }

/**

 * This function will read some data from a device.
   *

 * @param dev the pointer of device driver structure

 * @param pos the position of reading

 * @param buffer the data buffer to save read data

 * @param size the size of buffer
   *

 * @return the actually read size on successful, otherwise negative returned.
   *

 * @note since 0.4.0, the unit of size/pos is a block for block device.
   */
   xssize_t device_read(device_t *dev, char *buffer, xsize_t size, xloff_t *pos)
   {
   if (dev == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_get_type(&(dev->obj)) != OBJECT_CLASS_DEVICE)
   {
       return RETVAL(E_NO_DEV);
   }

   if (dev->ref_cnt == 0)
   {
       return RETVAL(E_STATE);
   }

   /* call device_read interface */
   if (device_ops_read != NULL)
   {
       return device_ops_read(dev, buffer, size, pos);
   }

   return RETVAL(E_NOT_SUPPORT);
   }

/**

 * This function will write some data to a device.
   *

 * @param dev the pointer of device driver structure

 * @param pos the position of written

 * @param buffer the data buffer to be written to device

 * @param size the size of buffer
   *

 * @return the actually written size on successful, otherwise negative returned.
   *

 * @note since 0.4.0, the unit of size/pos is a block for block device.
   */
   xssize_t device_write(device_t *dev, const char *buffer, xsize_t size, xloff_t *pos)
   {
   if (dev == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_get_type(&(dev->obj)) != OBJECT_CLASS_DEVICE)
   {
       return RETVAL(E_NO_DEV);
   }

   if (dev->ref_cnt == 0)
   {
       return RETVAL(E_STATE);
   }

   /* call device_write interface */
   if (device_ops_write != NULL)
   {
       return device_ops_write(dev, buffer, size, pos);
   }

   return RETVAL(E_NOT_SUPPORT);
   }

/**

 * This function will perform a variety of control functions on devices.
   *

 * @param dev the pointer of device driver structure

 * @param cmd the command sent to device

 * @param arg the argument of command
   *

 * @return the result
   */
   int32_t device_ioctl(device_t *dev, int cmd, void *arg)
   {
   if (dev == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_get_type(&(dev->obj)) != OBJECT_CLASS_DEVICE)
   {
       return RETVAL(E_NO_DEV);
   }

   if (dev->ref_cnt == 0)
   {
       return RETVAL(E_STATE);
   }

   /* call device_write interface */
   if (device_ops_ioctl != NULL)
   {
       return device_ops_ioctl(dev, cmd, arg);
   }

   return RETVAL(E_NOT_SUPPORT);
   }
#ifndef _DEVICE_H_
#define _DEVICE_H_

#include "typedefs.h"
#include "object.h"
#include "driver.h"

/**

 * device flags defitions
   */
   #define DEVICE_FLAG_DEACTIVATE          0x0000  /**< device is not not initialized */

#define DEVICE_FLAG_RDONLY              0x0001  /**< read only */
#define DEVICE_FLAG_WRONLY              0x0002  /**< write only */
#define DEVICE_FLAG_RDWR                0x0003  /**< read and write */

#define DEVICE_FLAG_REMOVABLE           0x0004  /**< removable device */
#define DEVICE_FLAG_STANDALONE          0x0008  /**< standalone device */
#define DEVICE_FLAG_ACTIVATED           0x0010  /**< device is activated */
#define DEVICE_FLAG_SUSPENDED           0x0020  /**< device is suspended */
#define DEVICE_FLAG_STREAM              0x0040  /**< stream mode */

#define DEVICE_FLAG_INT_RX              0x0100  /**< INT mode on Rx */
#define DEVICE_FLAG_DMA_RX              0x0200  /**< DMA mode on Rx */
#define DEVICE_FLAG_INT_TX              0x0400  /**< INT mode on Tx */
#define DEVICE_FLAG_DMA_TX              0x0800  /**< DMA mode on Tx */

#define DEVICE_OFLAG_CLOSE              0x0000  /**< device is closed */
#define DEVICE_OFLAG_RDONLY             0x0001  /**< read only access */
#define DEVICE_OFLAG_WRONLY             0x0002  /**< write only access */
#define DEVICE_OFLAG_RDWR               0x0003  /**< read and write */
#define DEVICE_OFLAG_OPEN               0x0008  /**< device is opened */
#define DEVICE_OFLAG_MASK               0x0F0F  /**< mask of open flag */

/**

 * general device commands
   */
   #define DEVICE_CTRL_RESUME              0x0100  /**< resume device */
   #define DEVICE_CTRL_SUSPEND             0x0200  /**< suspend device */
   #define DEVICE_CTRL_CONFIG              0x0300  /**< configure device */
   #define DEVICE_CTRL_STATE               0x0400  /**< get device state */

#define DEVICE_CTRL_SET_INT             0x1000  /**< set interrupt */
#define DEVICE_CTRL_CLR_INT             0x1100  /**< clear interrupt */
#define DEVICE_CTRL_GET_INT             0x1200  /**< get interrupt status */

/**

 * special device commands
   */
   #define DEVICE_CTRL_CHAR_STREAM         0x3000  /**< stream mode on char device */

#define DEVICE_CTRL_BLK_GETGEOME        0x4000  /**< get geometry information   */
#define DEVICE_CTRL_BLK_SYNC            0x4100  /**< flush data to block device */
#define DEVICE_CTRL_BLK_ERASE           0x4200  /**< erase block on block device */
#define DEVICE_CTRL_BLK_AUTOREFRESH     0x4300  /**< block device : enter/exit auto refresh mode */

#define DEVICE_CTRL_NETIF_GETMAC        0x5000  /**< get mac address */

#define DEVICE_CTRL_MTD_FORMAT          0x6000  /**< format a MTD device */

#define DEVICE_CTRL_RTC_GET_TIME        0x7000  /**< get time */
#define DEVICE_CTRL_RTC_SET_TIME        0x7100  /**< set time */
#define DEVICE_CTRL_RTC_GET_ALARM       0x7200  /**< get alarm */
#define DEVICE_CTRL_RTC_SET_ALARM       0x7300  /**< set alarm */

/**

 * device (I/O) class type
   */
   typedef enum
   {
   DEVICE_CLASS_CHAR,                          /**< character device */
   DEVICE_CLASS_BLOCK,                         /**< block device */
   DEVICE_CLASS_NETIF,                         /**< net interface */
   DEVICE_CLASS_MTD,                           /**< memory device */
   DEVICE_CLASS_CAN,                           /**< CAN device */
   DEVICE_CLASS_RTC,                           /**< RTC device */
   DEVICE_CLASS_SOUND,                         /**< Sound device */
   DEVICE_CLASS_GRAPHIC,                       /**< Graphic device */
   DEVICE_CLASS_I2C_BUS,                       /**< I2C bus device */
   DEVICE_CLASS_USB_DEVICE,                    /**< USB slave device */
   DEVICE_CLASS_USB_HOST,                      /**< USB host bus */
   DEVICE_CLASS_SPI_BUS,                       /**< SPI bus device */
   DEVICE_CLASS_SPI_DEVICE,                    /**< SPI device */
   DEVICE_CLASS_SDIO,                          /**< SDIO bus device */
   DEVICE_CLASS_PM,                            /**< PM pseudo device */
   DEVICE_CLASS_PIPE,                          /**< Pipe device */
   DEVICE_CLASS_PORTAL,                        /**< Portal device */
   DEVICE_CLASS_TIMER,                         /**< Timer device */
   DEVICE_CLASS_MISCELLANEOUS,                 /**< Miscellaneous device */
   DEVICE_CLASS_SENSOR,                        /**< Sensor device */
   DEVICE_CLASS_TOUCH,                         /**< Touch device */
   DEVICE_CLASS_UNKNOWN                        /**< unknown device */
   } device_class_t;

typedef struct device_s device_t;
typedef struct device_ops_s device_ops_t;

/**

 * operations set for device object
   */
   struct device_ops_s
   {
   int32_t (*open)(device_t *dev);
   int32_t (*close)(device_t *dev);
   xssize_t (*read)(device_t *dev, char *buffer, xsize_t size, xloff_t *pos);
   xssize_t (*write)(device_t *dev, const char *buffer, xsize_t size, xloff_t *pos);
   int32_t (*ioctl)(device_t *dev, uint32_t cmd, void *args);
   };

/**

 * Device structure
   */
   struct device_s
   {
   object_t            obj;                    /**< inherit from rt_object */

   device_class_t      type;                   /**< device type */
   xflag_t             flag;                   /**< device flag */
   xflag_t             oflag;                  /**< device open flag */

   uint8_t             ref_cnt;                /**< reference count */
   uint8_t             dev_id;                 /**< 0 - 255 */

   const device_ops_t  *dev_ops;               /**< common device interface */
   driver_t            *dev_drv;               /**< device driver */
   void                *dev_data;              /**< device private data */
   };

int32_t device_register(device_t *dev, const char *name, xflag_t flags);
int32_t device_unregister(device_t *dev);

device_t* device_find(const char *name);
int32_t device_open(device_t *dev, xflag_t oflag);
int32_t device_close(device_t *dev);
xssize_t device_read(device_t *dev, char *buffer, xsize_t size, xloff_t *pos);
xssize_t device_write(device_t *dev, const char *buffer, xsize_t size, xloff_t *pos);
int32_t device_ioctl(device_t *dev, int cmd, void *arg);

#endif // _DEVICE_H_
#include "errorno.h"

#include "driver.h"

#define DRIVER_ENTER_CRITICAL()
#define DRIVER_EXIT_CRITICAL()

/**

 * This function finds a driver by specified name.
   *
 * @param name the driver's name
   *
 * @return the registered driver on successful, or NULL on failure.
   */
   driver_t* driver_find(const char *name)
   {
   driver_t *obj;
   obj = (driver_t*)object_find(OBJECT_CLASS_DRIVER, name);
   return obj;
   }

/**

 * This function registers a driver with specified name.
   *

 * @param drv the pointer of driver structure

 * @param name the driver's name
   *

 * @return the error code, EOK on initialization successfully.
   */
   int32_t driver_register(driver_t *drv, const char *name)
   {
   int32_t ret;

   if (drv == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (driver_find(name) != NULL)
   {
       return RETVAL(E_FAIL);
   }

   ret = object_attack(&(drv->obj), OBJECT_CLASS_DRIVER, name);

   return ret;
   }

/**

 * This function removes a previously registered driver
   *

 * @param drv the pointer of driver structure
   *

 * @return the error code, EOK on successfully.
   */
   int32_t driver_unregister(driver_t *drv)
   {
   int32_t ret;

   if (drv == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_get_type(&(drv->obj)) != OBJECT_CLASS_DRIVER)
   {
       return RETVAL(E_NO_DEV);
   }

   ret = object_detach(&(drv->obj));

   return ret;
   }

/**

 * This function will probe the specified driver
   *

 * @param drv the pointer of driver structure
   *

 * @return the result
   */
   int32_t driver_probe(driver_t *drv)
   {
   int32_t ret = RETVAL(E_OK);

   if (drv == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (drv->probe == NULL)
   {
       return RETVAL(E_NOT_SUPPORT);
   }

   ret = drv->probe();

   return ret;
   }

/**

 * This function will remove the specified driver
   *

 * @param drv the pointer of driver structure
   *

 * @return the result
   */
   int32_t driver_remove(driver_t *drv)
   {
   int32_t ret = RETVAL(E_OK);

   if (drv == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (drv->remove == NULL)
   {
       return RETVAL(E_NOT_SUPPORT);
   }

   ret = drv->remove();

   return ret;
   }

/**

 * This function will set the reception indication callback function. This callback function
 * is invoked when this driver receives data.
   *
 * @param drv the pointer of driver structure
 * @param rx_ind the indication callback function
   *
 * @return EOK
   */
   void driver_set_rx_ind_cbk(driver_t *drv, drv_rx_ind_cbk_t rx_ind)
   {
   if (drv != NULL)
   {
       drv->rx_ind_cbk = rx_ind;
   }
   }

/**

 * This function will set the indication callback function when device has
 * written data to physical hardware.
   *
 * @param drv the pointer of driver structure
 * @param tx_done the indication callback function
   *
 * @return EOK
   */
   void driver_set_tx_done_cbk(driver_t *drv, drv_tx_done_cbk_t tx_done)
   {
   if (drv != NULL)
   {
       drv->tx_done_cbk = tx_done;
   }
   }

/**

 * This function will sent rx indicate
   *
 * @param drv the pointer of driver structure
   *
 * @return the result
   */
   void driver_rx_ind_to_upper(driver_t *drv, void *buffer, uint16_t size)
   {
   if (drv != NULL && drv->rx_ind_cbk != NULL)
   {
       drv->rx_ind_cbk(buffer, size);
   }
   }

/**

 * This function will sent the tx done message
   *
 * @param drv the pointer of driver structure
   *
 * @return the result
   */
   void driver_tx_done_to_upper(driver_t *drv, void *buffer, uint16_t size)
   {
   if (drv != NULL && drv->tx_done_cbk != NULL)
   {
       drv->tx_done_cbk(buffer, size);
   }
   }

/**

 * This function will set the private data
   *
 * @param drv the pointer of driver structure
   *
 * @return the result
   */
   void driver_set_drvdata(driver_t *drv, void* drv_data)
   {
   if (drv != NULL)
   {
       drv->drv_data = drv_data;
   }
   }

/**

 * This function will get the private data
   *

 * @param drv the pointer of driver structure
   *

 * @return the result
   */
   void* driver_get_drvdata(driver_t *drv)
   {
   if (drv == NULL)
   {
       return NULL;
   }

   return drv->drv_data;
   }
#ifndef _DRIVER_H_
#define _DRIVER_H_

#include "typedefs.h"
#include "object.h"

/**

 * driver class type
   */
   typedef enum
   {
   DRIVER_CLASS_NET,                                   /** net driver */
   DRIVER_CLASS_MTD,                                   /** memory driver */
   DRIVER_CLASS_CAN,                                   /** CAN driver */
   DRIVER_CLASS_RTC,                                   /** RTC driver */
   DRIVER_CLASS_SOUND,                                 /** Sound driver */
   DRIVER_CLASS_LED,                                   /** LED driver */
   DRIVER_CLASS_GRAPHIC,                               /** Graphic driver */
   DRIVER_CLASS_I2C,                                   /** I2C bus driver */
   DRIVER_CLASS_USB_DEVICE,                            /** USB slave driver */
   DRIVER_CLASS_USB_HOST,                              /** USB host bus */
   DRIVER_CLASS_SPI_BUS,                               /** SPI bus driver */
   DRIVER_CLASS_SPI_DEVICE,                            /** SPI driver */
   DRIVER_CLASS_SDIO,                                  /** SDIO bus driver */
   DRIVER_CLASS_SENSOR,                                /** Sensor driver */
   DRIVER_CLASS_TOUCH,                                 /** Touch driver */
   DRIVER_CLASS_FULE_GAUGE,                            /** Fuel gauge driver */
   DRIVER_CLASS_CHARGER,                               /** Charger driver */
   DRIVER_CLASS_BUCK_BOOST,
   DRIVER_CLASS_UNKNOWN                                /** unknown driver */
   } driver_class_t;

typedef struct driver_s driver_t;

/**

 * Operations set for driver object
   */
   typedef struct
   {
   int32_t (*shutdown)(driver_t *drv);
   int32_t (*suspend)(driver_t *drv);
   int32_t (*resume)(driver_t *dev);
   } driver_pm_ops_t;

typedef void (*drv_rx_ind_cbk_t)(void *buffer, uint16_t size);
typedef void (*drv_tx_done_cbk_t)(void *buffer, uint16_t size);

/**

 * Driver structure
   */
   struct driver_s
   {
   object_t                obj;                        /** inherit from object */
   driver_class_t          type;                       /** driver type */
   int32_t                 (*probe)(void);             /** driver probe */
   int32_t                 (*remove)(void);            /** driver remove */
   drv_rx_ind_cbk_t        rx_ind_cbk;                 /** RX callback */
   drv_tx_done_cbk_t       tx_done_cbk;                /** TX callback */
   const driver_pm_ops_t   *pm_ops;                    /** common interface */
   void                    *drv_data;                  /** driver private data */
   };

int32_t driver_register(driver_t *drv, const char *name);
int32_t driver_unregister(driver_t *drv);

driver_t* driver_find(const char *name);
int32_t driver_probe(driver_t *drv);
int32_t driver_remove(driver_t *drv);

void driver_set_rx_ind_cbk(driver_t *drv, drv_rx_ind_cbk_t rx_ind);
void driver_set_tx_done_cbk(driver_t *drv, drv_tx_done_cbk_t tx_done);

void driver_rx_ind_to_upper(driver_t *drv, void *buffer, uint16_t size);
void driver_tx_done_to_upper(driver_t *drv, void *buffer, uint16_t size);

void driver_set_drvdata(driver_t *drv, void* drv_data);
void* driver_get_drvdata(driver_t *drv);

#endif // _DRIVER_H_
#include <string.h>

#include "errorno.h"
#include "sys_cmsis.h"

#include "object.h"

#define OBJECT_MALLOC(sz)               mem_malloc(sz)
#define OBJECT_FREE(ptr)                mem_free(ptr)

#define OBJECT_ENTER_CRITICAL()         sys_enter_critical()
#define OBJECT_EXIT_CRITICAL(VAL)       sys_exit_critical(VAL)

#define _OBJ_SET_LIST_INIT(t)     \
    { &(g_object_sets[t].obj_list), &(g_object_sets[t].obj_list) }


static object_set_t g_object_sets[OBJECT_CLASS_UNKNOWN - 1] =
{
    /* initialize object container - device */
    { OBJECT_CLASS_DEVICE, _OBJ_SET_LIST_INIT(OBJECT_CLASS_DEVICE - 1) },
    /* initialize object container - driver */
    { OBJECT_CLASS_DRIVER, _OBJ_SET_LIST_INIT(OBJECT_CLASS_DRIVER - 1) },
};

/**

 * This function will return the specified type of object information.
   *

 * @param type the type of object

 * @return the object type information or NULL
   */
   object_set_t* object_get_obj_set(object_class_t type)
   {
   int index;

   for (index = 0; index < (OBJECT_CLASS_UNKNOWN - 1); index ++)
   {
       if (g_object_sets[index].obj_type == type)
       {
           return &g_object_sets[index];
       }
   }

   return NULL;
   }

/**

 * This function will initialize an object and add it to object system

 * management.
   *

 * @param object the specified object to be initialized.

 * @param type the object type.

 * @param name the object name. In system, the object's name must be unique.
   */
   int32_t object_attack(object_t *object, object_class_t type, const char *name)
   {
   // register uint32_t temp;
   object_set_t *obj_set = NULL;
   object_t *obj = NULL;
   xlist_node_t *node = NULL;

   /* get object information */
   obj_set = object_get_obj_set(type);
   if (obj_set == NULL)
   {
       return RETVAL(E_NULL);
   }

   /* check object type to avoid re-initialization */

   /* enter critical */
   uint32_t temp;
   temp = OBJECT_ENTER_CRITICAL();
   /* try to find object */
   xlist_for_each(node, &(obj_set->obj_list))
   {
       obj = xlist_entry(node, object_t, list);
       if (obj == object)
       {
           OBJECT_EXIT_CRITICAL(temp);
           return RETVAL(E_FAIL);
       }
   }
   /* leave critical */
   OBJECT_EXIT_CRITICAL(temp);

   /* initialize object's parameters */
   /* set object type to static */
   object->type = type | OBJECT_CLASS_STATIC;

   /* copy name */
   strncpy(object->name, name, OBJECT_NAME_SIZE);
   object->name[OBJECT_NAME_SIZE-1] = '\0';

   /* lock interrupt */
   // temp = hw_interrupt_disable();
   temp = OBJECT_ENTER_CRITICAL();

   /* insert object into information object list */
   xlist_insert_after(&(obj_set->obj_list), &(object->list));

   /* unlock interrupt */
   // hw_interrupt_enable(temp);
   OBJECT_EXIT_CRITICAL(temp);

   return RETVAL(E_OK);
   }

/**

 * This function will detach a static object from object system,

 * and the memory of static object is not freed.
   *

 * @param object the specified object to be detached.
   */
   int32_t object_detach(object_t* object)
   {
   // register uint32_t temp;

   /* object check */
   if (object == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (!object_is_static_obj(object))
   {
       return RETVAL(E_FAIL);
   }

   /* reset object type */
   object->type = OBJECT_CLASS_NULL;

   /* lock interrupt */
   // temp = hw_interrupt_disable();
   uint32_t temp;
   temp = OBJECT_ENTER_CRITICAL();

   /* remove from old list */
   xlist_remove(&(object->list));

   /* unlock interrupt */
   // hw_interrupt_enable(temp);
   OBJECT_EXIT_CRITICAL(temp);

   return RETVAL(E_OK);
   }

/**

 * This function will allocate an object from object system
   *

 * @param type the type of object

 * @param name the object name. In system, the object's name must be unique.
   *

 * @return object
   */
   object_t* object_alloc_attack(object_class_t type, const char *name, xsize_t obj_size)
   {
   // register uint32_t temp;
   object_set_t *obj_set = NULL;
   object_t *obj = NULL;

   /* get object information */
   obj_set = object_get_obj_set(type);
   if (obj_set == NULL)
   {
       return NULL;
   }

   if (object_find(type, name) == NULL)
   {
       return NULL;
   }

   obj = (object_t *)OBJECT_MALLOC(obj_size);
   if (obj == NULL)
   {
       /* no memory can be allocated */
       return NULL;
   }

   /* clean memory data of object */
   memset(obj, 0, obj_size);

   /* initialize object's parameters */

   /* set object type */
   obj->type = type;

   /* copy name */
   strncpy(obj->name, name, OBJECT_NAME_SIZE);
   obj->name[OBJECT_NAME_SIZE-1] = '\0';

   /* lock interrupt */
   // temp = hw_interrupt_disable();
   uint32_t temp;
   temp = OBJECT_ENTER_CRITICAL();

   /* insert object into information object list */
   xlist_insert_after(&(obj_set->obj_list), &(obj->list));

   /* unlock interrupt */
   // hw_interrupt_enable(temp);
   OBJECT_EXIT_CRITICAL(temp);

   return obj;
   }

/**

 * This function will delete an object and release object memory.
   *

 * @param object the specified object to be deleted.
   */
   int32_t object_free_detack(object_t* object)
   {
   // register uint32_t temp;

   /* object check */
   if (object == NULL)
   {
       return RETVAL(E_NULL);
   }

   if (object_is_static_obj(object))
   {
       return RETVAL(E_FAIL);
   }

   /* reset object type */
   object->type = OBJECT_CLASS_NULL;

   /* lock interrupt */
   // temp = hw_interrupt_disable();
   uint32_t temp;
   temp = OBJECT_ENTER_CRITICAL();

   /* remove from old list */
   xlist_remove(&(object->list));

   /* unlock interrupt */
   // hw_interrupt_enable(temp);
   OBJECT_EXIT_CRITICAL(temp);

   /* free the memory of object */
   OBJECT_FREE(object);

   return RETVAL(E_OK);
   }

/**

 * This function will judge the object is system object or not.

 * Normally, the system object is a static object and the type

 * of object set to Object_Class_Static.
   *

 * @param object the specified object to be judged.
   *

 * @return TRUE if a system object, FALSE for others.
   */
   bool object_is_static_obj(object_t* object)
   {
   if (object->type & OBJECT_CLASS_STATIC)
   {
       return true;
   }

   return false;
   }

/**

 * This function will return the type of object without

 * Object_Class_Static flag.
   *

 * @param object the specified object to be get type.
   *

 * @return the type of object.
   */
   object_class_t object_get_type(object_t* object)
   {
   if (object == NULL)
   {
       return OBJECT_CLASS_NULL;
   }

   return (object->type & ~OBJECT_CLASS_STATIC);
   }

/**

 * This function will find specified name object from object

 * container.
   *

 * @param name the specified name of object.

 * @param type the type of object
   *

 * @return the found object or NULL if there is no this object

 * in object container.
   *

 * @note this function shall not be invoked in interrupt status.
   */
   object_t* object_find(object_class_t type, const char *name)
   {
   object_set_t *obj_set = NULL;
   object_t *obj = NULL;
   xlist_node_t *node = NULL;

   /* parameter check */
   if ((name == NULL) || (type >= OBJECT_CLASS_UNKNOWN))
   {
       return NULL;
   }

   /* try to find object */
   obj_set = object_get_obj_set(type);
   if (obj_set == NULL)
   {
       return NULL;
   }

   /* enter critical */
   uint32_t temp;
   temp = OBJECT_ENTER_CRITICAL();
   xlist_for_each(node, &(obj_set->obj_list))
   {
       obj = xlist_entry(node, object_t, list);
       if (strncmp(obj->name, name, OBJECT_NAME_SIZE) == 0)
       {
           OBJECT_EXIT_CRITICAL(temp);
           return obj;
       }
   }
   /* leave critical */
   OBJECT_EXIT_CRITICAL(temp);

   return NULL;
   }

#ifndef _OBJECT_H_
#define _OBJECT_H_

#include "typedefs.h"
#include "xlist2.h"

#define OBJECT_NAME_SIZE     10

/**

 *  The object type can be one of the follows with specific
    */
    typedef enum
    {
    OBJECT_CLASS_NULL,
    OBJECT_CLASS_DEVICE,                    /**< The object is a device */
    OBJECT_CLASS_DRIVER,                    /**< The object is a driver */
    OBJECT_CLASS_UNKNOWN,                   /**< The object is unknown. */
    OBJECT_CLASS_STATIC = 0x80              /**< The object is a static object. */
    } object_class_t;

/**

 * Base structure of Kernel object
   */
   typedef struct
   {
   object_class_t  type;                   /**< type of kernel object */
   char            name[OBJECT_NAME_SIZE]; /**< name of kernel object */
   xlist_t         list;                   /**< list node of kernel object */
   } object_t;

/**

 * The information of the kernel object
   */
   typedef struct
   {
   object_class_t  obj_type;               /**< object class type */
   xlist_t         obj_list;               /**< object list */
   } object_set_t;


object_set_t* object_get_obj_set(object_class_t type);

int32_t object_attack(object_t *object, object_class_t type, const char *name);
int32_t object_detach(object_t* object);

object_t* object_alloc_attack(object_class_t type, const char *name, xsize_t obj_size);
int32_t object_free_detack(object_t* object);

bool object_is_static_obj(object_t* object);

object_class_t object_get_type(object_t* object);
object_t* object_find(object_class_t type, const char *name);

#endif // _OBJECT_H_
```![bb0c568a0d58408ead3e7f72b2e014b3.jpg][2]


  [1]: https://www.limint86.tech:1443/usr/uploads/2023/08/1683673598.jpg
  [2]: https://www.limint86.tech:1443/usr/uploads/2023/08/2699238388.jpg

声明:atom|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - MCU模拟Linux注册驱动


道生一,一生二,二生三,三生万物