首页 > 系统相关 >[单片机框架][driver层][ioctl] MCU模拟Linux注册驱动

[单片机框架][driver层][ioctl] MCU模拟Linux注册驱动

时间:2022-10-31 20:37:31浏览次数:42  
标签:return object driver dev 单片机 ioctl device DEVICE


概念

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)告诉驱动程序它想做什么,至于怎么解释这些命令和怎么实现这些命令,这都是驱动程序要做的事情。

[单片机框架][driver层][ioctl] MCU模拟Linux注册驱动_#include

在计算机中,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_


标签:return,object,driver,dev,单片机,ioctl,device,DEVICE
From: https://blog.51cto.com/xuejianqiang/5811161

相关文章

  • 单片机 STM32 HAL GSM通讯 SIM800L
    /*************笔记****************1、本SIM800L模块采用huart3(串口3),然后huart1(串口1)作为调试输出。2、CudeMX配置huart3:----------------------------------------......
  • 单片机 STM32 HAL PCF8574 例子代码
    #include"extgpio.h"#include"pcf8574.h"#include"74hc595.h"/******************笔记:1、X输入Y输出2、NPN(箭头向下)高电平时导通,PNP(箭头向上)低电平时导通;3、PCF8574......
  • 单片机 STM32 HAL IO扩展 74HC595 例子代码
    #include"74hc595.h"/******************功能:定义HC595的功能引脚备注:变更引脚,由MX配置完成*******************/constT_HC595_PINhc595={.sck_port=HC595_......
  • 单片机 N76E003 EC12 编码器
    sbitEC_B=P0^0;//编码器P0.0端口sbitEC_A=P1^3;//编码器P1.3端口staticuint8_tEC_A_Val=0,EC_B_Val=0;staticuint8_tEC_A_old=0,EC_B_ol......
  • N76E003 单片机 IIC 软模拟
    /*-----------------------------------------头文件-----------------------------------------*/#include"iic.h"/*-----------------------------------------宏定义-......
  • 单片机 ADXL346 IIC通讯
    ​​IIC协议链接​​/*-----------------------------------------头文件-----------------------------------------*/#include"ADXL346.h"#include"math.h"/*--------......
  • [单片机框架][os层] RTX5 中间件 公共函数
    KeilRTX5是一种免版税、确定性、全功能的实时操作系统,它实现了CMSIS-RTOSAPIv2,这是一种适用于基于Cortex-M处理器的设备的通用RTOS接口。功能包括定期激活定时器功......
  • [单片机框架][bsp层][cx32l003][bsp_tim] TIM定时器配置和使用
    TIM1简介高级控制定时器(TIM1)由一个16位的自动装载计数器组成,它由一个可编程的预分频器驱动。它适合多种用途,包含测量输入信号的脉冲宽度(输入捕获),或者产生输出波形(输......
  • [单片机框架][bsp层][cx32l003][bsp_crc] 硬件CRC配置和使用
    循环冗余校验(CRC)计算单元是根据固定的生成多项式得到任意字节数据的CRC计算结果。在应用中,CRC技术主要应用于核实数据传输或者数据存储的正确性和完整性。本模块算法......
  • [单片机框架][bsp层][cx32l003][bsp_key] KEY配置和使用
    按键的基本原理是设置单片机IO口(PB0-PB3)为输入状态,如DDRB=0XF0(方向寄存器,“1”为输出,“0”为输入);单片机一直检测按键端口(PB0-PB3)的状态,当端口为低电平时(即按键按下),实行相......