1.CAN模板更新。2.设备框架更新,中断机制重构,设备中断仅唤醒自身回调列表,需要递归调用可手动调用mr_dev_isr。3.由于使用回调列表,数据量可能发生变化,设备中断回调不再传入缓冲区数据数量,需用户手动获取。4.PIN设备支持模式保存。5.serial新增DMA支持。
This commit is contained in:
242
device/can.c
242
device/can.c
@@ -30,12 +30,12 @@ static int mr_can_bus_close(struct mr_dev *dev)
|
||||
return ops->configure(can_bus, &close_config);
|
||||
}
|
||||
|
||||
static ssize_t mr_can_bus_read(struct mr_dev *dev, int off, void *buf, size_t size, int async)
|
||||
static ssize_t mr_can_bus_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
{
|
||||
return MR_EIO;
|
||||
}
|
||||
|
||||
static ssize_t mr_can_bus_write(struct mr_dev *dev, int off, const void *buf, size_t size, int async)
|
||||
static ssize_t mr_can_bus_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
{
|
||||
return MR_EIO;
|
||||
}
|
||||
@@ -45,37 +45,34 @@ static ssize_t mr_can_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
struct mr_can_bus *can_bus = (struct mr_can_bus *)dev;
|
||||
struct mr_can_bus_ops *ops = (struct mr_can_bus_ops *)dev->drv->ops;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MR_ISR_CAN_RD_INT:
|
||||
{
|
||||
struct mr_list *list = MR_NULL;
|
||||
switch (event) {
|
||||
case MR_ISR_CAN_RD_INT: {
|
||||
uint8_t data[8] = {0};
|
||||
int id = ops->get_id(can_bus);
|
||||
ssize_t ret = ops->read(can_bus, data, sizeof(data));
|
||||
int id, ide, rtr;
|
||||
|
||||
/* Read id and data to FIFO */
|
||||
ssize_t ret = ops->read(can_bus, &id, &ide, &rtr, data, sizeof(data));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
id = (ide == MR_CAN_IDE_STD) ? (id & 0x7ff) : (id & 0x1fffffff);
|
||||
|
||||
/* Search the matching device */
|
||||
for (list = dev->clist.next; list != &dev->clist; list = list->next)
|
||||
{
|
||||
struct mr_can_dev *can_dev = (struct mr_can_dev *)MR_CONTAINER_OF(list, struct mr_dev, list);
|
||||
for (struct mr_list *list = dev->clist.next; list != &dev->clist; list = list->next) {
|
||||
struct mr_can_dev *can_dev = (struct mr_can_dev *)MR_CONTAINER_OF(list,
|
||||
struct mr_dev,
|
||||
list);
|
||||
|
||||
/* Check id is valid */
|
||||
if (can_dev->id == (id & ((1 << 29) - 1)))
|
||||
{
|
||||
/* Read data to FIFO. if callback is set, call it */
|
||||
if (can_dev->id == id) {
|
||||
mr_ringbuf_write_force(&can_dev->rd_fifo, data, ret);
|
||||
if (can_dev->dev.rd_call.call != MR_NULL)
|
||||
{
|
||||
ssize_t size = (ssize_t)mr_ringbuf_get_data_size(&can_dev->rd_fifo);
|
||||
can_dev->dev.rd_call.call(can_dev->dev.rd_call.desc, &size);
|
||||
}
|
||||
break;
|
||||
|
||||
return mr_dev_isr(&can_dev->dev, event, &rtr);
|
||||
}
|
||||
}
|
||||
return MR_EOK;
|
||||
return MR_ENOTFOUND;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -85,26 +82,23 @@ static ssize_t mr_can_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
* @brief This function registers a can-bus.
|
||||
*
|
||||
* @param can_dev The can-device.
|
||||
* @param name The name of the can-bus.
|
||||
* @param path The path of the can-bus.
|
||||
* @param drv The driver of the can-bus.
|
||||
*
|
||||
* @return MR_EOK on success, otherwise an error code.
|
||||
* @return 0 on success, otherwise an error code.
|
||||
*/
|
||||
int mr_can_bus_register(struct mr_can_bus *can_bus, const char *name, struct mr_drv *drv)
|
||||
int mr_can_bus_register(struct mr_can_bus *can_bus, const char *path, struct mr_drv *drv)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
mr_can_bus_open,
|
||||
mr_can_bus_close,
|
||||
mr_can_bus_read,
|
||||
mr_can_bus_write,
|
||||
MR_NULL,
|
||||
mr_can_bus_isr
|
||||
};
|
||||
static struct mr_dev_ops ops = {mr_can_bus_open,
|
||||
mr_can_bus_close,
|
||||
mr_can_bus_read,
|
||||
mr_can_bus_write,
|
||||
MR_NULL,
|
||||
mr_can_bus_isr};
|
||||
struct mr_can_config default_config = MR_CAN_CONFIG_DEFAULT;
|
||||
|
||||
MR_ASSERT(can_bus != MR_NULL);
|
||||
MR_ASSERT(name != MR_NULL);
|
||||
MR_ASSERT(path != MR_NULL);
|
||||
MR_ASSERT(drv != MR_NULL);
|
||||
MR_ASSERT(drv->ops != MR_NULL);
|
||||
|
||||
@@ -113,10 +107,10 @@ int mr_can_bus_register(struct mr_can_bus *can_bus, const char *name, struct mr_
|
||||
can_bus->owner = MR_NULL;
|
||||
|
||||
/* Register the can-bus */
|
||||
return mr_dev_register(&can_bus->dev, name, Mr_Dev_Type_CAN, MR_SFLAG_RDWR, &ops, drv);
|
||||
return mr_dev_register(&can_bus->dev, path, MR_DEV_TYPE_CAN, MR_O_RDWR, &ops, drv);
|
||||
}
|
||||
|
||||
static int can_dev_filter_configure(struct mr_can_dev *can_dev, int id, int ide, int state)
|
||||
MR_INLINE int can_dev_filter_configure(struct mr_can_dev *can_dev, int id, int ide, int state)
|
||||
{
|
||||
struct mr_can_bus *can_bus = (struct mr_can_bus *)can_dev->dev.parent;
|
||||
struct mr_can_bus_ops *ops = (struct mr_can_bus_ops *)can_bus->dev.drv->ops;
|
||||
@@ -129,24 +123,22 @@ MR_INLINE int can_dev_take_bus(struct mr_can_dev *can_dev)
|
||||
struct mr_can_bus *can_bus = (struct mr_can_bus *)can_dev->dev.parent;
|
||||
struct mr_can_bus_ops *ops = (struct mr_can_bus_ops *)can_bus->dev.drv->ops;
|
||||
|
||||
if ((can_dev != can_bus->owner) && (can_bus->owner != MR_NULL))
|
||||
{
|
||||
if ((can_bus->hold == MR_TRUE) && (can_dev != can_bus->owner)) {
|
||||
return MR_EBUSY;
|
||||
}
|
||||
|
||||
if (can_dev != can_bus->owner)
|
||||
{
|
||||
if (can_dev->config.baud_rate != can_bus->config.baud_rate)
|
||||
{
|
||||
/* If the owner changes, recheck the configuration */
|
||||
if (can_dev != can_bus->owner) {
|
||||
if (can_dev->config.baud_rate != can_bus->config.baud_rate) {
|
||||
int ret = ops->configure(can_bus, &can_dev->config);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
can_bus->config = can_dev->config;
|
||||
can_bus->owner = can_dev;
|
||||
}
|
||||
can_bus->hold = MR_TRUE;
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
@@ -154,137 +146,97 @@ MR_INLINE int can_dev_release_bus(struct mr_can_dev *can_dev)
|
||||
{
|
||||
struct mr_can_bus *can_bus = (struct mr_can_bus *)can_dev->dev.parent;
|
||||
|
||||
if (can_dev != can_bus->owner)
|
||||
{
|
||||
if (can_dev != can_bus->owner) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
can_bus->owner = MR_NULL;
|
||||
can_bus->hold = MR_FALSE;
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
MR_INLINE ssize_t can_dev_read(struct mr_can_dev *can_dev, uint8_t *buf, size_t size)
|
||||
MR_INLINE ssize_t can_dev_write(struct mr_can_dev *can_dev,
|
||||
int id,
|
||||
int ide,
|
||||
const uint8_t *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct mr_can_bus *can_bus = (struct mr_can_bus *)can_dev->dev.parent;
|
||||
struct mr_can_bus_ops *ops = (struct mr_can_bus_ops *)can_bus->dev.drv->ops;
|
||||
ssize_t rd_size = 0;
|
||||
|
||||
for (rd_size = 0; rd_size < size;)
|
||||
{
|
||||
/* Check id is valid */
|
||||
int id = ops->get_id(can_bus);
|
||||
if (can_dev->id != (id & ((1 << 29) - 1)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ssize_t ret = ops->read(can_bus, (buf + rd_size), (size - rd_size));
|
||||
if (ret <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
rd_size += ret;
|
||||
}
|
||||
return rd_size;
|
||||
return ops->write(can_bus, id, ide, buf, count);
|
||||
}
|
||||
|
||||
MR_INLINE ssize_t can_dev_write(struct mr_can_dev *can_dev, int id, int ide, int rtr, const uint8_t *buf, size_t size)
|
||||
MR_INLINE int can_dev_request(struct mr_can_dev *can_dev, int id, int ide)
|
||||
{
|
||||
struct mr_can_bus *can_bus = (struct mr_can_bus *)can_dev->dev.parent;
|
||||
struct mr_can_bus_ops *ops = (struct mr_can_bus_ops *)can_bus->dev.drv->ops;
|
||||
|
||||
return ops->write(can_bus, id, ide, rtr, buf, size);
|
||||
return ops->remote_request(can_bus, id, ide);
|
||||
}
|
||||
|
||||
static int mr_can_dev_open(struct mr_dev *dev)
|
||||
{
|
||||
struct mr_can_dev *can_dev = (struct mr_can_dev *)dev;
|
||||
|
||||
/* Allocate FIFO buffers */
|
||||
int ret = mr_ringbuf_allocate(&can_dev->rd_fifo, can_dev->rd_bufsz);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return can_dev_filter_configure(can_dev->dev.parent, can_dev->id, can_dev->ide, MR_ENABLE);
|
||||
return can_dev_filter_configure(can_dev, can_dev->id, can_dev->ide, MR_ENABLE);
|
||||
}
|
||||
|
||||
static int mr_can_dev_close(struct mr_dev *dev)
|
||||
{
|
||||
struct mr_can_dev *can_dev = (struct mr_can_dev *)dev;
|
||||
|
||||
/* Free FIFO buffers */
|
||||
mr_ringbuf_free(&can_dev->rd_fifo);
|
||||
|
||||
return can_dev_filter_configure(can_dev->dev.parent, can_dev->id, can_dev->ide, MR_DISABLE);
|
||||
return can_dev_filter_configure(can_dev, can_dev->id, can_dev->ide, MR_DISABLE);
|
||||
}
|
||||
|
||||
static ssize_t mr_can_dev_read(struct mr_dev *dev, int off, void *buf, size_t size, int async)
|
||||
static ssize_t mr_can_dev_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
{
|
||||
struct mr_can_dev *can_dev = (struct mr_can_dev *)dev;
|
||||
|
||||
ssize_t ret = can_dev_take_bus(can_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mr_ringbuf_get_bufsz(&can_dev->rd_fifo) == 0)
|
||||
{
|
||||
ret = can_dev_read(can_dev, (uint8_t *)buf, size);
|
||||
} else
|
||||
{
|
||||
ret = (ssize_t)mr_ringbuf_read(&can_dev->rd_fifo, buf, size);
|
||||
}
|
||||
ret = (ssize_t)mr_ringbuf_read(&can_dev->rd_fifo, buf, count);
|
||||
|
||||
can_dev_release_bus(can_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t mr_can_dev_write(struct mr_dev *dev, int off, const void *buf, size_t size, int async)
|
||||
static ssize_t mr_can_dev_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
{
|
||||
struct mr_can_dev *can_dev = (struct mr_can_dev *)dev;
|
||||
|
||||
/* Check offset is valid */
|
||||
if (off < 0)
|
||||
{
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
ssize_t ret = can_dev_take_bus(can_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = can_dev_write(can_dev,
|
||||
(off & ((1 << 29) - 1)),
|
||||
MR_BIT_IS_SET(off, MR_CAN_IDE_EXT),
|
||||
MR_BIT_IS_SET(off, MR_CAN_RTR_REMOTE),
|
||||
(uint8_t *)buf,
|
||||
size);
|
||||
ret = can_dev_write(can_dev, can_dev->id, can_dev->ide, (uint8_t *)buf, count);
|
||||
|
||||
can_dev_release_bus(can_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mr_can_dev_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
static int mr_can_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
{
|
||||
struct mr_can_dev *can_dev = (struct mr_can_dev *)dev;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MR_CTL_SET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MR_IOC_CAN_SET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_can_bus *can_bus = (struct mr_can_bus *)dev->parent;
|
||||
struct mr_can_config config = *(struct mr_can_config *)args;
|
||||
|
||||
/* If holding the bus, release it */
|
||||
if (can_dev == can_bus->owner)
|
||||
{
|
||||
if (can_dev == can_bus->owner) {
|
||||
can_bus->hold = MR_FALSE;
|
||||
can_bus->owner = MR_NULL;
|
||||
}
|
||||
@@ -293,16 +245,13 @@ static int mr_can_dev_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_CTL_SET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_CAN_SET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t bufsz = *(size_t *)args;
|
||||
|
||||
int ret = mr_ringbuf_allocate(&can_dev->rd_fifo, bufsz);
|
||||
can_dev->rd_bufsz = 0;
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
can_dev->rd_bufsz = bufsz;
|
||||
@@ -310,10 +259,15 @@ static int mr_can_dev_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_CTL_GET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_CAN_CLR_RD_BUF: {
|
||||
mr_ringbuf_reset(&can_dev->rd_fifo);
|
||||
return MR_EOK;
|
||||
}
|
||||
case MR_IOC_CAN_REMOTE_REQUEST: {
|
||||
return can_dev_request(can_dev, can_dev->id, can_dev->ide);
|
||||
}
|
||||
case MR_IOC_CAN_GET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_can_config *config = (struct mr_can_config *)args;
|
||||
|
||||
*config = can_dev->config;
|
||||
@@ -321,10 +275,8 @@ static int mr_can_dev_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_CTL_GET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_CAN_GET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *bufsz = (size_t *)args;
|
||||
|
||||
*bufsz = can_dev->rd_bufsz;
|
||||
@@ -332,8 +284,16 @@ static int mr_can_dev_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
default:
|
||||
{
|
||||
case MR_IOC_CAN_GET_RD_DATASZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *datasz = (size_t *)args;
|
||||
|
||||
*datasz = mr_ringbuf_get_data_size(&can_dev->rd_fifo);
|
||||
return sizeof(*datasz);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -343,27 +303,27 @@ static int mr_can_dev_ioctl(struct mr_dev *dev, int off, int cmd, void *args)
|
||||
* @brief This function registers a can-device.
|
||||
*
|
||||
* @param can_dev The can-device.
|
||||
* @param name The name of the can-device.
|
||||
* @param path The path of the can-device.
|
||||
* @param id The id of the can-device.
|
||||
* @param ide The id identifier of the can-device.
|
||||
*
|
||||
* @return MR_EOK on success, otherwise an error code.
|
||||
* @return 0 on success, otherwise an error code.
|
||||
*/
|
||||
int mr_can_dev_register(struct mr_can_dev *can_dev, const char *name, int id, int ide)
|
||||
int mr_can_dev_register(struct mr_can_dev *can_dev, const char *path, int id, int ide)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
mr_can_dev_open,
|
||||
mr_can_dev_close,
|
||||
mr_can_dev_read,
|
||||
mr_can_dev_write,
|
||||
mr_can_dev_ioctl,
|
||||
MR_NULL
|
||||
};
|
||||
static struct mr_dev_ops ops = {mr_can_dev_open,
|
||||
mr_can_dev_close,
|
||||
mr_can_dev_read,
|
||||
mr_can_dev_write,
|
||||
mr_can_dev_ioctl,
|
||||
MR_NULL};
|
||||
struct mr_can_config default_config = MR_CAN_CONFIG_DEFAULT;
|
||||
|
||||
MR_ASSERT(can_dev != MR_NULL);
|
||||
MR_ASSERT(name != MR_NULL);
|
||||
MR_ASSERT(path != MR_NULL);
|
||||
MR_ASSERT((ide == MR_CAN_IDE_STD) || (ide == MR_CAN_IDE_EXT));
|
||||
MR_ASSERT((ide != MR_CAN_IDE_STD) || ((id >= 0) && (id <= 0x7ff)));
|
||||
MR_ASSERT((ide != MR_CAN_IDE_EXT) || ((id >= 0) && (id <= 0x1fffffff)));
|
||||
|
||||
/* Initialize the fields */
|
||||
can_dev->config = default_config;
|
||||
@@ -376,7 +336,7 @@ int mr_can_dev_register(struct mr_can_dev *can_dev, const char *name, int id, in
|
||||
can_dev->ide = ide;
|
||||
|
||||
/* Register the can-device */
|
||||
return mr_dev_register(&can_dev->dev, name, Mr_Dev_Type_CAN, MR_SFLAG_RDWR | MR_SFLAG_NONDRV, &ops, MR_NULL);
|
||||
return mr_dev_register(&can_dev->dev, path, MR_DEV_TYPE_CAN, MR_O_RDWR, &ops, MR_NULL);
|
||||
}
|
||||
|
||||
#endif /* MR_USING_CAN */
|
||||
|
||||
186
device/i2c.c
186
device/i2c.c
@@ -46,25 +46,22 @@ static ssize_t mr_i2c_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
struct mr_i2c_bus *i2c_bus = (struct mr_i2c_bus *)dev;
|
||||
struct mr_i2c_bus_ops *ops = (struct mr_i2c_bus_ops *)dev->drv->ops;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MR_ISR_I2C_RD_INT:
|
||||
{
|
||||
switch (event) {
|
||||
case MR_ISR_I2C_RD_INT: {
|
||||
struct mr_i2c_dev *i2c_dev = (struct mr_i2c_dev *)i2c_bus->owner;
|
||||
uint8_t data;
|
||||
|
||||
/* Read data to FIFO */
|
||||
int ret = ops->read(i2c_bus, &data, MR_ENABLE);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
mr_ringbuf_push_force(&i2c_dev->rd_fifo, data);
|
||||
|
||||
return (ssize_t)mr_ringbuf_get_data_size(&i2c_dev->rd_fifo);
|
||||
/* Call the i2c-dev ISR */
|
||||
return mr_dev_isr(&i2c_dev->dev, event, MR_NULL);
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -81,15 +78,12 @@ static ssize_t mr_i2c_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
*/
|
||||
int mr_i2c_bus_register(struct mr_i2c_bus *i2c_bus, const char *path, struct mr_drv *drv)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
mr_i2c_bus_open,
|
||||
mr_i2c_bus_close,
|
||||
mr_i2c_bus_read,
|
||||
mr_i2c_bus_write,
|
||||
MR_NULL,
|
||||
mr_i2c_bus_isr
|
||||
};
|
||||
static struct mr_dev_ops ops = {mr_i2c_bus_open,
|
||||
mr_i2c_bus_close,
|
||||
mr_i2c_bus_read,
|
||||
mr_i2c_bus_write,
|
||||
MR_NULL,
|
||||
mr_i2c_bus_isr};
|
||||
struct mr_i2c_config default_config = MR_I2C_CONFIG_DEFAULT;
|
||||
|
||||
MR_ASSERT(i2c_bus != MR_NULL);
|
||||
@@ -112,22 +106,18 @@ MR_INLINE int i2c_dev_take_bus(struct mr_i2c_dev *i2c_dev)
|
||||
struct mr_i2c_bus_ops *ops = (struct mr_i2c_bus_ops *)i2c_bus->dev.drv->ops;
|
||||
|
||||
/* Check if the bus is busy */
|
||||
if ((i2c_bus->hold == MR_TRUE) && (i2c_dev != i2c_bus->owner))
|
||||
{
|
||||
if ((i2c_bus->hold == MR_TRUE) && (i2c_dev != i2c_bus->owner)) {
|
||||
return MR_EBUSY;
|
||||
}
|
||||
|
||||
/* If the owner changes, recheck the configuration */
|
||||
if (i2c_dev != i2c_bus->owner)
|
||||
{
|
||||
if (i2c_dev->config.baud_rate != i2c_bus->config.baud_rate
|
||||
|| i2c_dev->config.host_slave != i2c_bus->config.host_slave)
|
||||
{
|
||||
if (i2c_dev != i2c_bus->owner) {
|
||||
if (i2c_dev->config.baud_rate != i2c_bus->config.baud_rate ||
|
||||
i2c_dev->config.host_slave != i2c_bus->config.host_slave) {
|
||||
int addr = (i2c_dev->config.host_slave == MR_I2C_HOST) ? 0x00 : i2c_dev->addr;
|
||||
|
||||
int ret = ops->configure(i2c_bus, &i2c_dev->config, addr, i2c_dev->addr_bits);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -142,14 +132,12 @@ MR_INLINE int i2c_dev_release_bus(struct mr_i2c_dev *i2c_dev)
|
||||
{
|
||||
struct mr_i2c_bus *i2c_bus = (struct mr_i2c_bus *)i2c_dev->dev.parent;
|
||||
|
||||
if (i2c_dev != i2c_bus->owner)
|
||||
{
|
||||
if (i2c_dev != i2c_bus->owner) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
/* If it is a host, release the bus. The slave needs to hold the bus at all times */
|
||||
if (i2c_dev->config.host_slave == MR_I2C_HOST)
|
||||
{
|
||||
if (i2c_dev->config.host_slave == MR_I2C_HOST) {
|
||||
i2c_bus->hold = MR_FALSE;
|
||||
}
|
||||
return MR_EOK;
|
||||
@@ -170,15 +158,13 @@ MR_INLINE int i2c_dev_send_addr(struct mr_i2c_dev *i2c_dev, int rdwr)
|
||||
|
||||
/* Set the read command */
|
||||
addr = (0xf000 | ((addr >> 8) & 0x03) << 9) | (addr & 0xff);
|
||||
if (rdwr == MR_I2C_RD)
|
||||
{
|
||||
if (rdwr == MR_I2C_RD) {
|
||||
addr |= (addr_bits == MR_I2C_ADDR_BITS_7) ? 0x01 : 0x10;
|
||||
}
|
||||
|
||||
ops->start(i2c_bus);
|
||||
int ret = ops->send_addr(i2c_bus, addr, addr_bits);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
ops->stop(i2c_bus);
|
||||
}
|
||||
return ret;
|
||||
@@ -198,13 +184,11 @@ MR_INLINE ssize_t i2c_dev_read(struct mr_i2c_dev *i2c_dev, uint8_t *buf, size_t
|
||||
struct mr_i2c_bus_ops *ops = (struct mr_i2c_bus_ops *)i2c_bus->dev.drv->ops;
|
||||
ssize_t rd_size;
|
||||
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*buf))
|
||||
{
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*buf)) {
|
||||
int ack = ((count - rd_size) != sizeof(*buf));
|
||||
|
||||
int ret = ops->read(i2c_bus, buf, ack);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
buf++;
|
||||
@@ -218,11 +202,9 @@ MR_INLINE ssize_t i2c_dev_write(struct mr_i2c_dev *i2c_dev, const uint8_t *buf,
|
||||
struct mr_i2c_bus_ops *ops = (struct mr_i2c_bus_ops *)i2c_bus->dev.drv->ops;
|
||||
ssize_t wr_size;
|
||||
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*buf))
|
||||
{
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*buf)) {
|
||||
int ret = ops->write(i2c_bus, *buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
buf++;
|
||||
@@ -250,38 +232,33 @@ static ssize_t mr_i2c_dev_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
struct mr_i2c_dev *i2c_dev = (struct mr_i2c_dev *)dev;
|
||||
|
||||
ssize_t ret = i2c_dev_take_bus(i2c_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (i2c_dev->config.host_slave == MR_I2C_HOST)
|
||||
{
|
||||
if (i2c_dev->config.host_slave == MR_I2C_HOST) {
|
||||
/* Send the address of the register that needs to be read */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
if (dev->position >= 0) {
|
||||
ret = i2c_dev_send_addr(i2c_dev, MR_I2C_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
goto release_bus;
|
||||
}
|
||||
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)&dev->position, (i2c_dev->config.reg_bits >> 3));
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = i2c_dev_write(i2c_dev,
|
||||
(uint8_t *)&dev->position,
|
||||
(i2c_dev->config.reg_bits >> 3));
|
||||
if (ret < 0) {
|
||||
goto release_bus;
|
||||
}
|
||||
}
|
||||
|
||||
ret = i2c_dev_send_addr(i2c_dev, MR_I2C_RD);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
goto release_bus;
|
||||
}
|
||||
ret = i2c_dev_read(i2c_dev, (uint8_t *)buf, count);
|
||||
i2c_dev_send_stop(i2c_dev);
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
ret = (ssize_t)mr_ringbuf_read(&i2c_dev->rd_fifo, buf, count);
|
||||
}
|
||||
|
||||
@@ -295,33 +272,29 @@ static ssize_t mr_i2c_dev_write(struct mr_dev *dev, const void *buf, size_t coun
|
||||
struct mr_i2c_dev *i2c_dev = (struct mr_i2c_dev *)dev;
|
||||
|
||||
ssize_t ret = i2c_dev_take_bus(i2c_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (i2c_dev->config.host_slave == MR_I2C_HOST)
|
||||
{
|
||||
if (i2c_dev->config.host_slave == MR_I2C_HOST) {
|
||||
ret = i2c_dev_send_addr(i2c_dev, MR_I2C_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
goto release_bus;
|
||||
}
|
||||
|
||||
/* Send the address of the register that needs to be written */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)&dev->position, (i2c_dev->config.reg_bits >> 3));
|
||||
if (ret < 0)
|
||||
{
|
||||
if (dev->position >= 0) {
|
||||
ret = i2c_dev_write(i2c_dev,
|
||||
(uint8_t *)&dev->position,
|
||||
(i2c_dev->config.reg_bits >> 3));
|
||||
if (ret < 0) {
|
||||
goto release_bus;
|
||||
}
|
||||
}
|
||||
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)buf, count);
|
||||
i2c_dev_send_stop(i2c_dev);
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
ret = i2c_dev_write(i2c_dev, (uint8_t *)buf, count);
|
||||
}
|
||||
|
||||
@@ -334,29 +307,23 @@ static int mr_i2c_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
{
|
||||
struct mr_i2c_dev *i2c_dev = (struct mr_i2c_dev *)dev;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MR_IOC_I2C_SET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MR_IOC_I2C_SET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_i2c_bus *i2c_bus = (struct mr_i2c_bus *)dev->parent;
|
||||
struct mr_i2c_config config = *(struct mr_i2c_config *)args;
|
||||
|
||||
/* If holding the bus, release it */
|
||||
if (i2c_dev == i2c_bus->owner)
|
||||
{
|
||||
if (i2c_dev == i2c_bus->owner) {
|
||||
i2c_bus->hold = MR_FALSE;
|
||||
i2c_bus->owner = MR_NULL;
|
||||
}
|
||||
|
||||
/* Update the configuration and try again to get the bus */
|
||||
i2c_dev->config = config;
|
||||
if (config.host_slave == MR_I2C_SLAVE)
|
||||
{
|
||||
if (config.host_slave == MR_I2C_SLAVE) {
|
||||
int ret = i2c_dev_take_bus(i2c_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -364,16 +331,13 @@ static int mr_i2c_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_I2C_SET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_I2C_SET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t bufsz = *(size_t *)args;
|
||||
|
||||
int ret = mr_ringbuf_allocate(&i2c_dev->rd_fifo, bufsz);
|
||||
i2c_dev->rd_bufsz = 0;
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
i2c_dev->rd_bufsz = bufsz;
|
||||
@@ -381,15 +345,12 @@ static int mr_i2c_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_I2C_CLR_RD_BUF:
|
||||
{
|
||||
case MR_IOC_I2C_CLR_RD_BUF: {
|
||||
mr_ringbuf_reset(&i2c_dev->rd_fifo);
|
||||
return MR_EOK;
|
||||
}
|
||||
case MR_IOC_I2C_GET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_I2C_GET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_i2c_config *config = (struct mr_i2c_config *)args;
|
||||
|
||||
*config = i2c_dev->config;
|
||||
@@ -397,10 +358,8 @@ static int mr_i2c_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_I2C_GET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_I2C_GET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *bufsz = (size_t *)args;
|
||||
|
||||
*bufsz = i2c_dev->rd_bufsz;
|
||||
@@ -408,18 +367,16 @@ static int mr_i2c_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_I2C_GET_RD_DATASZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_I2C_GET_RD_DATASZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *datasz = (size_t *)args;
|
||||
|
||||
*datasz = mr_ringbuf_get_bufsz(&i2c_dev->rd_fifo);
|
||||
return sizeof(*datasz);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -437,22 +394,19 @@ static int mr_i2c_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
*/
|
||||
int mr_i2c_dev_register(struct mr_i2c_dev *i2c_dev, const char *path, int addr, int addr_bits)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
mr_i2c_dev_open,
|
||||
mr_i2c_dev_close,
|
||||
mr_i2c_dev_read,
|
||||
mr_i2c_dev_write,
|
||||
mr_i2c_dev_ioctl,
|
||||
MR_NULL
|
||||
};
|
||||
static struct mr_dev_ops ops = {mr_i2c_dev_open,
|
||||
mr_i2c_dev_close,
|
||||
mr_i2c_dev_read,
|
||||
mr_i2c_dev_write,
|
||||
mr_i2c_dev_ioctl,
|
||||
MR_NULL};
|
||||
struct mr_i2c_config default_config = MR_I2C_CONFIG_DEFAULT;
|
||||
|
||||
MR_ASSERT(i2c_dev != MR_NULL);
|
||||
MR_ASSERT(path != MR_NULL);
|
||||
MR_ASSERT((addr_bits == MR_I2C_ADDR_BITS_7) || (addr_bits == MR_I2C_ADDR_BITS_10));
|
||||
MR_ASSERT((addr_bits != MR_I2C_ADDR_BITS_7) || (addr >= 0x00 && addr <= 0x7f));
|
||||
MR_ASSERT((addr_bits != MR_I2C_ADDR_BITS_10) || (addr >= 0x00 && addr <= 0x3ff));
|
||||
MR_ASSERT((addr_bits != MR_I2C_ADDR_BITS_7) || (addr >= 0 && addr <= 0x7f));
|
||||
MR_ASSERT((addr_bits != MR_I2C_ADDR_BITS_10) || (addr >= 0 && addr <= 0x3ff));
|
||||
|
||||
/* Initialize the fields */
|
||||
i2c_dev->config = default_config;
|
||||
|
||||
129
device/pin.c
129
device/pin.c
@@ -12,16 +12,59 @@
|
||||
|
||||
void _mr_fast_pin_init(struct mr_dev *dev);
|
||||
|
||||
MR_INLINE int pin_set_mode(struct mr_pin *pin, int number, int mode)
|
||||
#define PIN_MODE_SET(_pin, _number, _mode) \
|
||||
do \
|
||||
{ \
|
||||
MR_BIT_CLR((_pin)->pins[(_number) / 8], (0xf << (((_number) % 8) * 4))); \
|
||||
MR_BIT_SET((_pin)->pins[(_number) / 8], ((_mode) << (((_number) % 8) * 4))); \
|
||||
} while (0)
|
||||
#define PIN_MODE_GET(_pin, _number) \
|
||||
((int)(((_pin)->pins[(_number) / 8] >> (((_number) % 8) * 4)) & 0xf)) \
|
||||
|
||||
MR_INLINE int pin_set_mode(struct mr_pin *pin, int number, struct mr_pin_config config)
|
||||
{
|
||||
struct mr_pin_ops *ops = (struct mr_pin_ops *)pin->dev.drv->ops;
|
||||
|
||||
if (number < 0)
|
||||
{
|
||||
if ((number < 0) || (number >= (sizeof(pin->pins) * 2))) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
return ops->configure(pin, number, mode);
|
||||
int ret = ops->configure(pin, number, config.mode);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
PIN_MODE_SET(pin, number, config.mode);
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
MR_INLINE int pin_get_mode(struct mr_pin *pin, int number, struct mr_pin_config *config)
|
||||
{
|
||||
if ((number < 0) || (number >= (sizeof(pin->pins) * 2))) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
config->mode = PIN_MODE_GET(pin, number);
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
static int mr_pin_close(struct mr_dev *dev)
|
||||
{
|
||||
struct mr_pin *pin = (struct mr_pin *)dev;
|
||||
struct mr_pin_ops *ops = (struct mr_pin_ops *)dev->drv->ops;
|
||||
|
||||
#ifdef MR_USING_PIN_AUTO_DISABLE
|
||||
/* Disable all pins */
|
||||
for (size_t i = 0; i < (sizeof(pin->pins) * 2); i++)
|
||||
{
|
||||
if (PIN_MODE_GET(pin, i) != MR_PIN_MODE_NONE)
|
||||
{
|
||||
ops->configure(pin, (int)i, MR_PIN_MODE_NONE);
|
||||
PIN_MODE_SET(pin, i, MR_PIN_MODE_NONE);
|
||||
}
|
||||
}
|
||||
#endif /* MR_USING_PIN_AUTO_DISABLE */
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
static ssize_t mr_pin_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
@@ -33,17 +76,16 @@ static ssize_t mr_pin_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
|
||||
#ifdef MR_USING_PIN_CHECK
|
||||
/* Check number is valid */
|
||||
if (dev->position < 0)
|
||||
{
|
||||
if ((dev->position < 0) ||
|
||||
(dev->position >= (sizeof(pin->pins) * 2)) ||
|
||||
(PIN_MODE_GET(pin, dev->position) == MR_PIN_MODE_NONE)) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
#endif /* MR_USING_PIN_CHECK */
|
||||
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*rd_buf)) {
|
||||
int ret = (uint8_t)ops->read(pin, dev->position, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
rd_buf++;
|
||||
@@ -60,17 +102,16 @@ static ssize_t mr_pin_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
|
||||
#ifdef MR_USING_PIN_CHECK
|
||||
/* Check number is valid */
|
||||
if (dev->position < 0)
|
||||
{
|
||||
if ((dev->position < 0) ||
|
||||
(dev->position >= (sizeof(pin->pins) * 2)) ||
|
||||
(PIN_MODE_GET(pin, dev->position) == MR_PIN_MODE_NONE)) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
#endif /* MR_USING_PIN_CHECK */
|
||||
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*wr_buf))
|
||||
{
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*wr_buf)) {
|
||||
int ret = ops->write(pin, dev->position, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
wr_buf++;
|
||||
@@ -82,25 +123,31 @@ static int mr_pin_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
{
|
||||
struct mr_pin *pin = (struct mr_pin *)dev;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MR_IOC_PIN_SET_MODE:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MR_IOC_PIN_SET_MODE: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_pin_config config = *((struct mr_pin_config *)args);
|
||||
|
||||
int ret = pin_set_mode(pin, dev->position, config.mode);
|
||||
if (ret < 0)
|
||||
{
|
||||
int ret = pin_set_mode(pin, dev->position, config);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return sizeof(config);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
default:
|
||||
{
|
||||
case MR_IOC_PIN_GET_MODE: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_pin_config *config = (struct mr_pin_config *)args;
|
||||
|
||||
int ret = pin_get_mode(pin, dev->position, config);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return sizeof(*config);
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -108,16 +155,12 @@ static int mr_pin_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
|
||||
static ssize_t mr_pin_isr(struct mr_dev *dev, int event, void *args)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case MR_ISR_PIN_EXTI_INT:
|
||||
{
|
||||
switch (event) {
|
||||
case MR_ISR_PIN_EXTI_INT: {
|
||||
ssize_t number = *(int *)args;
|
||||
|
||||
return number;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -134,15 +177,12 @@ static ssize_t mr_pin_isr(struct mr_dev *dev, int event, void *args)
|
||||
*/
|
||||
int mr_pin_register(struct mr_pin *pin, const char *path, struct mr_drv *drv)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
MR_NULL,
|
||||
MR_NULL,
|
||||
mr_pin_read,
|
||||
mr_pin_write,
|
||||
mr_pin_ioctl,
|
||||
mr_pin_isr
|
||||
};
|
||||
static struct mr_dev_ops ops = {MR_NULL,
|
||||
mr_pin_close,
|
||||
mr_pin_read,
|
||||
mr_pin_write,
|
||||
mr_pin_ioctl,
|
||||
mr_pin_isr};
|
||||
|
||||
MR_ASSERT(pin != MR_NULL);
|
||||
MR_ASSERT(path != MR_NULL);
|
||||
@@ -151,8 +191,7 @@ int mr_pin_register(struct mr_pin *pin, const char *path, struct mr_drv *drv)
|
||||
|
||||
/* Register the pin */
|
||||
int ret = mr_dev_register(&pin->dev, path, MR_DEV_TYPE_PIN, MR_O_RDWR, &ops, drv);
|
||||
if (ret == MR_EOK)
|
||||
{
|
||||
if (ret == MR_EOK) {
|
||||
/* Initialize the fast pin */
|
||||
_mr_fast_pin_init(&pin->dev);
|
||||
}
|
||||
|
||||
372
device/serial.c
372
device/serial.c
@@ -10,22 +10,119 @@
|
||||
|
||||
#ifdef MR_USING_SERIAL
|
||||
|
||||
MR_INLINE ssize_t serial_poll_read(struct mr_serial *serial, uint8_t *buf, size_t count)
|
||||
{
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)serial->dev.drv->ops;
|
||||
ssize_t size;
|
||||
|
||||
for (size = 0; size < count; size += sizeof(*buf)) {
|
||||
int ret = ops->read(serial, buf);
|
||||
if (ret < 0) {
|
||||
return (size == 0) ? ret : size;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
MR_INLINE ssize_t serial_poll_write(struct mr_serial *serial, uint8_t *buf, size_t count)
|
||||
{
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)serial->dev.drv->ops;
|
||||
ssize_t size;
|
||||
|
||||
for (size = 0; size < count; size += sizeof(*buf)) {
|
||||
int ret = ops->write(serial, *buf);
|
||||
if (ret < 0) {
|
||||
return (size == 0) ? ret : size;
|
||||
}
|
||||
buf++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef MR_USING_SERIAL_DMA
|
||||
MR_INLINE ssize_t serial_dma_write(struct mr_serial *serial, uint8_t *buf, size_t count)
|
||||
{
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)serial->dev.drv->ops;
|
||||
|
||||
if (serial->dma_wr_bufsz == 0) {
|
||||
if (serial->nonblock_state == MR_DISABLE) {
|
||||
ops->start_dma_tx(serial, buf, count);
|
||||
return (ssize_t)count;
|
||||
} else {
|
||||
return MR_EBUSY;
|
||||
}
|
||||
} else {
|
||||
if (serial->nonblock_state == MR_DISABLE) {
|
||||
if (count > serial->dma_wr_bufsz) {
|
||||
memcpy(serial->dma_wr_buf, buf, serial->dma_wr_bufsz);
|
||||
ops->start_dma_tx(serial, serial->dma_wr_buf, serial->dma_wr_bufsz);
|
||||
return (ssize_t)(serial->dma_wr_bufsz +
|
||||
mr_ringbuf_write(&serial->wr_fifo,
|
||||
buf + serial->dma_wr_bufsz,
|
||||
count - serial->dma_wr_bufsz));
|
||||
} else {
|
||||
memcpy(serial->dma_wr_buf, buf, count);
|
||||
ops->start_dma_tx(serial, serial->dma_wr_buf, count);
|
||||
return (ssize_t)count;
|
||||
}
|
||||
} else {
|
||||
return (ssize_t)mr_ringbuf_write(&serial->wr_fifo, buf, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MR_USING_SERIAL_DMA */
|
||||
|
||||
MR_INLINE ssize_t serial_nonblocking_write(struct mr_serial *serial, uint8_t *buf, size_t count)
|
||||
{
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)serial->dev.drv->ops;
|
||||
ssize_t size;
|
||||
|
||||
#ifdef MR_USING_SERIAL_DMA
|
||||
/* DMA sending */
|
||||
if ((ops->start_dma_tx != MR_NULL) && (ops->stop_dma_tx != MR_NULL)) {
|
||||
return serial_dma_write(serial, buf, count);
|
||||
}
|
||||
#endif /* MR_USING_SERIAL_DMA */
|
||||
|
||||
/* Interrupt sending */
|
||||
size = (ssize_t)mr_ringbuf_write(&serial->wr_fifo, buf, count);
|
||||
if ((size > 0) && (serial->nonblock_state == MR_DISABLE)) {
|
||||
ops->start_tx(serial);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int mr_serial_open(struct mr_dev *dev)
|
||||
{
|
||||
struct mr_serial *serial = (struct mr_serial *)dev;
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops;
|
||||
|
||||
int ret = mr_ringbuf_allocate(&serial->rd_fifo, serial->rd_bufsz);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = mr_ringbuf_allocate(&serial->wr_fifo, serial->wr_bufsz);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef MR_USING_SERIAL_DMA
|
||||
serial->dma_rd_buf = (uint8_t *)mr_malloc(serial->dma_rd_bufsz);
|
||||
if ((serial->dma_rd_buf == MR_NULL) && (serial->dma_rd_bufsz != 0)) {
|
||||
return MR_ENOMEM;
|
||||
}
|
||||
serial->dma_wr_buf = (uint8_t *)mr_malloc(serial->dma_wr_bufsz);
|
||||
if ((serial->dma_wr_buf == MR_NULL) && (serial->dma_wr_bufsz != 0)) {
|
||||
return MR_ENOMEM;
|
||||
}
|
||||
|
||||
/* Configure DMA */
|
||||
if ((ops->start_dma_rx != MR_NULL) && (serial->dma_rd_bufsz != 0)) {
|
||||
ops->start_dma_rx(serial, serial->dma_rd_buf, serial->dma_rd_bufsz);
|
||||
}
|
||||
#endif /* MR_USING_SERIAL_DMA */
|
||||
|
||||
return ops->configure(serial, &serial->config);
|
||||
}
|
||||
|
||||
@@ -38,29 +135,23 @@ static int mr_serial_close(struct mr_dev *dev)
|
||||
mr_ringbuf_free(&serial->rd_fifo);
|
||||
mr_ringbuf_free(&serial->wr_fifo);
|
||||
|
||||
#ifdef MR_USING_SERIAL_DMA
|
||||
mr_free(serial->dma_rd_buf);
|
||||
mr_free(serial->dma_wr_buf);
|
||||
#endif /* MR_USING_SERIAL_DMA */
|
||||
|
||||
return ops->configure(serial, &close_config);
|
||||
}
|
||||
|
||||
static ssize_t mr_serial_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
{
|
||||
struct mr_serial *serial = (struct mr_serial *)dev;
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops;
|
||||
uint8_t *rd_buf = (uint8_t *)buf;
|
||||
ssize_t rd_size;
|
||||
|
||||
if (mr_ringbuf_get_bufsz(&serial->rd_fifo) == 0)
|
||||
{
|
||||
for (rd_size = 0; rd_size < count; rd_size += sizeof(*rd_buf))
|
||||
{
|
||||
int ret = ops->read(serial, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (rd_size == 0) ? ret : rd_size;
|
||||
}
|
||||
rd_buf++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (mr_ringbuf_get_bufsz(&serial->rd_fifo) == 0) {
|
||||
rd_size = serial_poll_read(serial, rd_buf, count);
|
||||
} else {
|
||||
rd_size = (ssize_t)mr_ringbuf_read(&serial->rd_fifo, buf, count);
|
||||
}
|
||||
return rd_size;
|
||||
@@ -69,29 +160,13 @@ static ssize_t mr_serial_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
static ssize_t mr_serial_write(struct mr_dev *dev, const void *buf, size_t count)
|
||||
{
|
||||
struct mr_serial *serial = (struct mr_serial *)dev;
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops;
|
||||
uint8_t *wr_buf = (uint8_t *)buf;
|
||||
ssize_t wr_size;
|
||||
|
||||
if (dev->sync == MR_SYNC)
|
||||
{
|
||||
for (wr_size = 0; wr_size < count; wr_size += sizeof(*wr_buf))
|
||||
{
|
||||
int ret = ops->write(serial, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (wr_size == 0) ? ret : wr_size;
|
||||
}
|
||||
wr_buf++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
wr_size = (ssize_t)mr_ringbuf_write(&serial->wr_fifo, buf, count);
|
||||
if (wr_size > 0)
|
||||
{
|
||||
/* Start interrupt sending */
|
||||
ops->start_tx(serial);
|
||||
}
|
||||
if (dev->sync == MR_SYNC) {
|
||||
wr_size = serial_poll_write(serial, wr_buf, count);
|
||||
} else {
|
||||
wr_size = serial_nonblocking_write(serial, wr_buf, count);
|
||||
}
|
||||
return wr_size;
|
||||
}
|
||||
@@ -101,17 +176,13 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
struct mr_serial *serial = (struct mr_serial *)dev;
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MR_IOC_SERIAL_SET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MR_IOC_SERIAL_SET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_serial_config config = *(struct mr_serial_config *)args;
|
||||
|
||||
int ret = ops->configure(serial, &config);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
serial->config = config;
|
||||
@@ -119,16 +190,13 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_SET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SERIAL_SET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t bufsz = *(size_t *)args;
|
||||
|
||||
int ret = mr_ringbuf_allocate(&serial->rd_fifo, bufsz);
|
||||
serial->rd_bufsz = 0;
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
serial->rd_bufsz = bufsz;
|
||||
@@ -136,16 +204,13 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_SET_WR_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SERIAL_SET_WR_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t bufsz = *(size_t *)args;
|
||||
|
||||
int ret = mr_ringbuf_allocate(&serial->wr_fifo, bufsz);
|
||||
serial->wr_bufsz = 0;
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
serial->wr_bufsz = bufsz;
|
||||
@@ -153,20 +218,16 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_CLR_RD_BUF:
|
||||
{
|
||||
case MR_IOC_SERIAL_CLR_RD_BUF: {
|
||||
mr_ringbuf_reset(&serial->rd_fifo);
|
||||
return MR_EOK;
|
||||
}
|
||||
case MR_IOC_SERIAL_CLR_WR_BUF:
|
||||
{
|
||||
case MR_IOC_SERIAL_CLR_WR_BUF: {
|
||||
mr_ringbuf_reset(&serial->wr_fifo);
|
||||
return MR_EOK;
|
||||
}
|
||||
case MR_IOC_SERIAL_GET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SERIAL_GET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_serial_config *config = (struct mr_serial_config *)args;
|
||||
|
||||
*config = serial->config;
|
||||
@@ -174,10 +235,8 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_GET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SERIAL_GET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *bufsz = (size_t *)args;
|
||||
|
||||
*bufsz = serial->rd_bufsz;
|
||||
@@ -185,10 +244,8 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_GET_WR_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SERIAL_GET_WR_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *bufsz = (size_t *)args;
|
||||
|
||||
*bufsz = serial->wr_bufsz;
|
||||
@@ -196,10 +253,8 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_GET_RD_DATASZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SERIAL_GET_RD_DATASZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *datasz = (size_t *)args;
|
||||
|
||||
*datasz = mr_ringbuf_get_data_size(&serial->rd_fifo);
|
||||
@@ -207,10 +262,8 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_GET_WR_DATASZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SERIAL_GET_WR_DATASZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *datasz = (size_t *)args;
|
||||
|
||||
*datasz = mr_ringbuf_get_data_size(&serial->wr_fifo);
|
||||
@@ -218,8 +271,64 @@ static int mr_serial_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
default:
|
||||
{
|
||||
#ifdef MR_USING_SERIAL_DMA
|
||||
case MR_IOC_SERIAL_SET_RD_DMA_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t bufsz = *(size_t *)args;
|
||||
|
||||
if (ops->stop_dma_rx) {
|
||||
return MR_EIO;
|
||||
}
|
||||
ops->stop_dma_rx(serial);
|
||||
|
||||
uint8_t *pool = mr_realloc(serial->dma_rd_buf, bufsz);
|
||||
if ((pool == MR_NULL) && (bufsz != 0)) {
|
||||
return MR_ENOMEM;
|
||||
}
|
||||
serial->dma_rd_buf = pool;
|
||||
serial->dma_rd_bufsz = bufsz;
|
||||
|
||||
if ((ops->start_dma_rx != MR_NULL) && (serial->dma_rd_bufsz != 0)) {
|
||||
ops->start_dma_rx(serial, serial->dma_rd_buf, serial->dma_rd_bufsz);
|
||||
}
|
||||
return sizeof(bufsz);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_SET_WR_DMA_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t bufsz = *(size_t *)args;
|
||||
|
||||
uint8_t *pool = mr_realloc(serial->dma_wr_buf, bufsz);
|
||||
if ((pool == MR_NULL) && (bufsz != 0)) {
|
||||
return MR_ENOMEM;
|
||||
}
|
||||
serial->dma_wr_buf = pool;
|
||||
serial->dma_wr_bufsz = bufsz;
|
||||
return sizeof(bufsz);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_GET_RD_DMA_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *bufsz = (size_t *)args;
|
||||
|
||||
*bufsz = serial->dma_rd_bufsz;
|
||||
return sizeof(*bufsz);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SERIAL_GET_WR_DMA_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *bufsz = (size_t *)args;
|
||||
|
||||
*bufsz = serial->dma_wr_bufsz;
|
||||
return sizeof(*bufsz);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
#endif /* MR_USING_SERIAL_DMA */
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -230,39 +339,67 @@ static ssize_t mr_serial_isr(struct mr_dev *dev, int event, void *args)
|
||||
struct mr_serial *serial = (struct mr_serial *)dev;
|
||||
struct mr_serial_ops *ops = (struct mr_serial_ops *)dev->drv->ops;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MR_ISR_SERIAL_RD_INT:
|
||||
{
|
||||
switch (event) {
|
||||
case MR_ISR_SERIAL_RD_INT: {
|
||||
uint8_t data;
|
||||
|
||||
/* Read data to FIFO */
|
||||
int ret = ops->read(serial, &data);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
mr_ringbuf_push_force(&serial->rd_fifo, data);
|
||||
|
||||
return (ssize_t)mr_ringbuf_get_data_size(&serial->rd_fifo);
|
||||
return MR_EOK;
|
||||
}
|
||||
case MR_ISR_SERIAL_WR_INT:
|
||||
{
|
||||
case MR_ISR_SERIAL_WR_INT: {
|
||||
uint8_t data;
|
||||
|
||||
/* Write data from FIFO, if FIFO is empty, stop transmit */
|
||||
if (mr_ringbuf_pop(&serial->wr_fifo, &data) == sizeof(data))
|
||||
{
|
||||
if (mr_ringbuf_pop(&serial->wr_fifo, &data) == sizeof(data)) {
|
||||
ops->write(serial, data);
|
||||
return MR_EBUSY;
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
serial->nonblock_state = MR_DISABLE;
|
||||
ops->stop_tx(serial);
|
||||
return MR_EOK;
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
#ifdef MR_USING_SERIAL_DMA
|
||||
case MR_ISR_SERIAL_RD_DMA: {
|
||||
if (args != MR_NULL) {
|
||||
size_t dma_rx_datasz = *(size_t *)args;
|
||||
|
||||
mr_ringbuf_write_force(&serial->rd_fifo,
|
||||
serial->dma_rd_buf,
|
||||
MR_BOUND(dma_rx_datasz, 0, serial->dma_rd_bufsz));
|
||||
if (ops->start_dma_rx != MR_NULL) {
|
||||
ops->start_dma_rx(serial, serial->dma_rd_buf, serial->dma_rd_bufsz);
|
||||
}
|
||||
return MR_EOK;
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_ISR_SERIAL_WR_DMA: {
|
||||
if (serial->dma_wr_bufsz == 0) {
|
||||
serial->nonblock_state = MR_DISABLE;
|
||||
ops->stop_dma_tx(serial);
|
||||
return MR_EOK;
|
||||
} else {
|
||||
size_t size = mr_ringbuf_read(&serial->wr_fifo,
|
||||
serial->dma_wr_buf,
|
||||
serial->dma_wr_bufsz);
|
||||
if (size != 0) {
|
||||
ops->start_dma_tx(serial, serial->dma_wr_buf, size);
|
||||
return MR_EBUSY;
|
||||
} else {
|
||||
serial->nonblock_state = MR_DISABLE;
|
||||
ops->stop_dma_tx(serial);
|
||||
return MR_EOK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MR_USING_SERIAL_DMA */
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -279,15 +416,12 @@ static ssize_t mr_serial_isr(struct mr_dev *dev, int event, void *args)
|
||||
*/
|
||||
int mr_serial_register(struct mr_serial *serial, const char *path, struct mr_drv *drv)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
mr_serial_open,
|
||||
mr_serial_close,
|
||||
mr_serial_read,
|
||||
mr_serial_write,
|
||||
mr_serial_ioctl,
|
||||
mr_serial_isr
|
||||
};
|
||||
static struct mr_dev_ops ops = {mr_serial_open,
|
||||
mr_serial_close,
|
||||
mr_serial_read,
|
||||
mr_serial_write,
|
||||
mr_serial_ioctl,
|
||||
mr_serial_isr};
|
||||
struct mr_serial_config default_config = MR_SERIAL_CONFIG_DEFAULT;
|
||||
|
||||
MR_ASSERT(serial != MR_NULL);
|
||||
@@ -307,9 +441,27 @@ int mr_serial_register(struct mr_serial *serial, const char *path, struct mr_drv
|
||||
#endif /* MR_CFG_SERIAL_WR_BUFSZ */
|
||||
serial->rd_bufsz = MR_CFG_SERIAL_RD_BUFSZ;
|
||||
serial->wr_bufsz = MR_CFG_SERIAL_WR_BUFSZ;
|
||||
#ifdef MR_USING_SERIAL_DMA
|
||||
serial->dma_rd_buf = MR_NULL;
|
||||
serial->dma_wr_buf = MR_NULL;
|
||||
#ifndef MR_CFG_SERIAL_RD_DMA_BUFSZ
|
||||
#define MR_CFG_SERIAL_RD_DMA_BUFSZ (0)
|
||||
#endif /* MR_CFG_SERIAL_RD_DMA_BUFSZ */
|
||||
#ifndef MR_CFG_SERIAL_WR_DMA_BUFSZ
|
||||
#define MR_CFG_SERIAL_WR_DMA_BUFSZ (0)
|
||||
#endif /* MR_CFG_SERIAL_WR_DMA_BUFSZ */
|
||||
serial->dma_rd_bufsz = MR_CFG_SERIAL_RD_DMA_BUFSZ;
|
||||
serial->dma_wr_bufsz = MR_CFG_SERIAL_WR_DMA_BUFSZ;
|
||||
#endif /* MR_USING_SERIAL_DMA */
|
||||
serial->nonblock_state = MR_DISABLE;
|
||||
|
||||
/* Register the serial */
|
||||
return mr_dev_register(&serial->dev, path, MR_DEV_TYPE_SERIAL, MR_O_RDWR | MR_O_NONBLOCK, &ops, drv);
|
||||
return mr_dev_register(&serial->dev,
|
||||
path,
|
||||
MR_DEV_TYPE_SERIAL,
|
||||
MR_O_RDWR | MR_O_NONBLOCK,
|
||||
&ops,
|
||||
drv);
|
||||
}
|
||||
|
||||
#endif /* MR_USING_SERIAL */
|
||||
|
||||
231
device/spi.c
231
device/spi.c
@@ -36,8 +36,7 @@ static int mr_spi_bus_close(struct mr_dev *dev)
|
||||
struct mr_spi_config close_config = {0};
|
||||
|
||||
#ifdef MR_USING_PIN
|
||||
if (spi_bus->cs_desc >= 0)
|
||||
{
|
||||
if (spi_bus->cs_desc >= 0) {
|
||||
mr_dev_close(spi_bus->cs_desc);
|
||||
spi_bus->cs_desc = -1;
|
||||
}
|
||||
@@ -60,25 +59,22 @@ static ssize_t mr_spi_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
struct mr_spi_bus *spi_bus = (struct mr_spi_bus *)dev;
|
||||
struct mr_spi_bus_ops *ops = (struct mr_spi_bus_ops *)dev->drv->ops;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case MR_ISR_SPI_RD_INT:
|
||||
{
|
||||
switch (event) {
|
||||
case MR_ISR_SPI_RD_INT: {
|
||||
struct mr_spi_dev *spi_dev = (struct mr_spi_dev *)spi_bus->owner;
|
||||
uint8_t data;
|
||||
|
||||
/* Read data to FIFO */
|
||||
int ret = ops->read(spi_bus, &data);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
mr_ringbuf_write_force(&spi_dev->rd_fifo, &data, sizeof(data));
|
||||
|
||||
return (ssize_t)mr_ringbuf_get_data_size(&spi_dev->rd_fifo);;
|
||||
/* Call the spi-dev ISR */
|
||||
return mr_dev_isr(&spi_dev->dev, event, MR_NULL);
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -95,15 +91,12 @@ static ssize_t mr_spi_bus_isr(struct mr_dev *dev, int event, void *args)
|
||||
*/
|
||||
int mr_spi_bus_register(struct mr_spi_bus *spi_bus, const char *path, struct mr_drv *drv)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
mr_spi_bus_open,
|
||||
mr_spi_bus_close,
|
||||
mr_spi_bus_read,
|
||||
mr_spi_bus_write,
|
||||
MR_NULL,
|
||||
mr_spi_bus_isr
|
||||
};
|
||||
static struct mr_dev_ops ops = {mr_spi_bus_open,
|
||||
mr_spi_bus_close,
|
||||
mr_spi_bus_read,
|
||||
mr_spi_bus_write,
|
||||
MR_NULL,
|
||||
mr_spi_bus_isr};
|
||||
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
|
||||
|
||||
MR_ASSERT(spi_bus != MR_NULL);
|
||||
@@ -127,30 +120,24 @@ static void spi_dev_cs_configure(struct mr_spi_dev *spi_dev, int state)
|
||||
struct mr_spi_bus *spi_bus = (struct mr_spi_bus *)spi_dev->dev.parent;
|
||||
int desc = spi_bus->cs_desc, old_number = -1;
|
||||
|
||||
if (desc < 0)
|
||||
{
|
||||
if (desc < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spi_dev->cs_pin != -1)
|
||||
{
|
||||
if (spi_dev->cs_pin != -1) {
|
||||
/* Temporarily store the old number */
|
||||
mr_dev_ioctl(desc, MR_IOC_GPOS, &old_number);
|
||||
|
||||
/* Set the new number */
|
||||
mr_dev_ioctl(desc, MR_IOC_SPOS, MR_MAKE_LOCAL(int, spi_dev->cs_pin));
|
||||
if (state == MR_ENABLE)
|
||||
{
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
if (state == MR_ENABLE) {
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST) {
|
||||
mr_dev_ioctl(desc, MR_IOC_SCFG, MR_MAKE_LOCAL(int, MR_PIN_MODE_OUTPUT));
|
||||
mr_dev_write(desc, MR_MAKE_LOCAL(uint8_t, !spi_dev->cs_active), sizeof(uint8_t));
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
mr_dev_ioctl(desc, MR_IOC_SCFG, MR_MAKE_LOCAL(int, MR_PIN_MODE_NONE));
|
||||
}
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
mr_dev_ioctl(desc, MR_IOC_SCFG, MR_MAKE_LOCAL(int, MR_PIN_MODE_NONE));
|
||||
}
|
||||
|
||||
@@ -165,13 +152,14 @@ MR_INLINE void spi_dev_cs_set(struct mr_spi_dev *spi_dev, int state)
|
||||
#ifdef MR_USING_PIN
|
||||
struct mr_spi_bus *spi_bus = (struct mr_spi_bus *)spi_dev->dev.parent;
|
||||
|
||||
if (spi_bus->cs_desc < 0)
|
||||
{
|
||||
if (spi_bus->cs_desc < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the new state */
|
||||
mr_dev_write(spi_bus->cs_desc, MR_MAKE_LOCAL(uint8_t, !(state ^ spi_dev->cs_active)), sizeof(uint8_t));
|
||||
mr_dev_write(spi_bus->cs_desc,
|
||||
MR_MAKE_LOCAL(uint8_t, !(state ^ spi_dev->cs_active)),
|
||||
sizeof(uint8_t));
|
||||
#endif /* MR_USING_PIN */
|
||||
}
|
||||
|
||||
@@ -181,30 +169,25 @@ MR_INLINE int spi_dev_take_bus(struct mr_spi_dev *spi_dev)
|
||||
struct mr_spi_bus_ops *ops = (struct mr_spi_bus_ops *)spi_bus->dev.drv->ops;
|
||||
|
||||
/* Check if the bus is busy */
|
||||
if ((spi_bus->hold == MR_TRUE) && (spi_dev != spi_bus->owner))
|
||||
{
|
||||
if ((spi_bus->hold == MR_TRUE) && (spi_dev != spi_bus->owner)) {
|
||||
return MR_EBUSY;
|
||||
}
|
||||
|
||||
if (spi_dev != spi_bus->owner)
|
||||
{
|
||||
if (spi_dev != spi_bus->owner) {
|
||||
/* Reconfigure the bus */
|
||||
if (spi_dev->config.baud_rate != spi_bus->config.baud_rate
|
||||
|| spi_dev->config.host_slave != spi_bus->config.host_slave
|
||||
|| spi_dev->config.mode != spi_bus->config.mode
|
||||
|| spi_dev->config.bit_order != spi_bus->config.bit_order)
|
||||
{
|
||||
if (spi_dev->config.baud_rate != spi_bus->config.baud_rate ||
|
||||
spi_dev->config.host_slave != spi_bus->config.host_slave ||
|
||||
spi_dev->config.mode != spi_bus->config.mode ||
|
||||
spi_dev->config.bit_order != spi_bus->config.bit_order) {
|
||||
int ret = ops->configure(spi_bus, &spi_dev->config);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
spi_bus->config = spi_dev->config;
|
||||
spi_bus->owner = spi_dev;
|
||||
#ifdef MR_USING_PIN
|
||||
if ((spi_bus->cs_desc >= 0) && (spi_bus->config.host_slave == MR_SPI_HOST))
|
||||
{
|
||||
if ((spi_bus->cs_desc >= 0) && (spi_bus->config.host_slave == MR_SPI_HOST)) {
|
||||
mr_dev_ioctl(spi_bus->cs_desc, MR_IOC_SPOS, MR_MAKE_LOCAL(int, spi_dev->cs_pin));
|
||||
}
|
||||
#endif /* MR_USING_PIN */
|
||||
@@ -217,14 +200,12 @@ MR_INLINE int spi_dev_release_bus(struct mr_spi_dev *spi_dev)
|
||||
{
|
||||
struct mr_spi_bus *spi_bus = (struct mr_spi_bus *)spi_dev->dev.parent;
|
||||
|
||||
if (spi_dev != spi_bus->owner)
|
||||
{
|
||||
if (spi_dev != spi_bus->owner) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
|
||||
/* If it is a host, release the bus. The slave needs to hold the bus at all times */
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST) {
|
||||
spi_bus->hold = MR_FALSE;
|
||||
}
|
||||
return MR_EOK;
|
||||
@@ -244,43 +225,35 @@ static ssize_t spi_dev_transfer(struct mr_spi_dev *spi_dev,
|
||||
struct mr_spi_bus_ops *ops = (struct mr_spi_bus_ops *)spi_bus->dev.drv->ops;
|
||||
ssize_t tf_size;
|
||||
|
||||
if (rdwr == MR_SPI_RD)
|
||||
{
|
||||
for (tf_size = 0; tf_size < size; tf_size += sizeof(*rd_buf))
|
||||
{
|
||||
if (rdwr == MR_SPI_RD) {
|
||||
for (tf_size = 0; tf_size < size; tf_size += sizeof(*rd_buf)) {
|
||||
ops->write(spi_bus, 0);
|
||||
int ret = ops->read(spi_bus, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
rd_buf++;
|
||||
}
|
||||
} else if (rdwr == MR_SPI_WR)
|
||||
{
|
||||
for (tf_size = 0; tf_size < size; tf_size += sizeof(*wr_buf))
|
||||
{
|
||||
} else if (rdwr == MR_SPI_WR) {
|
||||
for (tf_size = 0; tf_size < size; tf_size += sizeof(*wr_buf)) {
|
||||
int ret = ops->write(spi_bus, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
ops->read(spi_bus, MR_MAKE_LOCAL(uint8_t, 0));
|
||||
wr_buf++;
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (tf_size = 0; tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_buf)); tf_size += sizeof(*wr_buf))
|
||||
{
|
||||
} else {
|
||||
for (tf_size = 0;
|
||||
tf_size < MR_ALIGN_DOWN(size, sizeof(*wr_buf));
|
||||
tf_size += sizeof(*wr_buf)) {
|
||||
int ret = ops->write(spi_bus, *wr_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
|
||||
ret = ops->read(spi_bus, rd_buf);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return (tf_size == 0) ? ret : tf_size;
|
||||
}
|
||||
rd_buf++;
|
||||
@@ -320,25 +293,21 @@ static ssize_t mr_spi_dev_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
struct mr_spi_dev *spi_dev = (struct mr_spi_dev *)dev;
|
||||
|
||||
ssize_t ret = spi_dev_take_bus(spi_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST) {
|
||||
spi_dev_cs_set(spi_dev, MR_ENABLE);
|
||||
|
||||
/* Send the address of the register that needs to be read */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
if (dev->position >= 0) {
|
||||
ret = spi_dev_transfer(spi_dev,
|
||||
MR_NULL,
|
||||
(uint8_t *)&dev->position,
|
||||
(spi_dev->config.reg_bits >> 3),
|
||||
MR_SPI_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
spi_dev_cs_set(spi_dev, MR_DISABLE);
|
||||
spi_dev_release_bus(spi_dev);
|
||||
return ret;
|
||||
@@ -347,8 +316,7 @@ static ssize_t mr_spi_dev_read(struct mr_dev *dev, void *buf, size_t count)
|
||||
|
||||
ret = spi_dev_transfer(spi_dev, buf, MR_NULL, count, MR_SPI_RD);
|
||||
spi_dev_cs_set(spi_dev, MR_DISABLE);
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
ret = (ssize_t)mr_ringbuf_read(&spi_dev->rd_fifo, buf, count);
|
||||
}
|
||||
|
||||
@@ -361,25 +329,21 @@ static ssize_t mr_spi_dev_write(struct mr_dev *dev, const void *buf, size_t coun
|
||||
struct mr_spi_dev *spi_dev = (struct mr_spi_dev *)dev;
|
||||
|
||||
ssize_t ret = spi_dev_take_bus(spi_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST) {
|
||||
spi_dev_cs_set(spi_dev, MR_ENABLE);
|
||||
|
||||
/* Send the address of the register that needs to be written */
|
||||
if (dev->position >= 0)
|
||||
{
|
||||
if (dev->position >= 0) {
|
||||
ret = spi_dev_transfer(spi_dev,
|
||||
MR_NULL,
|
||||
(uint8_t *)&dev->position,
|
||||
(spi_dev->config.reg_bits >> 3),
|
||||
MR_SPI_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
spi_dev_cs_set(spi_dev, MR_DISABLE);
|
||||
spi_dev_release_bus(spi_dev);
|
||||
return ret;
|
||||
@@ -388,8 +352,7 @@ static ssize_t mr_spi_dev_write(struct mr_dev *dev, const void *buf, size_t coun
|
||||
|
||||
ret = spi_dev_transfer(spi_dev, MR_NULL, buf, count, MR_SPI_WR);
|
||||
spi_dev_cs_set(spi_dev, MR_DISABLE);
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
ret = spi_dev_transfer(spi_dev, MR_NULL, buf, count, MR_SPI_WR);
|
||||
}
|
||||
|
||||
@@ -401,38 +364,31 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
{
|
||||
struct mr_spi_dev *spi_dev = (struct mr_spi_dev *)dev;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MR_IOC_SPI_SET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MR_IOC_SPI_SET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_spi_bus *spi_bus = (struct mr_spi_bus *)dev->parent;
|
||||
struct mr_spi_config config = *(struct mr_spi_config *)args;
|
||||
|
||||
#ifdef MR_USING_PIN
|
||||
/* Reconfigure CS */
|
||||
if (config.host_slave != spi_dev->config.host_slave)
|
||||
{
|
||||
if (config.host_slave != spi_dev->config.host_slave) {
|
||||
spi_dev->config = config;
|
||||
spi_dev_cs_configure(spi_dev, MR_ENABLE);
|
||||
}
|
||||
#endif /* MR_USING_PIN */
|
||||
|
||||
/* If holding the bus, release it */
|
||||
if (spi_dev == spi_bus->owner)
|
||||
{
|
||||
if (spi_dev == spi_bus->owner) {
|
||||
spi_bus->hold = MR_FALSE;
|
||||
spi_bus->owner = MR_NULL;
|
||||
}
|
||||
|
||||
/* Update the configuration and try again to get the bus */
|
||||
spi_dev->config = config;
|
||||
if (config.host_slave == MR_SPI_SLAVE)
|
||||
{
|
||||
if (config.host_slave == MR_SPI_SLAVE) {
|
||||
int ret = spi_dev_take_bus(spi_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -440,16 +396,13 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SPI_SET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SPI_SET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t bufsz = *(size_t *)args;
|
||||
|
||||
int ret = mr_ringbuf_allocate(&spi_dev->rd_fifo, bufsz);
|
||||
spi_dev->rd_bufsz = 0;
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
spi_dev->rd_bufsz = bufsz;
|
||||
@@ -457,25 +410,20 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SPI_CLR_RD_BUF:
|
||||
{
|
||||
case MR_IOC_SPI_CLR_RD_BUF: {
|
||||
mr_ringbuf_reset(&spi_dev->rd_fifo);
|
||||
return MR_EOK;
|
||||
}
|
||||
case MR_IOC_SPI_TRANSFER:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SPI_TRANSFER: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_spi_transfer transfer = *(struct mr_spi_transfer *)args;
|
||||
|
||||
int ret = spi_dev_take_bus(spi_dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST)
|
||||
{
|
||||
if (spi_dev->config.host_slave == MR_SPI_HOST) {
|
||||
spi_dev_cs_set(spi_dev, MR_ENABLE);
|
||||
ret = (int)spi_dev_transfer(dev->parent,
|
||||
transfer.rd_buf,
|
||||
@@ -483,8 +431,7 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
transfer.size,
|
||||
MR_SPI_RDWR);
|
||||
spi_dev_cs_set(spi_dev, MR_DISABLE);
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
ret = (int)spi_dev_transfer(dev->parent,
|
||||
transfer.rd_buf,
|
||||
transfer.wr_buf,
|
||||
@@ -497,10 +444,8 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SPI_GET_CONFIG:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SPI_GET_CONFIG: {
|
||||
if (args != MR_NULL) {
|
||||
struct mr_spi_config *config = (struct mr_spi_config *)args;
|
||||
|
||||
*config = spi_dev->config;
|
||||
@@ -508,10 +453,8 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SPI_GET_RD_BUFSZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SPI_GET_RD_BUFSZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *bufsz = (size_t *)args;
|
||||
|
||||
*bufsz = spi_dev->rd_bufsz;
|
||||
@@ -519,10 +462,8 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SPI_GET_RD_DATASZ:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_SPI_GET_RD_DATASZ: {
|
||||
if (args != MR_NULL) {
|
||||
size_t *datasz = (size_t *)args;
|
||||
|
||||
*datasz = mr_ringbuf_get_data_size(&spi_dev->rd_fifo);
|
||||
@@ -530,8 +471,7 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
@@ -549,15 +489,12 @@ static int mr_spi_dev_ioctl(struct mr_dev *dev, int cmd, void *args)
|
||||
*/
|
||||
int mr_spi_dev_register(struct mr_spi_dev *spi_dev, const char *path, int cs_pin, int cs_active)
|
||||
{
|
||||
static struct mr_dev_ops ops =
|
||||
{
|
||||
mr_spi_dev_open,
|
||||
mr_spi_dev_close,
|
||||
mr_spi_dev_read,
|
||||
mr_spi_dev_write,
|
||||
mr_spi_dev_ioctl,
|
||||
MR_NULL
|
||||
};
|
||||
static struct mr_dev_ops ops = {mr_spi_dev_open,
|
||||
mr_spi_dev_close,
|
||||
mr_spi_dev_read,
|
||||
mr_spi_dev_write,
|
||||
mr_spi_dev_ioctl,
|
||||
MR_NULL};
|
||||
struct mr_spi_config default_config = MR_SPI_CONFIG_DEFAULT;
|
||||
|
||||
MR_ASSERT(spi_dev != MR_NULL);
|
||||
|
||||
@@ -230,9 +230,6 @@ mr_dev_ioctl(ds, MR_IOC_GRBDSZ, &size);
|
||||
/* 定义回调函数 */
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* 获取缓冲区数据大小 */
|
||||
ssize_t data_size = *(ssize_t *)args;
|
||||
|
||||
/* 处理中断 */
|
||||
}
|
||||
void (*callback)(int desc, void *args);
|
||||
@@ -249,9 +246,6 @@ mr_dev_ioctl(ds, MR_IOC_I2C_GET_RD_CALL, &callback);
|
||||
/* 定义回调函数 */
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* 获取缓冲区数据大小 */
|
||||
ssize_t data_size = *(ssize_t *)args;
|
||||
|
||||
/* 处理中断 */
|
||||
}
|
||||
void (*callback)(int desc, void *args);
|
||||
|
||||
@@ -37,7 +37,7 @@ int mr_i2c_dev_register(struct mr_i2c_dev *i2c_dev, const char *path, int addr,
|
||||
| `=0` | Registration succeeds |
|
||||
| `<0` | Error code |
|
||||
|
||||
- `name`: The I2C device needs to bind to the specified I2C bus, and the name needs to add the bus name, such
|
||||
- `name`: The I2C device needs to bind to the specified I2C spi_bus, and the name needs to add the spi_bus name, such
|
||||
as: `i2cx/dev-name`, `i2c1/i2c10`.
|
||||
- `addr`: Device address (the lowest bit is read/write bit, please pass the address shifted to the left).
|
||||
When serving as a host, the address is the peer's address. When serving as a slave, the address is its own address.
|
||||
@@ -142,7 +142,7 @@ Note:
|
||||
- Baud rate: `100000`
|
||||
- Master/slave mode: `MR_I2C_HOST`
|
||||
- Register bits: `MR_I2C_REG_BITS_8`
|
||||
- When an I2C device on the I2C bus is configured to slave mode, it will continuously occupy the I2C bus. At this point,
|
||||
- When an I2C device on the I2C spi_bus is configured to slave mode, it will continuously occupy the I2C spi_bus. At this point,
|
||||
other I2C devices cannot perform read/write operations until the I2C device in slave mode is reconfigured to master
|
||||
mode.
|
||||
|
||||
@@ -237,9 +237,6 @@ mr_dev_ioctl(ds, MR_IOC_GRBDSZ, &size);
|
||||
/* Define callback function */
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* Get buffer data size */
|
||||
ssize_t data_size = *(ssize_t *)args;
|
||||
|
||||
/* Handle interrupt */
|
||||
}
|
||||
void (*callback)(int desc, void *args);
|
||||
@@ -256,9 +253,6 @@ Independent of I2C interface:
|
||||
/* Define callback function */
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* Get buffer data size */
|
||||
ssize_t data_size = *(ssize_t *)args;
|
||||
|
||||
/* Handle interrupt */
|
||||
}
|
||||
void (*callback)(int desc, void *args);
|
||||
@@ -441,7 +435,7 @@ int mr_soft_i2c_bus_register(struct mr_soft_i2c_bus *soft_i2c_bus, const char *p
|
||||
|
||||
| Parameter | Description |
|
||||
|------------------|------------------------------------|
|
||||
| soft_i2c_bus | Software I2C bus structure pointer |
|
||||
| soft_i2c_bus | Software I2C spi_bus structure pointer |
|
||||
| path | Bus path |
|
||||
| scl_pin | SCL pin number |
|
||||
| sda_pin | SDA pin number |
|
||||
@@ -450,17 +444,17 @@ int mr_soft_i2c_bus_register(struct mr_soft_i2c_bus *soft_i2c_bus, const char *p
|
||||
| `<0` | Error code |
|
||||
|
||||
```c
|
||||
/* Define SCL, SDA pin numbers for software I2C bus */
|
||||
/* Define SCL, SDA pin numbers for software I2C spi_bus */
|
||||
#define SCL_PIN_NUMBER 0
|
||||
#define SDA_PIN_NUMBER 1
|
||||
|
||||
/* Define software I2C bus */
|
||||
/* Define software I2C spi_bus */
|
||||
struct mr_soft_i2c_bus soft_i2c_bus;
|
||||
|
||||
/* Register software I2C bus */
|
||||
/* Register software I2C spi_bus */
|
||||
mr_soft_i2c_bus_register(&soft_i2c_bus, "i2c1", SCL_PIN_NUMBER, SDA_PIN_NUMBER);
|
||||
```
|
||||
|
||||
After registration, the software I2C bus will simulate a hardware I2C.
|
||||
After registration, the software I2C spi_bus will simulate a hardware I2C.
|
||||
|
||||
Note: The software I2C bus only supports master mode.
|
||||
Note: The software I2C spi_bus only supports master mode.
|
||||
|
||||
@@ -71,6 +71,7 @@ int mr_dev_ioctl(int desc, int cmd, void *args);
|
||||
- `MR_IOC_PIN_SET_MODE`:设置引脚模式。
|
||||
- `MR_IOC_PIN_SET_EXTI_CALL`:设置外部中断回调函数。
|
||||
- `MR_IOC_PIN_GET_NUMBER`:获取引脚编号。
|
||||
- `MR_IOC_PIN_GET_MODE`:获取引脚模式。
|
||||
- `MR_IOC_PIN_GET_EXTI_CALL`:获取外部中断回调函数。
|
||||
|
||||
### 设置/获取引脚编号
|
||||
@@ -110,7 +111,7 @@ int number;
|
||||
mr_dev_ioctl(ds, MR_IOC_GPOS, &number);
|
||||
```
|
||||
|
||||
### 设置引脚模式
|
||||
### 设置/获取引脚模式
|
||||
|
||||
#### 引脚模式
|
||||
|
||||
@@ -137,6 +138,10 @@ mr_dev_ioctl(ds, MR_IOC_GPOS, &number);
|
||||
|
||||
/* 设置引脚模式 */
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
|
||||
/* 获取引脚模式 */
|
||||
int mode;
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_GET_MODE, &mode);
|
||||
```
|
||||
|
||||
不依赖PIN接口:
|
||||
@@ -147,6 +152,10 @@ mr_dev_ioctl(ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
|
||||
/* 设置引脚模式 */
|
||||
mr_dev_ioctl(ds, MR_IOC_SCFG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
|
||||
/* 获取引脚模式 */
|
||||
int mode;
|
||||
mr_dev_ioctl(ds, MR_IOC_GCFG, &mode);
|
||||
```
|
||||
|
||||
### 设置/获取外部中断回调函数
|
||||
@@ -157,7 +166,7 @@ mr_dev_ioctl(ds, MR_IOC_SCFG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* 获取引脚编号 */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
int number = *(int *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* 处理外部中断事件 */
|
||||
@@ -180,7 +189,7 @@ mr_dev_ioctl(ds, MR_IOC_PIN_GET_EXTI_CALL, &callback);
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* 获取引脚编号 */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
int number = *(int *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* 处理外部中断事件 */
|
||||
@@ -268,7 +277,7 @@ int key_ds = -1;
|
||||
|
||||
void key_call(int desc, void *args)
|
||||
{
|
||||
ssize_t number = *((ssize_t *)args);
|
||||
int number = *((int *)args);
|
||||
|
||||
if (number == KEY_PIN_NUMBER)
|
||||
{
|
||||
|
||||
@@ -73,6 +73,7 @@ int mr_dev_ioctl(int desc, int cmd, void *args);
|
||||
- `MR_IOC_PIN_SET_MODE`: Set pin mode
|
||||
- `MR_IOC_PIN_SET_EXTI_CALL`: Set external interrupt callback function
|
||||
- `MR_IOC_PIN_GET_NUMBER`: Get pin number
|
||||
- `MR_IOC_PIN_GET_MODE`: Get pin mode
|
||||
- `MR_IOC_PIN_GET_EXTI_CALL`: Get external interrupt callback function
|
||||
|
||||
### Set/Get Pin Number
|
||||
@@ -141,6 +142,10 @@ And 5 external interrupt modes:
|
||||
|
||||
/* Set pin mode */
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_SET_MODE, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
|
||||
/* Get pin mode */
|
||||
int mode;
|
||||
mr_dev_ioctl(ds, MR_IOC_PIN_GET_MODE, &mode);
|
||||
```
|
||||
|
||||
Independent of PIN interface:
|
||||
@@ -151,6 +156,10 @@ Independent of PIN interface:
|
||||
|
||||
/* Set pin mode */
|
||||
mr_dev_ioctl(ds, MR_IOC_SCFG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
|
||||
/* Get pin mode */
|
||||
int mode;
|
||||
mr_dev_ioctl(ds, MR_IOC_GCFG, &mode);
|
||||
```
|
||||
|
||||
### Set/Get External Interrupt Callback Function
|
||||
@@ -161,7 +170,7 @@ mr_dev_ioctl(ds, MR_IOC_SCFG, MR_MAKE_LOCAL(int, PIN_MODE));
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* Get pin number */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
int number = *(int *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* Handle external interrupt event */
|
||||
@@ -184,7 +193,7 @@ Independent of PIN interface:
|
||||
void fn(int desc, void *args)
|
||||
{
|
||||
/* Get pin number */
|
||||
ssize_t number = *(ssize_t *)args;
|
||||
int number = *(int *)args;
|
||||
if (number == PIN_NUMBER)
|
||||
{
|
||||
/* Handle external interrupt event */
|
||||
@@ -272,7 +281,7 @@ int key_ds = -1;
|
||||
|
||||
void key_call(int desc, void *args)
|
||||
{
|
||||
ssize_t number = *((ssize_t *)args);
|
||||
int number = *((int *)args);
|
||||
|
||||
if (number == KEY_PIN_NUMBER)
|
||||
{
|
||||
|
||||
@@ -17,12 +17,26 @@ extern "C" {
|
||||
|
||||
#ifdef MR_USING_CAN
|
||||
|
||||
/**
|
||||
* @addtogroup CAN
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief CAN mode.
|
||||
*/
|
||||
#define MR_CAN_MODE_NORMAL (0) /**< Normal mode */
|
||||
#define MR_CAN_MODE_LOOPBACK (1) /**< Loopback mode */
|
||||
#define MR_CAN_MODE_SILENT (2) /**< Silent mode */
|
||||
#define MR_CAN_MODE_SILENT_LOOPBACK (3) /**< Silent loopback mode */
|
||||
|
||||
/**
|
||||
* @brief CAN default configuration.
|
||||
*/
|
||||
#define MR_CAN_CONFIG_DEFAULT \
|
||||
{ \
|
||||
500000, \
|
||||
MR_CAN_MODE_NORMAL, \
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,32 +45,22 @@ extern "C" {
|
||||
struct mr_can_config
|
||||
{
|
||||
uint32_t baud_rate; /**< Baud rate */
|
||||
int mode; /**< Mode */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief CAN identifier.
|
||||
*/
|
||||
#define MR_CAN_IDE_STD (0 << 29)
|
||||
#define MR_CAN_IDE_EXT (1 << 29)
|
||||
|
||||
/**
|
||||
* @brief CAN remote transmission request.
|
||||
*/
|
||||
#define MR_CAN_RTR_DATA (0 << 30)
|
||||
#define MR_CAN_RTR_REMOTE (1 << 30)
|
||||
|
||||
/**
|
||||
* @brief Help to set id.
|
||||
*/
|
||||
#define MR_CAN_ID(id, ide, rtr) ((id) | (ide) | (rtr)) /**< Set id-ide-rtr */
|
||||
|
||||
/**
|
||||
* @brief CAN control command.
|
||||
*/
|
||||
#define MR_CTL_CAN_SET_ID MR_CTL_SET_OFFSET /**< Set id */
|
||||
#define MR_CTL_CAN_GET_ID MR_CTL_GET_OFFSET /**< Get id */
|
||||
#define MR_CTL_CAN_SET_RD_CALL MR_CTL_SET_RD_CALL /**< Set read call */
|
||||
#define MR_CTL_CAN_GET_RD_CALL MR_CTL_GET_RD_CALL /**< Get read call */
|
||||
#define MR_IOC_CAN_SET_CONFIG MR_IOC_SCFG /**< Set configuration command */
|
||||
#define MR_IOC_CAN_SET_RD_BUFSZ MR_IOC_SRBSZ /**< Set read buffer size command */
|
||||
#define MR_IOC_CAN_CLR_RD_BUF MR_IOC_CRBD /**< Clear read buffer command */
|
||||
#define MR_IOC_CAN_SET_RD_CALL MR_IOC_SRCB /**< Set read callback command */
|
||||
#define MR_IOC_CAN_REMOTE_REQUEST (0x01) /**< Remote request command */
|
||||
|
||||
#define MR_IOC_CAN_GET_CONFIG MR_IOC_GCFG /**< Get configuration command */
|
||||
#define MR_IOC_CAN_GET_RD_BUFSZ MR_IOC_GRBSZ /**< Get read buffer size command */
|
||||
#define MR_IOC_CAN_GET_RD_DATASZ MR_IOC_GRBDSZ /**< Get read data size command */
|
||||
#define MR_IOC_CAN_GET_RD_CALL MR_IOC_GRCB /**< Get read callback command */
|
||||
|
||||
/**
|
||||
* @brief CAN data type.
|
||||
@@ -66,7 +70,7 @@ typedef uint8_t mr_can_data_t; /**< CAN rea
|
||||
/**
|
||||
* @brief CAN ISR events.
|
||||
*/
|
||||
#define MR_ISR_CAN_RD_INT (MR_ISR_RD | (0x01 << 8)) /**< Read interrupt */
|
||||
#define MR_ISR_CAN_RD_INT (MR_ISR_RD | (0x01 << 8)) /**< Read interrupt event */
|
||||
|
||||
/**
|
||||
* @brief CAN bus structure.
|
||||
@@ -87,39 +91,35 @@ struct mr_can_bus_ops
|
||||
{
|
||||
int (*configure)(struct mr_can_bus *can_bus, struct mr_can_config *config);
|
||||
int (*filter_configure)(struct mr_can_bus *can_bus, int id, int ide, int state);
|
||||
int (*get_id)(struct mr_can_bus *can_bus);
|
||||
ssize_t (*read)(struct mr_can_bus *can_bus, uint8_t *buf, size_t size);
|
||||
ssize_t (*write)(struct mr_can_bus *can_bus, int id, int ide, int rtr, const uint8_t *buf, size_t size);
|
||||
int (*read)(struct mr_can_bus *can_bus, int *id, int *ide, int *rtr, uint8_t *buf, size_t size);
|
||||
ssize_t (*write)(struct mr_can_bus *can_bus, int id, int ide, const uint8_t *buf, size_t size);
|
||||
int (*remote_request)(struct mr_can_bus *can_bus, int id, int ide);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief CAN id identifier.
|
||||
* @brief CAN ID type.
|
||||
*/
|
||||
#define MR_CAN_ID_STD (0) /**< Standard identifier */
|
||||
#define MR_CAN_ID_EXT (1) /**< Extended identifier */
|
||||
#define MR_CAN_IDE_STD (0) /**< Standard ID */
|
||||
#define MR_CAN_IDE_EXT (1) /**< Extended ID */
|
||||
|
||||
/**
|
||||
* @brief CAN device structure.
|
||||
*/
|
||||
struct mr_can_dev
|
||||
{
|
||||
struct mr_dev dev;
|
||||
struct mr_dev dev; /**< Device structure */
|
||||
|
||||
struct mr_can_config config;
|
||||
struct mr_ringbuf rd_fifo;
|
||||
size_t rd_bufsz;
|
||||
uint32_t id: 29;
|
||||
uint32_t ide: 1;
|
||||
uint32_t reserved: 2;
|
||||
struct mr_can_config config; /**< Configuration */
|
||||
struct mr_ringbuf rd_fifo; /**< Read FIFO */
|
||||
size_t rd_bufsz; /**< Read buffer size */
|
||||
int id; /**< ID */
|
||||
int ide; /**< ID type */
|
||||
};
|
||||
|
||||
/**
|
||||
* @addtogroup CAN.
|
||||
* @{
|
||||
*/
|
||||
int mr_can_bus_register(struct mr_can_bus *can_bus, const char *name, struct mr_drv *drv);
|
||||
int mr_can_dev_register(struct mr_can_dev *can_dev, const char *name, int id, int ide);
|
||||
int mr_can_bus_register(struct mr_can_bus *can_bus, const char *path, struct mr_drv *drv);
|
||||
int mr_can_dev_register(struct mr_can_dev *can_dev, const char *path, int id, int ide);
|
||||
/** @} */
|
||||
|
||||
#endif /* MR_USING_CAN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -35,11 +35,11 @@ extern "C" {
|
||||
/**
|
||||
* @brief PIN mode-interrupt.
|
||||
*/
|
||||
#define MR_PIN_MODE_IRQ_RISING (6) /**< Interrupt rising edge */
|
||||
#define MR_PIN_MODE_IRQ_FALLING (7) /**< Interrupt falling edge */
|
||||
#define MR_PIN_MODE_IRQ_EDGE (8) /**< Interrupt edge */
|
||||
#define MR_PIN_MODE_IRQ_LOW (9) /**< Interrupt low level */
|
||||
#define MR_PIN_MODE_IRQ_HIGH (10) /**< Interrupt high level */
|
||||
#define MR_PIN_MODE_IRQ_RISING (6) /**< Interrupt rising edge mode */
|
||||
#define MR_PIN_MODE_IRQ_FALLING (7) /**< Interrupt falling edge mode */
|
||||
#define MR_PIN_MODE_IRQ_EDGE (8) /**< Interrupt edge mode */
|
||||
#define MR_PIN_MODE_IRQ_LOW (9) /**< Interrupt low level mode */
|
||||
#define MR_PIN_MODE_IRQ_HIGH (10) /**< Interrupt high level mode */
|
||||
|
||||
/**
|
||||
* @brief PIN configuration structure.
|
||||
@@ -57,6 +57,7 @@ struct mr_pin_config
|
||||
#define MR_IOC_PIN_SET_EXTI_CALL MR_IOC_SRCB /**< Set pin exti callback command */
|
||||
|
||||
#define MR_IOC_PIN_GET_NUMBER MR_IOC_GPOS /**< Get pin number command */
|
||||
#define MR_IOC_PIN_GET_MODE MR_IOC_GCFG /**< Get pin mode command */
|
||||
#define MR_IOC_PIN_GET_EXTI_CALL MR_IOC_GRCB /**< Get pin exti callback command */
|
||||
|
||||
/**
|
||||
@@ -67,7 +68,7 @@ typedef uint8_t mr_pin_data_t; /**< PIN rea
|
||||
/**
|
||||
* @brief PIN ISR events.
|
||||
*/
|
||||
#define MR_ISR_PIN_EXTI_INT (MR_ISR_RD | (0x01)) /**< Exti interrupt */
|
||||
#define MR_ISR_PIN_EXTI_INT (MR_ISR_RD | (0x01)) /**< Exti interrupt event */
|
||||
|
||||
/**
|
||||
* @brief PIN structure.
|
||||
@@ -75,6 +76,8 @@ typedef uint8_t mr_pin_data_t; /**< PIN rea
|
||||
struct mr_pin
|
||||
{
|
||||
struct mr_dev dev; /**< Device */
|
||||
|
||||
uint32_t pins[32]; /**< Pins */
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -89,6 +92,7 @@ struct mr_pin_ops
|
||||
|
||||
int mr_pin_register(struct mr_pin *pin, const char *path, struct mr_drv *drv);
|
||||
/** @} */
|
||||
|
||||
#endif /* MR_USING_PIN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
381
source/device.c
381
source/device.c
@@ -8,14 +8,8 @@
|
||||
|
||||
#include "include/mr_api.h"
|
||||
|
||||
static struct mr_dev root_dev = /**< Root device */
|
||||
{
|
||||
.name = "dev",
|
||||
.type = MR_DEV_TYPE_ROOT,
|
||||
.parent = MR_NULL,
|
||||
.list = MR_LIST_INIT(root_dev.list),
|
||||
.clist = MR_LIST_INIT(root_dev.clist)
|
||||
};
|
||||
static struct mr_dev root_dev = {.name = "dev", .type = MR_DEV_TYPE_ROOT, .parent = MR_NULL, .list = MR_LIST_INIT(
|
||||
root_dev.list), .clist = MR_LIST_INIT(root_dev.clist)}; /**< Root device */
|
||||
|
||||
#ifndef MR_CFG_DESC_NUM
|
||||
#define MR_CFG_DESC_NUM (32)
|
||||
@@ -38,11 +32,9 @@ MR_INLINE int dev_is_root(struct mr_dev *dev)
|
||||
|
||||
MR_INLINE struct mr_dev *dev_find_child(struct mr_dev *parent, const char *name)
|
||||
{
|
||||
for (struct mr_list *list = parent->clist.next; list != &parent->clist; list = list->next)
|
||||
{
|
||||
for (struct mr_list *list = parent->clist.next; list != &parent->clist; list = list->next) {
|
||||
struct mr_dev *dev = (struct mr_dev *)MR_CONTAINER_OF(list, struct mr_dev, list);
|
||||
if (strncmp(name, dev->name, MR_CFG_DEV_NAME_LEN) == 0)
|
||||
{
|
||||
if (strncmp(name, dev->name, MR_CFG_DEV_NAME_LEN) == 0) {
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
@@ -51,8 +43,7 @@ MR_INLINE struct mr_dev *dev_find_child(struct mr_dev *parent, const char *name)
|
||||
|
||||
MR_INLINE int dev_register_child(struct mr_dev *parent, struct mr_dev *child, const char *name)
|
||||
{
|
||||
if (dev_find_child(parent, name) != MR_NULL)
|
||||
{
|
||||
if (dev_find_child(parent, name) != MR_NULL) {
|
||||
return MR_EEXIST;
|
||||
}
|
||||
|
||||
@@ -65,15 +56,13 @@ MR_INLINE int dev_register_child(struct mr_dev *parent, struct mr_dev *child, co
|
||||
|
||||
static int dev_register_by_path(struct mr_dev *parent, struct mr_dev *dev, const char *path)
|
||||
{
|
||||
if (path[0] == '/')
|
||||
{
|
||||
if (path[0] == '/') {
|
||||
path++;
|
||||
}
|
||||
|
||||
/* Check for child path separator */
|
||||
const char *child_path = strchr(path, '/');
|
||||
if (child_path != MR_NULL)
|
||||
{
|
||||
if (child_path != MR_NULL) {
|
||||
char child_name[MR_CFG_DEV_NAME_LEN + 1] = {0};
|
||||
size_t len = MR_BOUND(child_path - path, 0, MR_CFG_DEV_NAME_LEN);
|
||||
|
||||
@@ -81,15 +70,13 @@ static int dev_register_by_path(struct mr_dev *parent, struct mr_dev *dev, const
|
||||
strncpy(child_name, path, len);
|
||||
child_name[len] = '\0';
|
||||
struct mr_dev *child = dev_find_child(parent, child_name);
|
||||
if (child == MR_NULL)
|
||||
{
|
||||
if (child == MR_NULL) {
|
||||
return MR_ENOTFOUND;
|
||||
}
|
||||
|
||||
/* Register recursively */
|
||||
return dev_register_by_path(child, dev, child_path);
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
/* Register with parent */
|
||||
return dev_register_child(parent, dev, path);
|
||||
}
|
||||
@@ -97,15 +84,13 @@ static int dev_register_by_path(struct mr_dev *parent, struct mr_dev *dev, const
|
||||
|
||||
static struct mr_dev *dev_find_by_path(struct mr_dev *parent, const char *path)
|
||||
{
|
||||
if (path[0] == '/')
|
||||
{
|
||||
if (path[0] == '/') {
|
||||
path++;
|
||||
}
|
||||
|
||||
/* Check for child path separator */
|
||||
const char *child_path = strchr(path, '/');
|
||||
if (child_path != MR_NULL)
|
||||
{
|
||||
if (child_path != MR_NULL) {
|
||||
char child_name[MR_CFG_DEV_NAME_LEN + 1] = {0};
|
||||
size_t len = MR_BOUND(child_path - path, 0, MR_CFG_DEV_NAME_LEN);
|
||||
|
||||
@@ -113,15 +98,13 @@ static struct mr_dev *dev_find_by_path(struct mr_dev *parent, const char *path)
|
||||
strncpy(child_name, path, len);
|
||||
child_name[len] = '\0';
|
||||
struct mr_dev *child = dev_find_child(parent, child_name);
|
||||
if (child == MR_NULL)
|
||||
{
|
||||
if (child == MR_NULL) {
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Find recursively */
|
||||
return dev_find_by_path(child, child_path);
|
||||
} else
|
||||
{
|
||||
} else {
|
||||
/* Find with parent */
|
||||
return dev_find_child(parent, path);
|
||||
}
|
||||
@@ -131,17 +114,14 @@ static struct mr_dev *dev_find_by_path(struct mr_dev *parent, const char *path)
|
||||
static int dev_lock_take(struct mr_dev *dev, uint32_t take, uint32_t set)
|
||||
{
|
||||
/* Continue iterating until reach the root device */
|
||||
if (dev_is_root(dev->parent) != MR_TRUE)
|
||||
{
|
||||
if (dev_is_root(dev->parent) != MR_TRUE) {
|
||||
int ret = dev_lock_take(dev->parent, take, set);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->lock & take)
|
||||
{
|
||||
if (dev->lock & take) {
|
||||
return MR_EBUSY;
|
||||
}
|
||||
MR_BIT_SET(dev->lock, set);
|
||||
@@ -151,8 +131,7 @@ static int dev_lock_take(struct mr_dev *dev, uint32_t take, uint32_t set)
|
||||
static void dev_lock_release(struct mr_dev *dev, uint32_t release)
|
||||
{
|
||||
/* Continue iterating until reach the root device */
|
||||
if (dev_is_root(dev->parent) != MR_TRUE)
|
||||
{
|
||||
if (dev_is_root(dev->parent) != MR_TRUE) {
|
||||
dev_lock_release(dev->parent, release);
|
||||
}
|
||||
|
||||
@@ -163,13 +142,12 @@ static void dev_lock_release(struct mr_dev *dev, uint32_t release)
|
||||
MR_INLINE struct mr_dev *dev_find(const char *path)
|
||||
{
|
||||
/* Check whether the path is absolute */
|
||||
if (*path == '/')
|
||||
{
|
||||
if (*path == '/') {
|
||||
path++;
|
||||
const char *next_slash = strchr(path, '/');
|
||||
if ((next_slash == MR_NULL) ||
|
||||
(strncmp(path, root_dev.name, MR_BOUND(next_slash - path, 0, MR_CFG_DEV_NAME_LEN)) != 0))
|
||||
{
|
||||
(strncmp(path, root_dev.name, MR_BOUND(next_slash - path, 0, MR_CFG_DEV_NAME_LEN)) !=
|
||||
0)) {
|
||||
return MR_NULL;
|
||||
}
|
||||
path += MR_BOUND(next_slash - path, 0, MR_CFG_DEV_NAME_LEN);
|
||||
@@ -182,13 +160,12 @@ MR_INLINE struct mr_dev *dev_find(const char *path)
|
||||
MR_INLINE int dev_register(struct mr_dev *dev, const char *path)
|
||||
{
|
||||
/* Check whether the path is absolute */
|
||||
if (*path == '/')
|
||||
{
|
||||
if (*path == '/') {
|
||||
path++;
|
||||
const char *next_slash = strchr(path, '/');
|
||||
if ((next_slash == MR_NULL) ||
|
||||
(strncmp(path, root_dev.name, MR_BOUND(next_slash - path, 0, MR_CFG_DEV_NAME_LEN)) != 0))
|
||||
{
|
||||
(strncmp(path, root_dev.name, MR_BOUND(next_slash - path, 0, MR_CFG_DEV_NAME_LEN)) !=
|
||||
0)) {
|
||||
return MR_EINVAL;
|
||||
}
|
||||
path += MR_BOUND(next_slash - path, 0, MR_CFG_DEV_NAME_LEN);
|
||||
@@ -201,87 +178,28 @@ MR_INLINE int dev_register(struct mr_dev *dev, const char *path)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dev_isr(struct mr_dev *dev, int event, void *args)
|
||||
{
|
||||
/* Call the all registered callbacks */
|
||||
switch (event)
|
||||
{
|
||||
case MR_ISR_RD:
|
||||
{
|
||||
for (struct mr_list *list = dev->rd_call_list.next; list != &dev->rd_call_list; list = list->next)
|
||||
{
|
||||
struct mr_dev_desc *desc = (struct mr_dev_desc *)MR_CONTAINER_OF(list,
|
||||
struct mr_dev_desc,
|
||||
rd_call.list);
|
||||
if (desc->rd_call.fn != MR_NULL)
|
||||
{
|
||||
desc->rd_call.fn((int)(desc - &desc_map[0]), args);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MR_ISR_WR:
|
||||
{
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
dev_lock_release(dev, MR_LOCK_NONBLOCK);
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
for (struct mr_list *list = dev->wr_call_list.next; list != &dev->wr_call_list; list = list->next)
|
||||
{
|
||||
struct mr_dev_desc *desc = (struct mr_dev_desc *)MR_CONTAINER_OF(list,
|
||||
struct mr_dev_desc,
|
||||
wr_call.list);
|
||||
if (desc->wr_call.fn != MR_NULL)
|
||||
{
|
||||
desc->wr_call.fn((int)(desc - &desc_map[0]), args);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wake up all child devices */
|
||||
for (struct mr_list *list = dev->clist.next; list != &dev->clist; list = list->next)
|
||||
{
|
||||
struct mr_dev *cdev = (struct mr_dev *)MR_CONTAINER_OF(list, struct mr_dev, list);
|
||||
|
||||
/* Handle recursively */
|
||||
dev_isr(cdev, event, args);
|
||||
}
|
||||
return MR_EOK;
|
||||
}
|
||||
|
||||
static int dev_open(struct mr_dev *dev, int flags)
|
||||
{
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
if (MR_BIT_IS_SET(dev->flags, flags) != MR_ENABLE)
|
||||
{
|
||||
if (MR_BIT_IS_SET(dev->flags, flags) != MR_ENABLE) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
|
||||
/* Check whether the device is opened */
|
||||
if (dev->ref_count == 0)
|
||||
{
|
||||
if (dev->ref_count == 0) {
|
||||
/* Continue iterating until reach the root device */
|
||||
if (dev_is_root(dev->parent) != MR_TRUE)
|
||||
{
|
||||
if (dev_is_root(dev->parent) != MR_TRUE) {
|
||||
int ret = dev_open(dev->parent, flags);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Open the device */
|
||||
if (dev->ops->open != MR_NULL)
|
||||
{
|
||||
if (dev->ops->open != MR_NULL) {
|
||||
int ret = dev->ops->open(dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -298,21 +216,17 @@ static int dev_close(struct mr_dev *dev)
|
||||
dev->ref_count--;
|
||||
|
||||
/* Check whether the device needs to be closed */
|
||||
if (dev->ref_count == 0)
|
||||
{
|
||||
if (dev->ref_count == 0) {
|
||||
/* Continue iterating until reach the root device */
|
||||
if (dev_is_root(dev->parent) != MR_TRUE)
|
||||
{
|
||||
if (dev_is_root(dev->parent) != MR_TRUE) {
|
||||
int ret = dev_close(dev->parent);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the device */
|
||||
if (dev->ops->close != MR_NULL)
|
||||
{
|
||||
if (dev->ops->close != MR_NULL) {
|
||||
return dev->ops->close(dev);
|
||||
}
|
||||
}
|
||||
@@ -322,12 +236,10 @@ static int dev_close(struct mr_dev *dev)
|
||||
MR_INLINE ssize_t dev_read(struct mr_dev *dev, int position, int sync, void *buf, size_t count)
|
||||
{
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
do
|
||||
{
|
||||
do {
|
||||
mr_interrupt_disable();
|
||||
int ret = dev_lock_take(dev, (MR_LOCK_RD | MR_LOCK_SLEEP), MR_LOCK_RD);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
mr_interrupt_enable();
|
||||
return ret;
|
||||
}
|
||||
@@ -348,17 +260,21 @@ MR_INLINE ssize_t dev_read(struct mr_dev *dev, int position, int sync, void *buf
|
||||
return ret;
|
||||
}
|
||||
|
||||
MR_INLINE ssize_t dev_write(struct mr_dev *dev, int position, int sync, const void *buf, size_t count)
|
||||
MR_INLINE ssize_t dev_write(struct mr_dev *dev,
|
||||
int position,
|
||||
int sync,
|
||||
const void *buf,
|
||||
size_t count)
|
||||
{
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
do
|
||||
{
|
||||
do {
|
||||
mr_interrupt_disable();
|
||||
int ret = dev_lock_take(dev,
|
||||
(MR_LOCK_WR | MR_LOCK_SLEEP | (sync == MR_SYNC ? MR_LOCK_NONBLOCK : 0)),
|
||||
(MR_LOCK_WR |
|
||||
MR_LOCK_SLEEP |
|
||||
(sync == MR_SYNC ? MR_LOCK_NONBLOCK : 0)),
|
||||
MR_LOCK_WR);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
mr_interrupt_enable();
|
||||
return ret;
|
||||
}
|
||||
@@ -375,8 +291,7 @@ MR_INLINE ssize_t dev_write(struct mr_dev *dev, int position, int sync, const vo
|
||||
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
dev_lock_release(dev, MR_LOCK_WR);
|
||||
if ((sync == MR_ASYNC) && (ret > 0))
|
||||
{
|
||||
if ((sync == MR_ASYNC) && (ret > 0)) {
|
||||
mr_interrupt_disable();
|
||||
dev_lock_take(dev, 0, MR_LOCK_NONBLOCK);
|
||||
mr_interrupt_enable();
|
||||
@@ -387,21 +302,19 @@ MR_INLINE ssize_t dev_write(struct mr_dev *dev, int position, int sync, const vo
|
||||
|
||||
MR_INLINE int dev_ioctl(struct mr_dev *dev, int position, int sync, int cmd, void *args)
|
||||
{
|
||||
if (dev->ops->ioctl == MR_NULL)
|
||||
{
|
||||
if (dev->ops->ioctl == MR_NULL) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
do
|
||||
{
|
||||
do {
|
||||
/* Lock only when user -> device command */
|
||||
if (cmd)
|
||||
{
|
||||
if (cmd) {
|
||||
mr_interrupt_disable();
|
||||
int ret = dev_lock_take(dev, (MR_LOCK_RDWR | MR_LOCK_SLEEP | MR_LOCK_NONBLOCK), MR_LOCK_RDWR);
|
||||
if (ret < 0)
|
||||
{
|
||||
int ret = dev_lock_take(dev,
|
||||
(MR_LOCK_RDWR | MR_LOCK_SLEEP | MR_LOCK_NONBLOCK),
|
||||
MR_LOCK_RDWR);
|
||||
if (ret < 0) {
|
||||
mr_interrupt_enable();
|
||||
return ret;
|
||||
}
|
||||
@@ -428,22 +341,18 @@ MR_INLINE int desc_allocate(const char *path)
|
||||
int desc = -1;
|
||||
|
||||
struct mr_dev *dev = dev_find(path);
|
||||
if (dev == MR_NULL)
|
||||
{
|
||||
if (dev == MR_NULL) {
|
||||
return MR_ENOTFOUND;
|
||||
}
|
||||
|
||||
/* Find a free descriptor */
|
||||
for (size_t i = 0; i < MR_CFG_DESC_NUM; i++)
|
||||
{
|
||||
if (DESC_OF(i).dev == MR_NULL)
|
||||
{
|
||||
for (size_t i = 0; i < MR_CFG_DESC_NUM; i++) {
|
||||
if (DESC_OF(i).dev == MR_NULL) {
|
||||
desc = (int)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (desc < 0)
|
||||
{
|
||||
if (desc < 0) {
|
||||
return MR_ENOMEM;
|
||||
}
|
||||
|
||||
@@ -459,8 +368,7 @@ MR_INLINE int desc_allocate(const char *path)
|
||||
|
||||
MR_INLINE void desc_free(int desc)
|
||||
{
|
||||
if (DESC_IS_VALID(desc) == MR_TRUE)
|
||||
{
|
||||
if (DESC_IS_VALID(desc) == MR_TRUE) {
|
||||
DESC_OF(desc).dev = MR_NULL;
|
||||
DESC_OF(desc).flags = MR_O_CLOSED;
|
||||
DESC_OF(desc).position = -1;
|
||||
@@ -543,20 +451,52 @@ int mr_dev_isr(struct mr_dev *dev, int event, void *args)
|
||||
MR_ASSERT(dev != MR_NULL);
|
||||
MR_ASSERT(event >= 0);
|
||||
|
||||
if ((dev->ref_count == 0) || (dev->ops->isr == MR_NULL))
|
||||
{
|
||||
if (dev->ref_count == 0) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
|
||||
/* Call the device ISR */
|
||||
ssize_t ret = dev->ops->isr(dev, event, args);
|
||||
if (ret < 0)
|
||||
{
|
||||
return (int)ret;
|
||||
if (dev->ops->isr != MR_NULL) {
|
||||
ssize_t ret = dev->ops->isr(dev, event, args);
|
||||
if (ret < 0) {
|
||||
return (int)ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle the ISR event */
|
||||
return dev_isr(dev, (event & MR_ISR_MASK), &ret);
|
||||
/* Call the all set callbacks */
|
||||
switch (event & MR_ISR_MASK) {
|
||||
case MR_ISR_RD: {
|
||||
for (struct mr_list *list = dev->rd_call_list.next;
|
||||
list != &dev->rd_call_list;
|
||||
list = list->next) {
|
||||
struct mr_dev_desc *desc = (struct mr_dev_desc *)MR_CONTAINER_OF(list,
|
||||
struct mr_dev_desc,
|
||||
rd_call.list);
|
||||
if (desc->rd_call.fn != MR_NULL) {
|
||||
desc->rd_call.fn((int)(desc - &desc_map[0]), args);
|
||||
}
|
||||
}
|
||||
return MR_EOK;
|
||||
}
|
||||
case MR_ISR_WR: {
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
dev_lock_release(dev, MR_LOCK_NONBLOCK);
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
for (struct mr_list *list = dev->wr_call_list.next;
|
||||
list != &dev->wr_call_list;
|
||||
list = list->next) {
|
||||
struct mr_dev_desc *desc = (struct mr_dev_desc *)MR_CONTAINER_OF(list,
|
||||
struct mr_dev_desc,
|
||||
wr_call.list);
|
||||
if (desc->wr_call.fn != MR_NULL) {
|
||||
desc->wr_call.fn((int)(desc - &desc_map[0]), args);
|
||||
}
|
||||
}
|
||||
return MR_EOK;
|
||||
}
|
||||
default: {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,11 +519,9 @@ int mr_dev_open(const char *path, int flags)
|
||||
MR_ASSERT(flags >= MR_O_CLOSED);
|
||||
|
||||
/* Query device flags */
|
||||
if (flags == MR_O_QUERY)
|
||||
{
|
||||
if (flags == MR_O_QUERY) {
|
||||
struct mr_dev *dev = dev_find(path);
|
||||
if (dev == MR_NULL)
|
||||
{
|
||||
if (dev == MR_NULL) {
|
||||
return MR_ENOTFOUND;
|
||||
}
|
||||
return dev->flags;
|
||||
@@ -591,13 +529,11 @@ int mr_dev_open(const char *path, int flags)
|
||||
|
||||
/* Allocate descriptor and open device */
|
||||
int desc = desc_allocate(path);
|
||||
if (desc < 0)
|
||||
{
|
||||
if (desc < 0) {
|
||||
return desc;
|
||||
}
|
||||
int ret = dev_open(DESC_OF(desc).dev, flags);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
desc_free(desc);
|
||||
return ret;
|
||||
}
|
||||
@@ -623,8 +559,7 @@ int mr_dev_close(int desc)
|
||||
|
||||
/* Close the device and free the descriptor */
|
||||
int ret = dev_close(DESC_OF(desc).dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
desc_free(desc);
|
||||
@@ -651,8 +586,7 @@ ssize_t mr_dev_read(int desc, void *buf, size_t count)
|
||||
MR_DESC_CHECK(desc);
|
||||
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_RDONLY) == MR_DISABLE)
|
||||
{
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_RDONLY) == MR_DISABLE) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
@@ -685,8 +619,7 @@ ssize_t mr_dev_write(int desc, const void *buf, size_t count)
|
||||
MR_DESC_CHECK(desc);
|
||||
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_WRONLY) == MR_DISABLE)
|
||||
{
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_WRONLY) == MR_DISABLE) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
@@ -717,12 +650,9 @@ int mr_dev_ioctl(int desc, int cmd, void *args)
|
||||
{
|
||||
MR_DESC_CHECK(desc);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case MR_IOC_SPOS:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
switch (cmd) {
|
||||
case MR_IOC_SPOS: {
|
||||
if (args != MR_NULL) {
|
||||
int position = *(int *)args;
|
||||
|
||||
DESC_OF(desc).position = position;
|
||||
@@ -730,44 +660,48 @@ int mr_dev_ioctl(int desc, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_SRCB:
|
||||
{
|
||||
case MR_IOC_SRCB: {
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_RDONLY) == MR_DISABLE) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
void (*fn)(int desc, void *args) = (void (*)(int desc, void *args))args;
|
||||
|
||||
/* Link or unlink the callback function */
|
||||
DESC_OF(desc).rd_call.fn = fn;
|
||||
mr_interrupt_disable();
|
||||
if (fn != MR_NULL)
|
||||
{
|
||||
mr_list_insert_before(&DESC_OF(desc).dev->rd_call_list, &DESC_OF(desc).rd_call.list);
|
||||
} else
|
||||
{
|
||||
if (fn != MR_NULL) {
|
||||
mr_list_insert_before(&DESC_OF(desc).dev->rd_call_list,
|
||||
&DESC_OF(desc).rd_call.list);
|
||||
} else {
|
||||
mr_list_remove(&DESC_OF(desc).rd_call.list);
|
||||
}
|
||||
mr_interrupt_enable();
|
||||
return sizeof(fn);
|
||||
}
|
||||
case MR_IOC_SWCB:
|
||||
{
|
||||
case MR_IOC_SWCB: {
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_WRONLY) == MR_DISABLE) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
void (*fn)(int desc, void *args) = (void (*)(int desc, void *args))args;
|
||||
|
||||
/* Link or unlink the callback function */
|
||||
DESC_OF(desc).wr_call.fn = fn;
|
||||
mr_interrupt_disable();
|
||||
if (fn != MR_NULL)
|
||||
{
|
||||
mr_list_insert_before(&DESC_OF(desc).dev->wr_call_list, &DESC_OF(desc).wr_call.list);
|
||||
} else
|
||||
{
|
||||
if (fn != MR_NULL) {
|
||||
mr_list_insert_before(&DESC_OF(desc).dev->wr_call_list,
|
||||
&DESC_OF(desc).wr_call.list);
|
||||
} else {
|
||||
mr_list_remove(&DESC_OF(desc).wr_call.list);
|
||||
}
|
||||
mr_interrupt_enable();
|
||||
return sizeof(fn);
|
||||
}
|
||||
case MR_IOC_GPOS:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_GPOS: {
|
||||
if (args != MR_NULL) {
|
||||
int *position = (int *)args;
|
||||
|
||||
*position = DESC_OF(desc).position;
|
||||
@@ -775,26 +709,31 @@ int mr_dev_ioctl(int desc, int cmd, void *args)
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_GRCB:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_GRCB: {
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_RDONLY) == MR_DISABLE) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
if (args != MR_NULL) {
|
||||
*(void (**)(int desc, void *args))args = DESC_OF(desc).rd_call.fn;
|
||||
return sizeof(DESC_OF(desc).rd_call.fn);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
case MR_IOC_GWCB:
|
||||
{
|
||||
if (args != MR_NULL)
|
||||
{
|
||||
case MR_IOC_GWCB: {
|
||||
#ifdef MR_USING_RDWR_CTL
|
||||
if (MR_BIT_IS_SET(DESC_OF(desc).flags, MR_O_WRONLY) == MR_DISABLE) {
|
||||
return MR_ENOTSUP;
|
||||
}
|
||||
#endif /* MR_USING_RDWR_CTL */
|
||||
if (args != MR_NULL) {
|
||||
*(void (**)(int desc, void *args))args = DESC_OF(desc).wr_call.fn;
|
||||
return sizeof(DESC_OF(desc).wr_call.fn);
|
||||
}
|
||||
return MR_EINVAL;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
/* I/O control to the device */
|
||||
return dev_ioctl(DESC_OF(desc).dev,
|
||||
DESC_OF(desc).position,
|
||||
@@ -813,14 +752,12 @@ static int dev_get_path(struct mr_dev *dev, char *buf, size_t bufsz)
|
||||
int ret = 0;
|
||||
|
||||
/* Continue iterating until reach the null parent */
|
||||
if (dev->parent != MR_NULL)
|
||||
{
|
||||
if (dev->parent != MR_NULL) {
|
||||
ret = dev_get_path(dev->parent, buf, bufsz);
|
||||
}
|
||||
|
||||
/* Check whether the buffer is enough */
|
||||
if ((bufsz - ret) <= (strlen(dev->name) + 1))
|
||||
{
|
||||
if ((bufsz - ret) <= (strlen(dev->name) + 1)) {
|
||||
return ret;
|
||||
}
|
||||
ret += snprintf(buf + ret, bufsz - ret, "/%s", dev->name);
|
||||
@@ -836,23 +773,23 @@ int msh_dev_get_path(int desc, char *buf, size_t size)
|
||||
|
||||
void msh_dlist_tree(struct mr_dev *parent, int level)
|
||||
{
|
||||
if (level == 0)
|
||||
{
|
||||
if (level == 0) {
|
||||
mr_msh_printf("|%s %-*s", mr_strflags(parent->flags), MR_CFG_DEV_NAME_LEN, parent->name);
|
||||
} else
|
||||
{
|
||||
mr_msh_printf("%*s|%s %-*s", level, " ", mr_strflags(parent->flags), MR_CFG_DEV_NAME_LEN, parent->name);
|
||||
} else {
|
||||
mr_msh_printf("%*s|%s %-*s",
|
||||
level,
|
||||
" ",
|
||||
mr_strflags(parent->flags),
|
||||
MR_CFG_DEV_NAME_LEN,
|
||||
parent->name);
|
||||
}
|
||||
for (size_t i = 0; i < MR_CFG_DESC_NUM; i++)
|
||||
{
|
||||
if (desc_map[i].dev == parent)
|
||||
{
|
||||
for (size_t i = 0; i < MR_CFG_DESC_NUM; i++) {
|
||||
if (desc_map[i].dev == parent) {
|
||||
mr_msh_printf(" [%d]", i);
|
||||
}
|
||||
}
|
||||
mr_msh_printf("\r\n");
|
||||
for (struct mr_list *child = parent->clist.next; child != &parent->clist; child = child->next)
|
||||
{
|
||||
for (struct mr_list *child = parent->clist.next; child != &parent->clist; child = child->next) {
|
||||
struct mr_dev *dev = MR_CONTAINER_OF(child, struct mr_dev, list);
|
||||
msh_dlist_tree(dev, level + 7);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user