mirror of
https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_RTL8710BX_ALIOS_SDK.git
synced 2025-07-31 19:31:05 +00:00
rel_1.6.0 init
This commit is contained in:
commit
27b3e2883d
19359 changed files with 8093121 additions and 0 deletions
211
Living_SDK/kernel/vfs/device.c
Normal file
211
Living_SDK/kernel/vfs/device.c
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <aos/aos.h>
|
||||
|
||||
#include <vfs_conf.h>
|
||||
#include <vfs_err.h>
|
||||
#include <vfs_register.h>
|
||||
#include <event_device.h>
|
||||
|
||||
#if (AOS_CONFIG_VFS_POLL_SUPPORT > 0)
|
||||
static int inited;
|
||||
|
||||
typedef struct {
|
||||
aos_mutex_t mutex;
|
||||
poll_notify_t poll_cb;
|
||||
struct pollfd *fd;
|
||||
void *poll_data;
|
||||
int counter;
|
||||
dlist_t bufs;
|
||||
int cache_count;
|
||||
dlist_t buf_cache;
|
||||
} event_dev_t;
|
||||
|
||||
typedef struct {
|
||||
dlist_t node;
|
||||
size_t len;
|
||||
char buf[];
|
||||
} dev_event_t;
|
||||
|
||||
static int event_open(inode_t *node, file_t *file)
|
||||
{
|
||||
event_dev_t *pdev = (event_dev_t *)aos_malloc(sizeof * pdev);
|
||||
memset(pdev,0,sizeof (*pdev));
|
||||
aos_mutex_new(&pdev->mutex);
|
||||
dlist_init(&pdev->bufs);
|
||||
dlist_init(&pdev->buf_cache);
|
||||
file->f_arg = pdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int event_close(file_t *file)
|
||||
{
|
||||
event_dev_t *pdev = file->f_arg;
|
||||
aos_mutex_free(&pdev->mutex);
|
||||
|
||||
while (!dlist_empty(&pdev->bufs)) {
|
||||
dlist_t *n = pdev->bufs.next;
|
||||
dlist_del(n);
|
||||
aos_free(n);
|
||||
}
|
||||
|
||||
while (!dlist_empty(&pdev->buf_cache)) {
|
||||
dlist_t *n = pdev->buf_cache.next;
|
||||
dlist_del(n);
|
||||
aos_free(n);
|
||||
}
|
||||
|
||||
aos_free(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t _event_write(file_t *f, const void *buf, size_t len, bool urgent)
|
||||
{
|
||||
event_dev_t *pdev = f->f_arg;
|
||||
aos_mutex_lock(&pdev->mutex, AOS_WAIT_FOREVER);
|
||||
ssize_t ret = len;
|
||||
|
||||
dev_event_t *evt;
|
||||
evt = (dev_event_t *)pdev->buf_cache.next;
|
||||
|
||||
if (pdev->cache_count > 0 && evt->len == len) {
|
||||
dlist_del(&evt->node);
|
||||
pdev->cache_count --;
|
||||
} else {
|
||||
evt = (dev_event_t *)aos_malloc(sizeof(*evt) + len);
|
||||
}
|
||||
|
||||
if (evt == NULL) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pdev->counter ++;
|
||||
|
||||
evt->len = len;
|
||||
memcpy(evt->buf, buf, len);
|
||||
if (urgent) {
|
||||
dlist_add(&evt->node, &pdev->bufs);
|
||||
} else {
|
||||
dlist_add_tail(&evt->node, &pdev->bufs);
|
||||
}
|
||||
|
||||
if (pdev->poll_cb != NULL) {
|
||||
pdev->fd->revents |= POLLIN;
|
||||
pdev->poll_cb(pdev->fd, pdev->poll_data);
|
||||
}
|
||||
out:
|
||||
aos_mutex_unlock(&pdev->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t event_write(file_t *f, const void *buf, size_t len)
|
||||
{
|
||||
return _event_write(f, buf, len, false);
|
||||
}
|
||||
|
||||
static int event_ioctl(file_t *f, int cmd, unsigned long arg)
|
||||
{
|
||||
int len = _GET_LEN(cmd);
|
||||
void *buf = (void *)arg;
|
||||
cmd = _GET_CMD(cmd);
|
||||
switch (cmd) {
|
||||
case IOCTL_WRITE_NORMAL:
|
||||
return _event_write(f, buf, len, false);
|
||||
case IOCTL_WRITE_URGENT:
|
||||
return _event_write(f, buf, len, true);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t event_read(file_t *f, void *buf, size_t len)
|
||||
{
|
||||
event_dev_t *pdev = f->f_arg;
|
||||
int cnt = pdev->counter;
|
||||
|
||||
if (!cnt) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aos_mutex_lock(&pdev->mutex, AOS_WAIT_FOREVER);
|
||||
|
||||
dev_event_t *evt = (dev_event_t *)pdev->bufs.next;
|
||||
dlist_del(&evt->node);
|
||||
cnt = (len > evt->len) ? evt->len : len;
|
||||
memcpy(buf, evt->buf, cnt);
|
||||
|
||||
if (pdev->cache_count < 4) {
|
||||
dlist_add(&evt->node, &pdev->buf_cache);
|
||||
pdev->cache_count ++;
|
||||
} else {
|
||||
aos_free(evt);
|
||||
}
|
||||
|
||||
pdev->counter --;
|
||||
|
||||
aos_mutex_unlock(&pdev->mutex);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static int event_poll(file_t *f, bool setup, poll_notify_t notify,
|
||||
struct pollfd *fd, void *opa)
|
||||
{
|
||||
event_dev_t *pdev = f->f_arg;
|
||||
|
||||
aos_mutex_lock(&pdev->mutex, AOS_WAIT_FOREVER);
|
||||
if (!setup) {
|
||||
pdev->poll_cb = NULL;
|
||||
pdev->poll_data = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pdev->poll_cb = notify;
|
||||
pdev->fd = fd;
|
||||
pdev->poll_data = opa;
|
||||
|
||||
if (pdev->counter) {
|
||||
pdev->fd->revents |= POLLIN;
|
||||
(*notify)(fd, opa);
|
||||
}
|
||||
out:
|
||||
aos_mutex_unlock(&pdev->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static file_ops_t event_fops = {
|
||||
.open = event_open,
|
||||
.read = event_read,
|
||||
.write = event_write,
|
||||
.close = event_close,
|
||||
.poll = event_poll,
|
||||
.ioctl = event_ioctl,
|
||||
};
|
||||
|
||||
int vfs_device_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (inited == 1) {
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
|
||||
ret = aos_register_driver("/dev/event", &event_fops, NULL);
|
||||
|
||||
if (ret != VFS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
inited = 1;
|
||||
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
16
Living_SDK/kernel/vfs/device/device.mk
Normal file
16
Living_SDK/kernel/vfs/device/device.mk
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
NAME := vfs_device
|
||||
|
||||
$(NAME)_MBINS_TYPE := kernel
|
||||
|
||||
$(NAME)_SOURCES += vfs_adc.c
|
||||
$(NAME)_SOURCES += vfs_uart.c
|
||||
$(NAME)_SOURCES += vfs_gpio.c
|
||||
$(NAME)_SOURCES += vfs_spi.c
|
||||
$(NAME)_SOURCES += vfs_pwm.c
|
||||
$(NAME)_SOURCES += vfs_rtc.c
|
||||
$(NAME)_SOURCES += vfs_wdg.c
|
||||
$(NAME)_SOURCES += vfs_i2c.c
|
||||
|
||||
$(NAME)_INCLUDES += ../include/device/ \
|
||||
../include/ \
|
||||
../../hal/soc/
|
||||
15
Living_SDK/kernel/vfs/device/ucube.py
Normal file
15
Living_SDK/kernel/vfs/device/ucube.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
src = Split('''
|
||||
vfs_adc.c
|
||||
vfs_uart.c
|
||||
vfs_gpio.c
|
||||
vfs_spi.c
|
||||
vfs_pwm.c
|
||||
vfs_rtc.c
|
||||
vfs_wdg.c
|
||||
vfs_i2c.c
|
||||
''')
|
||||
|
||||
component = aos_component('vfs_device', src)
|
||||
|
||||
component.add_global_includes('../include/device', '../include', '../../hal/soc/')
|
||||
|
||||
109
Living_SDK/kernel/vfs/device/vfs_adc.c
Normal file
109
Living_SDK/kernel/vfs/device/vfs_adc.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_adc.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* adc driver struct */
|
||||
const struct file_ops adc_ops =
|
||||
{
|
||||
.open = vfs_adc_open,
|
||||
.read = vfs_adc_read,
|
||||
.close = vfs_adc_close
|
||||
};
|
||||
|
||||
int vfs_adc_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
adc_dev_t *adc_dev = NULL; /* adc device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
adc_dev = (adc_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init adc device. */
|
||||
ret = hal_adc_init(adc_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_adc_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
adc_dev_t *adc_dev = NULL; /* adc device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
adc_dev = (adc_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off an ADC hardwar. */
|
||||
ret = hal_adc_finalize(adc_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_adc_read(file_t *fp, void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
adc_dev_t *adc_dev = NULL; /* adc device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
adc_dev = (adc_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* get adc sampled value. */
|
||||
ret = hal_adc_value_get(adc_dev, buf, HAL_WAIT_FOREVER);
|
||||
|
||||
/* If the data is got successfully, set the return
|
||||
value to nbytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
150
Living_SDK/kernel/vfs/device/vfs_gpio.c
Normal file
150
Living_SDK/kernel/vfs/device/vfs_gpio.c
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_gpio.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* gpio driver struct */
|
||||
const struct file_ops gpio_ops =
|
||||
{
|
||||
.open = vfs_gpio_open,
|
||||
.close = vfs_gpio_close,
|
||||
.read = vfs_gpio_read,
|
||||
.ioctl = vfs_gpio_ioctl
|
||||
};
|
||||
|
||||
int vfs_gpio_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
gpio_dev_t *gpio_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
gpio_dev = (gpio_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init gpio device. */
|
||||
ret = hal_gpio_init(gpio_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_gpio_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
gpio_dev_t *gpio_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
gpio_dev = (gpio_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off hardware. */
|
||||
ret = hal_gpio_finalize(gpio_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_gpio_read(file_t *fp, void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
gpio_dev_t *gpio_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
gpio_dev = (gpio_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* get data from gpio. */
|
||||
ret = hal_gpio_input_get(gpio_dev, (uint32_t *)buf);
|
||||
|
||||
/* If the data is read correctly and the number of read data
|
||||
bytes is not negative, the return value is set to read bytes. */
|
||||
if (ret == 0) {
|
||||
ret = sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_gpio_ioctl(file_t *fp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
gpio_dev_t *gpio_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp == NULL) || (fp->node == NULL)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get the device pointer. */
|
||||
gpio_dev = (gpio_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case IOCTL_GPIO_OUTPUT_HIGHT:
|
||||
ret = hal_gpio_output_high(gpio_dev); /* output hight */
|
||||
break;
|
||||
case IOCTL_GPIO_OUTPUT_LOW:
|
||||
ret = hal_gpio_output_low(gpio_dev); /* output low */
|
||||
break;
|
||||
case IOCTL_GPIO_OUTPUT_TOGGLE:
|
||||
ret = hal_gpio_output_toggle(gpio_dev); /* toggle output */
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
152
Living_SDK/kernel/vfs/device/vfs_i2c.c
Normal file
152
Living_SDK/kernel/vfs/device/vfs_i2c.c
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_i2c.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* i2c driver struct */
|
||||
const struct file_ops i2c_ops =
|
||||
{
|
||||
.open = vfs_i2c_open,
|
||||
.close = vfs_i2c_close,
|
||||
.read = vfs_i2c_read,
|
||||
.write = vfs_i2c_write
|
||||
};
|
||||
|
||||
int vfs_i2c_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
i2c_dev_t *i2c_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
i2c_dev = (i2c_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init i2c device. */
|
||||
ret = hal_i2c_init(i2c_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_i2c_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
i2c_dev_t *i2c_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
i2c_dev = (i2c_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off hardware. */
|
||||
ret = hal_i2c_finalize(i2c_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_i2c_read(file_t *fp, void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
i2c_dev_t *i2c_dev = NULL; /* device pointer */
|
||||
uint16_t dev_addr = 0; /* dev address */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
i2c_dev = (i2c_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* get the device address. */
|
||||
dev_addr = i2c_dev->config.dev_addr;
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* get data from i2c. */
|
||||
ret = hal_i2c_master_recv(i2c_dev, dev_addr, (uint8_t *)buf, nbytes, HAL_WAIT_FOREVER);
|
||||
|
||||
/* If the data is read correctly, the return
|
||||
value is set to read bytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_i2c_write(file_t *fp, const void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
i2c_dev_t *i2c_dev = NULL; /* device pointer */
|
||||
uint16_t dev_addr = 0; /* dev address */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
i2c_dev = (i2c_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* get the device address. */
|
||||
dev_addr = i2c_dev->config.dev_addr;
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* send data from i2c. */
|
||||
ret = hal_i2c_master_send(i2c_dev, dev_addr, (const uint8_t *)buf, nbytes, HAL_WAIT_FOREVER);
|
||||
|
||||
/* If the data is sent successfully, set the return
|
||||
value to nbytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
112
Living_SDK/kernel/vfs/device/vfs_pwm.c
Normal file
112
Living_SDK/kernel/vfs/device/vfs_pwm.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_pwm.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* pwm driver struct */
|
||||
const struct file_ops pwm_ops =
|
||||
{
|
||||
.open = vfs_pwm_open,
|
||||
.close = vfs_pwm_close,
|
||||
.ioctl = vfs_pwm_ioctl
|
||||
};
|
||||
|
||||
int vfs_pwm_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
pwm_dev_t *pwm_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
pwm_dev = (pwm_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init pwm device. */
|
||||
ret = hal_pwm_init(pwm_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_pwm_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
pwm_dev_t *pwm_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
pwm_dev = (pwm_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off hardware. */
|
||||
ret = hal_pwm_finalize(pwm_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_pwm_ioctl(file_t *fp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
pwm_dev_t *pwm_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp == NULL) || (fp->node == NULL)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get the device pointer. */
|
||||
pwm_dev = (pwm_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case IOCTL_PWM_OUTPUT_START:
|
||||
ret = hal_pwm_start(pwm_dev);
|
||||
break;
|
||||
case IOCTL_PWM_OUTPUT_STOP:
|
||||
ret = hal_pwm_stop(pwm_dev);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
143
Living_SDK/kernel/vfs/device/vfs_rtc.c
Normal file
143
Living_SDK/kernel/vfs/device/vfs_rtc.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_rtc.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* rtc driver struct */
|
||||
const struct file_ops rtc_ops =
|
||||
{
|
||||
.open = vfs_rtc_open,
|
||||
.close = vfs_rtc_close,
|
||||
.read = vfs_rtc_read,
|
||||
.write = vfs_rtc_write
|
||||
};
|
||||
|
||||
int vfs_rtc_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
rtc_dev_t *rtc_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
rtc_dev = (rtc_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init rtc device. */
|
||||
ret = hal_rtc_init(rtc_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_rtc_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
rtc_dev_t *rtc_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
rtc_dev = (rtc_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off hardware. */
|
||||
ret = hal_rtc_finalize(rtc_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_rtc_read(file_t *fp, void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
rtc_dev_t *rtc_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL) && (nbytes >= sizeof(rtc_time_t))) {
|
||||
|
||||
/* get the device pointer. */
|
||||
rtc_dev = (rtc_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* get data from rtc. */
|
||||
ret = hal_rtc_get_time(rtc_dev, (rtc_time_t *)buf);
|
||||
|
||||
/* If the data is read correctly the return value is set to nbytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_rtc_write(file_t *fp, const void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
rtc_dev_t *rtc_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL) && (nbytes >= sizeof(rtc_time_t))) {
|
||||
|
||||
/* get the device pointer. */
|
||||
rtc_dev = (rtc_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* set rtc time. */
|
||||
ret = hal_rtc_set_time(rtc_dev, (const rtc_time_t *)buf);
|
||||
|
||||
/* If the time is set successfully, set the return
|
||||
value to nbytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
144
Living_SDK/kernel/vfs/device/vfs_spi.c
Normal file
144
Living_SDK/kernel/vfs/device/vfs_spi.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_spi.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* spi driver struct */
|
||||
const struct file_ops spi_ops =
|
||||
{
|
||||
.open = vfs_spi_open,
|
||||
.close = vfs_spi_close,
|
||||
.read = vfs_spi_read,
|
||||
.write = vfs_spi_write
|
||||
};
|
||||
|
||||
int vfs_spi_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
spi_dev_t *spi_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
spi_dev = (spi_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init spi device. */
|
||||
ret = hal_spi_init(spi_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_spi_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
spi_dev_t *spi_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
spi_dev = (spi_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off hardware. */
|
||||
ret = hal_spi_finalize(spi_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_spi_read(file_t *fp, void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
spi_dev_t *spi_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
spi_dev = (spi_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* get data from spi. */
|
||||
ret = hal_spi_recv(spi_dev, (unsigned char *)buf, nbytes, HAL_WAIT_FOREVER);
|
||||
|
||||
/* If the data is read correctly and the number of read data
|
||||
bytes is not negative, the return value is set to read bytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_spi_write(file_t *fp, const void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
spi_dev_t *spi_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
spi_dev = (spi_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* send data from spi. */
|
||||
ret = hal_spi_send(spi_dev, (const uint8_t *)buf, nbytes, HAL_WAIT_FOREVER);
|
||||
|
||||
/* If the data is sent successfully, set the return
|
||||
value to nbytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
144
Living_SDK/kernel/vfs/device/vfs_uart.c
Normal file
144
Living_SDK/kernel/vfs/device/vfs_uart.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_uart.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* uart driver struct */
|
||||
const struct file_ops uart_ops =
|
||||
{
|
||||
.open = vfs_uart_open,
|
||||
.close = vfs_uart_close,
|
||||
.read = vfs_uart_read,
|
||||
.write = vfs_uart_write
|
||||
};
|
||||
|
||||
int vfs_uart_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
uart_dev_t *uart_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
uart_dev = (uart_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init uart device. */
|
||||
ret = hal_uart_init(uart_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_uart_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
uart_dev_t *uart_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
uart_dev = (uart_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off hardware. */
|
||||
ret = hal_uart_finalize(uart_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_uart_read(file_t *fp, void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
uart_dev_t *uart_dev = NULL; /* device pointer */
|
||||
uint32_t recv_bytes = 0; /* number of bytes received */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
uart_dev = (uart_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* get data from uart. */
|
||||
ret = hal_uart_recv_II(uart_dev, buf, nbytes, &recv_bytes, HAL_WAIT_FOREVER);
|
||||
|
||||
/* If the data is read correctly the return value is set to read bytes. */
|
||||
if (ret == 0) {
|
||||
ret = recv_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t vfs_uart_write(file_t *fp, const void *buf, size_t nbytes)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
uart_dev_t *uart_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* get the device pointer. */
|
||||
uart_dev = (uart_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* send data from uart. */
|
||||
ret = hal_uart_send(uart_dev, buf, nbytes, HAL_WAIT_FOREVER);
|
||||
|
||||
/* If the data is sent successfully, set the return
|
||||
value to nbytes. */
|
||||
if (ret == 0) {
|
||||
ret = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
110
Living_SDK/kernel/vfs/device/vfs_wdg.c
Normal file
110
Living_SDK/kernel/vfs/device/vfs_wdg.c
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "device/vfs_wdg.h"
|
||||
#include "hal/soc/soc.h"
|
||||
#include "vfs_err.h"
|
||||
|
||||
/* wdg driver struct */
|
||||
const struct file_ops wdg_ops =
|
||||
{
|
||||
.open = vfs_wdg_open,
|
||||
.close = vfs_wdg_close,
|
||||
.ioctl = vfs_wdg_ioctl
|
||||
};
|
||||
|
||||
int vfs_wdg_open(inode_t *inode, file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
wdg_dev_t *wdg_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* Initialize if the device is first opened. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
wdg_dev = (wdg_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* init wdg device. */
|
||||
ret = hal_wdg_init(wdg_dev);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_wdg_close(file_t *fp)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
wdg_dev_t *wdg_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp != NULL) && (fp->node != NULL)) {
|
||||
|
||||
/* close device if the device is last closed. */
|
||||
if (fp->node->refs == 1) {
|
||||
|
||||
/* get the device pointer. */
|
||||
wdg_dev = (wdg_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret == 0) {
|
||||
|
||||
/* turns off hardware. */
|
||||
ret = hal_wdg_finalize(wdg_dev);
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
} else {
|
||||
ret = VFS_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vfs_wdg_ioctl(file_t *fp, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = -1; /* return value */
|
||||
wdg_dev_t *wdg_dev = NULL; /* device pointer */
|
||||
|
||||
/* check empty pointer. */
|
||||
if ((fp == NULL) || (fp->node == NULL)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get the device pointer. */
|
||||
wdg_dev = (wdg_dev_t *)(fp->node->i_arg);
|
||||
|
||||
/* lock the device. */
|
||||
ret = aos_mutex_lock(&fp->node->mutex, AOS_WAIT_FOREVER);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch(cmd) {
|
||||
case IOCTL_WDG_RELOAD:
|
||||
hal_wdg_reload(wdg_dev);
|
||||
ret = VFS_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* unlock the device. */
|
||||
aos_mutex_unlock(&fp->node->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
52
Living_SDK/kernel/vfs/include/device/vfs_adc.h
Normal file
52
Living_SDK/kernel/vfs/include/device/vfs_adc.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_ADC_H
|
||||
#define AOS_VFS_ADC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* adc driver struct */
|
||||
extern const struct file_ops adc_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open adc device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_adc_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close adc device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_adc_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to complete the data sample and get the sampled value.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for sampled data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes read on success,
|
||||
* 0 on read nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_adc_read(file_t *fp, void *buf, size_t nbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_ADC_H */
|
||||
|
||||
26
Living_SDK/kernel/vfs/include/device/vfs_device.h
Normal file
26
Living_SDK/kernel/vfs/include/device/vfs_device.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_DEVICE_H
|
||||
#define AOS_VFS_DEVICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_adc.h"
|
||||
#include "vfs_gpio.h"
|
||||
#include "vfs_i2c.h"
|
||||
#include "vfs_pwm.h"
|
||||
#include "vfs_rtc.h"
|
||||
#include "vfs_spi.h"
|
||||
#include "vfs_uart.h"
|
||||
#include "vfs_wdg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_DEVICE_H */
|
||||
|
||||
68
Living_SDK/kernel/vfs/include/device/vfs_gpio.h
Normal file
68
Living_SDK/kernel/vfs/include/device/vfs_gpio.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_GPIO_H
|
||||
#define AOS_VFS_GPIO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* cmd for ioctl */
|
||||
#define IOCTL_GPIO_OUTPUT_HIGHT 1 /* output hight */
|
||||
#define IOCTL_GPIO_OUTPUT_LOW 2 /* output low */
|
||||
#define IOCTL_GPIO_OUTPUT_TOGGLE 3 /* toggle output */
|
||||
|
||||
/* gpio driver struct */
|
||||
extern const struct file_ops gpio_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open gpio device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_gpio_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close gpio device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_gpio_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to get data from gpio.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes read on success,
|
||||
* 0 on read nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_gpio_read(file_t *fp, void *buf, size_t nbytes);
|
||||
|
||||
/**
|
||||
* This function performs device input and output operations.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[in] cmd command of input and output operating.
|
||||
* @param[in] arg argument of input and output operating.
|
||||
*
|
||||
* @return 0 on success, negative on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_gpio_ioctl(file_t *fp, int cmd, unsigned long arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_GPIO_H */
|
||||
|
||||
64
Living_SDK/kernel/vfs/include/device/vfs_i2c.h
Normal file
64
Living_SDK/kernel/vfs/include/device/vfs_i2c.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_I2C_H
|
||||
#define AOS_VFS_I2C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* i2c driver struct */
|
||||
extern const struct file_ops i2c_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open i2c device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_i2c_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close i2c device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_i2c_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to get data from i2c.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes read on success,
|
||||
* 0 on read nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_i2c_read(file_t *fp, void *buf, size_t nbytes);
|
||||
|
||||
/**
|
||||
* This function is used to send data through i2c.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes write on success,
|
||||
* 0 on write nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_i2c_write(file_t *fp, const void *buf, size_t nbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_I2C_H */
|
||||
|
||||
55
Living_SDK/kernel/vfs/include/device/vfs_pwm.h
Normal file
55
Living_SDK/kernel/vfs/include/device/vfs_pwm.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_PWM_H
|
||||
#define AOS_VFS_PWM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* cmd for ioctl */
|
||||
#define IOCTL_PWM_OUTPUT_START 1 /* start output pwm */
|
||||
#define IOCTL_PWM_OUTPUT_STOP 2 /* stop output pwm */
|
||||
|
||||
/* pwm driver struct */
|
||||
extern const struct file_ops pwm_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open pwm device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_pwm_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close pwm device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_pwm_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function performs device input and output operations.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[in] cmd command of input and output operating.
|
||||
* @param[in] arg argument of input and output operating.
|
||||
*
|
||||
* @return 0 on success, negative on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_pwm_ioctl(file_t *fp, int cmd, unsigned long arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_PWM_H */
|
||||
|
||||
64
Living_SDK/kernel/vfs/include/device/vfs_rtc.h
Normal file
64
Living_SDK/kernel/vfs/include/device/vfs_rtc.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_RTC_H
|
||||
#define AOS_VFS_RTC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* rtc driver struct */
|
||||
extern const struct file_ops rtc_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open rtc device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_rtc_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close rtc device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_rtc_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to get Real-Time Clock.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes read on success,
|
||||
* 0 on read nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_rtc_read(file_t *fp, void *buf, size_t nbytes);
|
||||
|
||||
/**
|
||||
* This function is used to set Real-Time Clock.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes write on success,
|
||||
* 0 on write nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_rtc_write(file_t *fp, const void *buf, size_t nbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_RTC_H */
|
||||
|
||||
64
Living_SDK/kernel/vfs/include/device/vfs_spi.h
Normal file
64
Living_SDK/kernel/vfs/include/device/vfs_spi.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_SPI_H
|
||||
#define AOS_VFS_SPI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* spi driver struct */
|
||||
extern const struct file_ops spi_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open spi device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_spi_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close spi device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_spi_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to get data from spi.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes read on success,
|
||||
* 0 on read nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_spi_read(file_t *fp, void *buf, size_t nbytes);
|
||||
|
||||
/**
|
||||
* This function is used to send data through spi.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes write on success,
|
||||
* 0 on write nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_spi_write(file_t *fp, const void *buf, size_t nbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_SPI_H */
|
||||
|
||||
64
Living_SDK/kernel/vfs/include/device/vfs_uart.h
Normal file
64
Living_SDK/kernel/vfs/include/device/vfs_uart.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_UART_H
|
||||
#define AOS_VFS_UART_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* uart driver struct */
|
||||
extern const struct file_ops uart_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open uart device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_uart_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close uart device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_uart_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to get data from uart.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes read on success,
|
||||
* 0 on read nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_uart_read(file_t *fp, void *buf, size_t nbytes);
|
||||
|
||||
/**
|
||||
* This function is used to send data through uart.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[out] buf data buffer for data.
|
||||
* @param[in] nbytes the maximum size of the user-provided buffer.
|
||||
*
|
||||
* @return The positive non-zero number of bytes write on success,
|
||||
* 0 on write nothing, or negative on failure with errno set appropriately.
|
||||
*/
|
||||
ssize_t vfs_uart_write(file_t *fp, const void *buf, size_t nbytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_UART_H */
|
||||
|
||||
54
Living_SDK/kernel/vfs/include/device/vfs_wdg.h
Normal file
54
Living_SDK/kernel/vfs/include/device/vfs_wdg.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_WDG_H
|
||||
#define AOS_VFS_WDG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vfs_inode.h"
|
||||
|
||||
/* cmd for ioctl */
|
||||
#define IOCTL_WDG_RELOAD 1 /* reload watchdog */
|
||||
|
||||
/* wdg driver struct */
|
||||
extern const struct file_ops wdg_ops;
|
||||
|
||||
/**
|
||||
* This function is used to open wdg device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_wdg_open(inode_t *inode, file_t *fp);
|
||||
|
||||
/**
|
||||
* This function is used to close wdg device.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
*
|
||||
* @return 0 on success, others on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_wdg_close(file_t *fp);
|
||||
|
||||
/**
|
||||
* This function performs device input and output operations.
|
||||
*
|
||||
* @param[in] fp device pointer.
|
||||
* @param[in] cmd command of input and output operating.
|
||||
* @param[in] arg argument of input and output operating.
|
||||
*
|
||||
* @return 0 on success, negative on failure with errno set appropriately.
|
||||
*/
|
||||
int vfs_wdg_ioctl(file_t *fp, int cmd, unsigned long arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AOS_VFS_WDG_H */
|
||||
|
||||
23
Living_SDK/kernel/vfs/include/event_device.h
Normal file
23
Living_SDK/kernel/vfs/include/event_device.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef EVENT_DEVICE_H
|
||||
#define EVENT_DEVICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define IOCTL_WRITE_NORMAL 0x1
|
||||
#define IOCTL_WRITE_URGENT 0x2
|
||||
|
||||
#define MK_CMD(c, l) ((l << 4) | (c))
|
||||
#define _GET_LEN(cmd) ((cmd) >> 4)
|
||||
#define _GET_CMD(cmd) ((cmd) & 0xf)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
23
Living_SDK/kernel/vfs/include/vfs.h
Normal file
23
Living_SDK/kernel/vfs/include/vfs.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_H
|
||||
#define AOS_VFS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <vfs_conf.h>
|
||||
|
||||
int vfs_init(void);
|
||||
|
||||
int vfs_device_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
25
Living_SDK/kernel/vfs/include/vfs_conf.h
Normal file
25
Living_SDK/kernel/vfs/include/vfs_conf.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_CONFIG_H
|
||||
#define AOS_VFS_CONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#define VFS_FALSE 0u
|
||||
#define VFS_TRUE 1u
|
||||
|
||||
#define AOS_CONFIG_VFS_DEV_NODES 25
|
||||
/*mem 1000 byte*/
|
||||
#define AOS_CONFIG_VFS_DEV_MEM 2000
|
||||
#define AOS_CONFIG_VFS_POLL_SUPPORT 1
|
||||
#define AOS_CONFIG_VFS_FD_OFFSET 64
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
21
Living_SDK/kernel/vfs/include/vfs_err.h
Normal file
21
Living_SDK/kernel/vfs/include/vfs_err.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef VFS_ERRNO_H
|
||||
#define VFS_ERRNO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define VFS_SUCCESS 0u
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* VFS_ERRNO_H */
|
||||
|
||||
24
Living_SDK/kernel/vfs/include/vfs_file.h
Executable file
24
Living_SDK/kernel/vfs/include/vfs_file.h
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef AOS_VFS_FILE_H
|
||||
#define AOS_VFS_FILE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int get_fd(file_t *file);
|
||||
|
||||
file_t *get_file(int fd);
|
||||
|
||||
file_t *new_file(inode_t *node);
|
||||
|
||||
void del_file(file_t *file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
115
Living_SDK/kernel/vfs/include/vfs_inode.h
Normal file
115
Living_SDK/kernel/vfs/include/vfs_inode.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef VFS_INODE_H
|
||||
#define VFS_INODE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <aos/aos.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum {
|
||||
VFS_TYPE_NOT_INIT,
|
||||
VFS_TYPE_CHAR_DEV,
|
||||
VFS_TYPE_BLOCK_DEV,
|
||||
VFS_TYPE_FS_DEV
|
||||
};
|
||||
|
||||
#define INODE_IS_TYPE(i,t) \
|
||||
((i)->type == (t))
|
||||
|
||||
#define INODE_IS_CHAR(i) INODE_IS_TYPE(i, VFS_TYPE_CHAR_DEV)
|
||||
#define INODE_IS_BLOCK(i) INODE_IS_TYPE(i, VFS_TYPE_BLOCK_DEV)
|
||||
#define INODE_IS_FS(i) INODE_IS_TYPE(i, VFS_TYPE_FS_DEV)
|
||||
|
||||
#define INODE_GET_TYPE(i) ((i)->type)
|
||||
#define INODE_SET_TYPE(i,t) \
|
||||
do \
|
||||
{ \
|
||||
(i)->type = (t); \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#define INODE_SET_CHAR(i) INODE_SET_TYPE(i, VFS_TYPE_CHAR_DEV)
|
||||
#define INODE_SET_BLOCK(i) INODE_SET_TYPE(i, VFS_TYPE_BLOCK_DEV)
|
||||
#define INODE_SET_FS(i) INODE_SET_TYPE(i, VFS_TYPE_FS_DEV)
|
||||
|
||||
typedef const struct file_ops file_ops_t;
|
||||
typedef const struct fs_ops fs_ops_t;
|
||||
|
||||
union inode_ops_t {
|
||||
const file_ops_t *i_ops; /* char driver operations */
|
||||
const fs_ops_t *i_fops; /* FS operations */
|
||||
};
|
||||
|
||||
/* this structure represents inode for driver and fs*/
|
||||
typedef struct {
|
||||
union inode_ops_t ops; /* inode operations */
|
||||
void *i_arg; /* per inode private data */
|
||||
char *i_name; /* name of inode */
|
||||
int i_flags; /* flags for inode */
|
||||
uint8_t type; /* type for inode */
|
||||
uint8_t refs; /* refs for inode */
|
||||
aos_mutex_t mutex; /* mutex for inode */
|
||||
} inode_t;
|
||||
|
||||
typedef struct {
|
||||
inode_t *node; /* node for file */
|
||||
void *f_arg; /* f_arg for file */
|
||||
size_t offset; /* offset for file */
|
||||
} file_t;
|
||||
|
||||
struct pollfd;
|
||||
typedef void (*poll_notify_t)(struct pollfd *fd, void *arg);
|
||||
struct file_ops {
|
||||
int (*open) (inode_t *node, file_t *fp);
|
||||
int (*close) (file_t *fp);
|
||||
ssize_t (*read) (file_t *fp, void *buf, size_t nbytes);
|
||||
ssize_t (*write) (file_t *fp, const void *buf, size_t nbytes);
|
||||
int (*ioctl) (file_t *fp, int cmd, unsigned long arg);
|
||||
#ifdef AOS_CONFIG_VFS_POLL_SUPPORT
|
||||
int (*poll) (file_t *fp, bool flag, poll_notify_t notify, struct pollfd *fd, void *arg);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fs_ops {
|
||||
int (*open) (file_t *fp, const char *path, int flags);
|
||||
int (*close) (file_t *fp);
|
||||
ssize_t (*read) (file_t *fp, char *buf, size_t len);
|
||||
ssize_t (*write) (file_t *fp, const char *buf, size_t len);
|
||||
off_t (*lseek) (file_t *fp, off_t off, int whence);
|
||||
int (*sync) (file_t *fp);
|
||||
int (*stat) (file_t *fp, const char *path, struct stat *st);
|
||||
int (*unlink) (file_t *fp, const char *path);
|
||||
int (*rename) (file_t *fp, const char *oldpath, const char *newpath);
|
||||
aos_dir_t *(*opendir) (file_t *fp, const char *path);
|
||||
aos_dirent_t *(*readdir) (file_t *fp, aos_dir_t *dir);
|
||||
int (*closedir) (file_t *fp, aos_dir_t *dir);
|
||||
int (*mkdir) (file_t *fp, const char *path);
|
||||
int (*ioctl) (file_t *fp, int cmd, unsigned long arg);
|
||||
};
|
||||
|
||||
int inode_init(void);
|
||||
int inode_alloc(void);
|
||||
int inode_del(inode_t *node);
|
||||
inode_t *inode_open(const char *path);
|
||||
int inode_ptr_get(int fd, inode_t **node);
|
||||
int inode_avail_count(void);
|
||||
void inode_ref(inode_t *);
|
||||
void inode_unref(inode_t *);
|
||||
int inode_busy(inode_t *);
|
||||
int inode_reserve(const char *path, inode_t **inode);
|
||||
int inode_release(const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*VFS_INODE_H*/
|
||||
|
||||
25
Living_SDK/kernel/vfs/include/vfs_register.h
Normal file
25
Living_SDK/kernel/vfs/include/vfs_register.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef VFS_DRIVER_H
|
||||
#define VFS_DRIVER_H
|
||||
|
||||
#include <vfs_inode.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int aos_register_driver(const char *path, file_ops_t *fops, void *arg);
|
||||
int aos_unregister_driver(const char *path);
|
||||
|
||||
int aos_register_fs(const char *path, fs_ops_t *fops, void *arg);
|
||||
int aos_unregister_fs(const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*VFS_DRIVER_H*/
|
||||
|
||||
365
Living_SDK/kernel/vfs/select.c
Executable file
365
Living_SDK/kernel/vfs/select.c
Executable file
|
|
@ -0,0 +1,365 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <aos/aos.h>
|
||||
#include <aos/network.h>
|
||||
#include <vfs_conf.h>
|
||||
#include <vfs_err.h>
|
||||
#include <vfs_inode.h>
|
||||
#include <vfs.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <vfs_file.h>
|
||||
|
||||
#ifdef __ICCARM__
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#ifdef IO_NEED_TRAP
|
||||
#include <vfs_trap.h>
|
||||
#endif
|
||||
|
||||
extern aos_mutex_t g_vfs_mutex;
|
||||
|
||||
#if (AOS_CONFIG_VFS_POLL_SUPPORT>0)
|
||||
|
||||
#if !defined(WITH_LWIP) && !defined(WITH_SAL)&& defined(VCALL_RHINO)
|
||||
#define NEED_WAIT_IO
|
||||
#endif
|
||||
|
||||
#include <aos/network.h>
|
||||
|
||||
#ifdef CONFIG_NO_TCPIP
|
||||
|
||||
struct poll_arg {
|
||||
aos_sem_t sem;
|
||||
};
|
||||
|
||||
static void setup_fd(int fd)
|
||||
{
|
||||
}
|
||||
|
||||
static void teardown_fd(int fd)
|
||||
{
|
||||
}
|
||||
|
||||
static void vfs_poll_notify(struct pollfd *fd, void *arg)
|
||||
{
|
||||
struct poll_arg *parg = arg;
|
||||
aos_sem_signal(&parg->sem);
|
||||
}
|
||||
|
||||
static int wait_io(int maxfd, fd_set *rfds, struct poll_arg *parg, int timeout)
|
||||
{
|
||||
timeout = timeout >= 0 ? timeout : AOS_WAIT_FOREVER;
|
||||
aos_sem_wait(&parg->sem, timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_parg(struct poll_arg *parg)
|
||||
{
|
||||
aos_sem_new(&parg->sem, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_parg(struct poll_arg *parg)
|
||||
{
|
||||
aos_sem_free(&parg->sem);
|
||||
}
|
||||
#elif defined(NEED_WAIT_IO)
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#define gettid() syscall(SYS_gettid)
|
||||
|
||||
struct poll_arg {
|
||||
aos_sem_t sem;
|
||||
};
|
||||
|
||||
static void setup_fd(int fd)
|
||||
{
|
||||
int f = fcntl(fd, F_GETFL) | O_ASYNC;
|
||||
if (fcntl(fd, F_SETFL, f) < 0) {
|
||||
perror("fcntl setup");
|
||||
}
|
||||
if (fcntl(fd, F_SETOWN, gettid()) < 0) {
|
||||
perror("fcntl setown");
|
||||
}
|
||||
}
|
||||
|
||||
static void teardown_fd(int fd)
|
||||
{
|
||||
int f = fcntl(fd, F_GETFL) & ~O_ASYNC;
|
||||
if (fcntl(fd, F_SETFL, f) < 0) {
|
||||
perror("fcntl teardown");
|
||||
}
|
||||
}
|
||||
|
||||
static int wait_io(int maxfd, fd_set *rfds, struct poll_arg *parg, int timeout)
|
||||
{
|
||||
struct timeval tv = { 0 };
|
||||
int ret;
|
||||
fd_set saved_fds = *rfds;
|
||||
|
||||
/* check if already data available */
|
||||
ret = select(maxfd + 1, rfds, NULL, NULL, &tv);
|
||||
if (ret > 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
timeout = timeout >= 0 ? timeout : AOS_WAIT_FOREVER;
|
||||
ret = aos_sem_wait(&parg->sem, timeout);
|
||||
if (ret != VFS_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*rfds = saved_fds;
|
||||
ret = select(maxfd + 1, rfds, NULL, NULL, &tv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vfs_poll_notify(struct pollfd *fd, void *arg)
|
||||
{
|
||||
struct poll_arg *parg = arg;
|
||||
aos_sem_signal(&parg->sem);
|
||||
}
|
||||
|
||||
static void vfs_io_cb(int fd, void *arg)
|
||||
{
|
||||
struct poll_arg *parg = arg;
|
||||
aos_sem_signal(&parg->sem);
|
||||
}
|
||||
|
||||
void cpu_io_register(void (*f)(int, void *), void *arg);
|
||||
void cpu_io_unregister(void (*f)(int, void *), void *arg);
|
||||
static int init_parg(struct poll_arg *parg)
|
||||
{
|
||||
cpu_io_register(vfs_io_cb, parg);
|
||||
aos_sem_new(&parg->sem, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_parg(struct poll_arg *parg)
|
||||
{
|
||||
aos_sem_free(&parg->sem);
|
||||
cpu_io_unregister(vfs_io_cb, parg);
|
||||
}
|
||||
|
||||
#else
|
||||
struct poll_arg {
|
||||
int efd;
|
||||
};
|
||||
|
||||
static void vfs_poll_notify(struct pollfd *fd, void *arg)
|
||||
{
|
||||
struct poll_arg *parg = arg;
|
||||
uint64_t val = 1;
|
||||
write(parg->efd, &val, sizeof val);
|
||||
}
|
||||
|
||||
static void setup_fd(int fd)
|
||||
{
|
||||
}
|
||||
|
||||
static void teardown_fd(int fd)
|
||||
{
|
||||
}
|
||||
|
||||
static int init_parg(struct poll_arg *parg)
|
||||
{
|
||||
int efd;
|
||||
efd = eventfd(0, 0);
|
||||
|
||||
if (efd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
parg->efd = efd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void deinit_parg(struct poll_arg *parg)
|
||||
{
|
||||
close(parg->efd);
|
||||
}
|
||||
|
||||
static int wait_io(int maxfd, fd_set *rfds, struct poll_arg *parg, int timeout)
|
||||
{
|
||||
struct timeval tv = {
|
||||
.tv_sec = timeout / 1024,
|
||||
.tv_usec = (timeout % 1024) * 1024,
|
||||
};
|
||||
|
||||
FD_SET(parg->efd, rfds);
|
||||
maxfd = parg->efd > maxfd ? parg->efd : maxfd;
|
||||
return select(maxfd + 1, rfds, NULL, NULL, timeout >= 0 ? &tv : NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pre_poll(struct pollfd *fds, int nfds, fd_set *rfds, void *parg)
|
||||
{
|
||||
int i;
|
||||
int maxfd = 0;
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
struct pollfd *pfd = &fds[i];
|
||||
|
||||
pfd->revents = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
file_t *f;
|
||||
struct pollfd *pfd = &fds[i];
|
||||
|
||||
if (pfd->fd < AOS_CONFIG_VFS_FD_OFFSET) {
|
||||
setup_fd(pfd->fd);
|
||||
FD_SET(pfd->fd, rfds);
|
||||
maxfd = pfd->fd > maxfd ? pfd->fd : maxfd;
|
||||
continue;
|
||||
}
|
||||
|
||||
f = get_file(pfd->fd);
|
||||
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pfd = &fds[i];
|
||||
(f->node->ops.i_ops->poll)(f, true, vfs_poll_notify, pfd, parg);
|
||||
}
|
||||
|
||||
return maxfd;
|
||||
}
|
||||
|
||||
static int post_poll(struct pollfd *fds, int nfds)
|
||||
{
|
||||
int j;
|
||||
int ret = 0;
|
||||
|
||||
for (j = 0; j < nfds; j++) {
|
||||
file_t *f;
|
||||
struct pollfd *pfd = &fds[j];
|
||||
|
||||
if (pfd->fd < AOS_CONFIG_VFS_FD_OFFSET) {
|
||||
teardown_fd(pfd->fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
f = get_file(pfd->fd);
|
||||
|
||||
if (f == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(f->node->ops.i_ops->poll)(f, false, NULL, NULL, NULL);
|
||||
|
||||
if (pfd->revents) {
|
||||
ret ++;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_poll(struct pollfd *fds, int nfds, int timeout)
|
||||
{
|
||||
fd_set rfds;
|
||||
|
||||
int ret = VFS_SUCCESS;
|
||||
int nset = 0;
|
||||
struct poll_arg parg;
|
||||
|
||||
if (init_parg(&parg) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
ret = pre_poll(fds, nfds, &rfds, &parg);
|
||||
|
||||
if (ret < 0) {
|
||||
goto check_poll;
|
||||
}
|
||||
|
||||
ret = wait_io(ret, &rfds, &parg, timeout);
|
||||
|
||||
if (ret >= 0) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nfds; i++) {
|
||||
struct pollfd *pfd = fds + i;
|
||||
|
||||
if (FD_ISSET(pfd->fd, &rfds)) {
|
||||
pfd->revents |= POLLIN;
|
||||
}
|
||||
}
|
||||
|
||||
nset += ret;
|
||||
}
|
||||
|
||||
check_poll:
|
||||
nset += post_poll(fds, nfds);
|
||||
|
||||
deinit_parg(&parg);
|
||||
|
||||
return ret < 0 ? 0 : nset;
|
||||
}
|
||||
#endif
|
||||
|
||||
int aos_fcntl(int fd, int cmd, int val)
|
||||
{
|
||||
if (fd < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fd < AOS_CONFIG_VFS_FD_OFFSET) {
|
||||
#ifdef IO_NEED_TRAP
|
||||
return trap_fcntl(fd, cmd, val);
|
||||
#else
|
||||
return -ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aos_ioctl_in_loop(int cmd, unsigned long arg)
|
||||
{
|
||||
int err;
|
||||
int fd;
|
||||
|
||||
for (fd = AOS_CONFIG_VFS_FD_OFFSET;
|
||||
fd < AOS_CONFIG_VFS_FD_OFFSET + AOS_CONFIG_VFS_DEV_NODES; fd++) {
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
f = get_file(fd);
|
||||
|
||||
if (f == NULL) {
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_unlock(&g_vfs_mutex)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if ((node->ops.i_ops->ioctl) != NULL) {
|
||||
err = (node->ops.i_ops->ioctl)(f, cmd, arg);
|
||||
|
||||
if (err != VFS_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
16
Living_SDK/kernel/vfs/ucube.py
Normal file
16
Living_SDK/kernel/vfs/ucube.py
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
src = Split('''
|
||||
vfs.c
|
||||
select.c
|
||||
device.c
|
||||
vfs_file.c
|
||||
vfs_inode.c
|
||||
vfs_register.c
|
||||
''')
|
||||
component = aos_component('vfs', src)
|
||||
|
||||
if aos_global_config.ide != 'keil':
|
||||
component.add_comp_deps('kernel/vfs/device')
|
||||
|
||||
component.add_global_includes('include')
|
||||
|
||||
component.add_global_macros('AOS_VFS')
|
||||
591
Living_SDK/kernel/vfs/vfs.c
Executable file
591
Living_SDK/kernel/vfs/vfs.c
Executable file
|
|
@ -0,0 +1,591 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <aos/aos.h>
|
||||
#include <vfs_conf.h>
|
||||
#include <vfs_err.h>
|
||||
#include <vfs_inode.h>
|
||||
#include <vfs.h>
|
||||
#include <stdio.h>
|
||||
#include <hal/hal.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <vfs_file.h>
|
||||
|
||||
#ifdef IO_NEED_TRAP
|
||||
#include <vfs_trap.h>
|
||||
#endif
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 256
|
||||
#endif
|
||||
|
||||
static uint8_t g_vfs_init;
|
||||
aos_mutex_t g_vfs_mutex;
|
||||
|
||||
int vfs_init(void)
|
||||
{
|
||||
int ret = VFS_SUCCESS;
|
||||
|
||||
if (g_vfs_init == 1) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = aos_mutex_new(&g_vfs_mutex)) != VFS_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
inode_init();
|
||||
|
||||
g_vfs_init = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_open(const char *path, int flags)
|
||||
{
|
||||
file_t *file;
|
||||
inode_t *node;
|
||||
size_t len = 0;
|
||||
int ret = VFS_SUCCESS;
|
||||
|
||||
if (path == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
len = strlen(path);
|
||||
if (len > PATH_MAX) {
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
if ((ret = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
node = inode_open(path);
|
||||
|
||||
if (node == NULL) {
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
#ifdef IO_NEED_TRAP
|
||||
return trap_open(path, flags);
|
||||
#else
|
||||
return -ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
node->i_flags = flags;
|
||||
file = new_file(node);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
if (file == NULL) {
|
||||
return -ENFILE;
|
||||
}
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->open) != NULL) {
|
||||
ret = (node->ops.i_fops->open)(file, path, flags);
|
||||
}
|
||||
|
||||
} else {
|
||||
if ((node->ops.i_ops->open) != NULL) {
|
||||
ret = (node->ops.i_ops->open)(node, file);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != VFS_SUCCESS) {
|
||||
del_file(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return get_fd(file);
|
||||
}
|
||||
|
||||
int aos_close(int fd)
|
||||
{
|
||||
int ret = VFS_SUCCESS;
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
|
||||
f = get_file(fd);
|
||||
|
||||
if (f == NULL) {
|
||||
#ifdef IO_NEED_TRAP
|
||||
return trap_close(fd);
|
||||
#else
|
||||
return -ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->close) != NULL) {
|
||||
ret = (node->ops.i_fops->close)(f);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ((node->ops.i_ops->close) != NULL) {
|
||||
ret = (node->ops.i_ops->close)(f);
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
del_file(f);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t aos_read(int fd, void *buf, size_t nbytes)
|
||||
{
|
||||
ssize_t nread = -1;
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
|
||||
f = get_file(fd);
|
||||
|
||||
if (f == NULL) {
|
||||
#ifdef IO_NEED_TRAP
|
||||
return trap_read(fd, buf, nbytes);
|
||||
#else
|
||||
return -ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->read) != NULL) {
|
||||
nread = (node->ops.i_fops->read)(f, buf, nbytes);
|
||||
}
|
||||
} else {
|
||||
if ((node->ops.i_ops->read) != NULL) {
|
||||
nread = (node->ops.i_ops->read)(f, buf, nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
ssize_t aos_write(int fd, const void *buf, size_t nbytes)
|
||||
{
|
||||
ssize_t nwrite = -1;
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
|
||||
f = get_file(fd);
|
||||
|
||||
if (f == NULL) {
|
||||
#ifdef IO_NEED_TRAP
|
||||
return trap_write(fd, buf, nbytes);
|
||||
#else
|
||||
return -ENOENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->write) != NULL) {
|
||||
nwrite = (node->ops.i_fops->write)(f, buf, nbytes);
|
||||
}
|
||||
} else {
|
||||
if ((node->ops.i_ops->write) != NULL) {
|
||||
nwrite = (node->ops.i_ops->write)(f, buf, nbytes);
|
||||
}
|
||||
}
|
||||
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
int aos_ioctl(int fd, int cmd, unsigned long arg)
|
||||
{
|
||||
int ret = -ENOSYS;
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
|
||||
if (fd < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f = get_file(fd);
|
||||
|
||||
if (f == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->ioctl) != NULL) {
|
||||
ret = (node->ops.i_fops->ioctl)(f, cmd, arg);
|
||||
}
|
||||
} else {
|
||||
if ((node->ops.i_ops->ioctl) != NULL) {
|
||||
ret = (node->ops.i_ops->ioctl)(f, cmd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
off_t aos_lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
f = get_file(fd);
|
||||
|
||||
if (f == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->lseek) != NULL) {
|
||||
ret = (node->ops.i_fops->lseek)(f, offset, whence);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_sync(int fd)
|
||||
{
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
int ret = -ENOSYS;
|
||||
|
||||
f = get_file(fd);
|
||||
|
||||
if (f == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->sync) != NULL) {
|
||||
ret = (node->ops.i_fops->sync)(f);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_stat(const char *path, struct stat *st)
|
||||
{
|
||||
file_t *file;
|
||||
inode_t *node;
|
||||
int err, ret = -ENOSYS;
|
||||
|
||||
if (path == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
node = inode_open(path);
|
||||
|
||||
if (node == NULL) {
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
file = new_file(node);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
if (file == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->stat) != NULL) {
|
||||
ret = (node->ops.i_fops->stat)(file, path, st);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
del_file(file);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_unlink(const char *path)
|
||||
{
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
int err, ret = -ENOSYS;
|
||||
|
||||
if (path == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
node = inode_open(path);
|
||||
|
||||
if (node == NULL) {
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
f = new_file(node);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
if (f == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->unlink) != NULL) {
|
||||
ret = (node->ops.i_fops->unlink)(f, path);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
del_file(f);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
int err, ret = -ENOSYS;
|
||||
|
||||
if (oldpath == NULL || newpath == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
node = inode_open(oldpath);
|
||||
|
||||
if (node == NULL) {
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
f = new_file(node);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
if (f == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->rename) != NULL) {
|
||||
ret = (node->ops.i_fops->rename)(f, oldpath, newpath);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
del_file(f);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
aos_dir_t *aos_opendir(const char *path)
|
||||
{
|
||||
file_t *file;
|
||||
inode_t *node;
|
||||
aos_dir_t *dp = NULL;
|
||||
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = inode_open(path);
|
||||
|
||||
if (node == NULL) {
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file = new_file(node);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
if (file == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->opendir) != NULL) {
|
||||
dp = (node->ops.i_fops->opendir)(file, path);
|
||||
}
|
||||
}
|
||||
|
||||
if (dp == NULL) {
|
||||
if (aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
del_file(file);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dp->dd_vfs_fd = get_fd(file);
|
||||
return dp;
|
||||
}
|
||||
|
||||
int aos_closedir(aos_dir_t *dir)
|
||||
{
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
int err, ret = -ENOSYS;
|
||||
|
||||
if (dir == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
f = get_file(dir->dd_vfs_fd);
|
||||
|
||||
if (f == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->closedir) != NULL) {
|
||||
ret = (node->ops.i_fops->closedir)(f, dir);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
del_file(f);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
aos_dirent_t *aos_readdir(aos_dir_t *dir)
|
||||
{
|
||||
file_t *f;
|
||||
inode_t *node;
|
||||
aos_dirent_t *ret = NULL;
|
||||
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f = get_file(dir->dd_vfs_fd);
|
||||
if (f == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node = f->node;
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->readdir) != NULL) {
|
||||
ret = (node->ops.i_fops->readdir)(f, dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != NULL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int aos_mkdir(const char *path)
|
||||
{
|
||||
file_t *file;
|
||||
inode_t *node;
|
||||
int err, ret = -ENOSYS;
|
||||
|
||||
if (path == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
node = inode_open(path);
|
||||
|
||||
if (node == NULL) {
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
file = new_file(node);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
|
||||
if (file == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (INODE_IS_FS(node)) {
|
||||
if ((node->ops.i_fops->mkdir) != NULL) {
|
||||
ret = (node->ops.i_fops->mkdir)(file, path);
|
||||
}
|
||||
}
|
||||
|
||||
if ((err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER)) != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
del_file(file);
|
||||
|
||||
aos_mutex_unlock(&g_vfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern uart_dev_t uart_0;
|
||||
|
||||
int32_t aos_uart_send(void *data, uint32_t size, uint32_t timeout)
|
||||
{
|
||||
return hal_uart_send(&uart_0, data, size, timeout);
|
||||
}
|
||||
|
||||
int32_t aos_uart_recv(void *data, uint32_t expect_size, uint32_t *recv_size, uint32_t timeout)
|
||||
{
|
||||
return hal_uart_recv_II(&uart_0, data, expect_size, recv_size, timeout);
|
||||
}
|
||||
32
Living_SDK/kernel/vfs/vfs.mk
Executable file
32
Living_SDK/kernel/vfs/vfs.mk
Executable file
|
|
@ -0,0 +1,32 @@
|
|||
NAME := vfs
|
||||
|
||||
$(NAME)_TYPE := kernel
|
||||
$(NAME)_MBINS_TYPE := kernel
|
||||
|
||||
$(NAME)_SOURCES := vfs.c
|
||||
$(NAME)_SOURCES += select.c
|
||||
$(NAME)_SOURCES += device.c
|
||||
$(NAME)_SOURCES += vfs_file.c
|
||||
$(NAME)_SOURCES += vfs_inode.c
|
||||
$(NAME)_SOURCES += vfs_register.c
|
||||
|
||||
ifeq ($(HOST_ARCH),linux)
|
||||
$(NAME)_DEFINES += IO_NEED_TRAP
|
||||
endif
|
||||
|
||||
#default gcc
|
||||
ifeq ($(COMPILER),)
|
||||
$(NAME)_CFLAGS += -Wall -Werror
|
||||
else ifeq ($(COMPILER),gcc)
|
||||
$(NAME)_CFLAGS += -Wall -Werror
|
||||
else ifeq ($(COMPILER),armcc)
|
||||
GLOBAL_DEFINES += __BSD_VISIBLE
|
||||
endif
|
||||
|
||||
GLOBAL_INCLUDES += include
|
||||
GLOBAL_DEFINES += AOS_VFS
|
||||
|
||||
ifneq ($(IDE),keil)
|
||||
$(NAME)_COMPONENTS += kernel.vfs.device
|
||||
endif
|
||||
|
||||
64
Living_SDK/kernel/vfs/vfs_file.c
Executable file
64
Living_SDK/kernel/vfs/vfs_file.c
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <aos/aos.h>
|
||||
#include <vfs_conf.h>
|
||||
#include <vfs_err.h>
|
||||
#include <vfs_inode.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAX_FILE_NUM (AOS_CONFIG_VFS_DEV_NODES * 2)
|
||||
static file_t files[MAX_FILE_NUM];
|
||||
|
||||
file_t *new_file(inode_t *node)
|
||||
{
|
||||
file_t *f;
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < MAX_FILE_NUM; idx++) {
|
||||
f = &files[idx];
|
||||
|
||||
if (f->node == NULL) {
|
||||
goto got_file;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
got_file:
|
||||
f->node = node;
|
||||
f->f_arg = NULL;
|
||||
f->offset = 0;
|
||||
inode_ref(node);
|
||||
return f;
|
||||
}
|
||||
|
||||
void del_file(file_t *file)
|
||||
{
|
||||
inode_unref(file->node);
|
||||
file->node = NULL;
|
||||
}
|
||||
|
||||
int get_fd(file_t *file)
|
||||
{
|
||||
return (file - files) + AOS_CONFIG_VFS_FD_OFFSET;
|
||||
}
|
||||
|
||||
file_t *get_file(int fd)
|
||||
{
|
||||
file_t *f;
|
||||
|
||||
fd -= AOS_CONFIG_VFS_FD_OFFSET;
|
||||
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fd >= MAX_FILE_NUM) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f = &files[fd];
|
||||
return f->node ? f : NULL;
|
||||
}
|
||||
189
Living_SDK/kernel/vfs/vfs_inode.c
Executable file
189
Living_SDK/kernel/vfs/vfs_inode.c
Executable file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <vfs_conf.h>
|
||||
#include <vfs_err.h>
|
||||
#include <vfs_inode.h>
|
||||
#include <aos/aos.h>
|
||||
|
||||
#define VFS_NULL_PARA_CHK(para) do { if (!(para)) return -EINVAL; } while(0)
|
||||
|
||||
static inode_t g_vfs_dev_nodes[AOS_CONFIG_VFS_DEV_NODES];
|
||||
|
||||
int inode_init()
|
||||
{
|
||||
memset(g_vfs_dev_nodes, 0, sizeof(inode_t) * AOS_CONFIG_VFS_DEV_NODES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inode_alloc()
|
||||
{
|
||||
int e = 0;
|
||||
|
||||
for (; e < AOS_CONFIG_VFS_DEV_NODES; e++) {
|
||||
if (g_vfs_dev_nodes[e].type == VFS_TYPE_NOT_INIT) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int inode_del(inode_t *node)
|
||||
{
|
||||
if (node->refs > 0) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (node->refs == 0) {
|
||||
if (node->i_name != NULL) {
|
||||
aos_free(node->i_name);
|
||||
}
|
||||
|
||||
node->i_name = NULL;
|
||||
node->i_arg = NULL;
|
||||
node->i_flags = 0;
|
||||
node->type = VFS_TYPE_NOT_INIT;
|
||||
}
|
||||
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
|
||||
inode_t *inode_open(const char *path)
|
||||
{
|
||||
int e = 0;
|
||||
inode_t *node;
|
||||
|
||||
for (; e < AOS_CONFIG_VFS_DEV_NODES; e++) {
|
||||
node = &g_vfs_dev_nodes[e];
|
||||
if (node == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (node->i_name == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (INODE_IS_TYPE(node, VFS_TYPE_FS_DEV)) {
|
||||
if ((strncmp(node->i_name, path, strlen(node->i_name)) == 0) &&
|
||||
(*(path + strlen(node->i_name)) == '/')) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
if (strcmp(node->i_name, path) == 0) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int inode_ptr_get(int fd, inode_t **node)
|
||||
{
|
||||
if (fd < 0 || fd >= AOS_CONFIG_VFS_DEV_NODES) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*node = &g_vfs_dev_nodes[fd];
|
||||
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
|
||||
void inode_ref(inode_t *node)
|
||||
{
|
||||
node->refs++;
|
||||
}
|
||||
|
||||
void inode_unref(inode_t *node)
|
||||
{
|
||||
if (node->refs > 0) {
|
||||
node->refs--;
|
||||
}
|
||||
}
|
||||
|
||||
int inode_busy(inode_t *node)
|
||||
{
|
||||
return node->refs > 0;
|
||||
}
|
||||
|
||||
int inode_avail_count(void)
|
||||
{
|
||||
int count = 0;
|
||||
int e = 0;
|
||||
|
||||
for (; e < AOS_CONFIG_VFS_DEV_NODES; e++) {
|
||||
if (g_vfs_dev_nodes[count].type == VFS_TYPE_NOT_INIT) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int inode_set_name(const char *path, inode_t **inode)
|
||||
{
|
||||
size_t len;
|
||||
void *mem;
|
||||
|
||||
len = strlen(path);
|
||||
mem = (void *)aos_malloc(len + 1);
|
||||
if (!mem) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(mem, (const void *)path, len);
|
||||
(*inode)->i_name = (char *)mem;
|
||||
(*inode)->i_name[len] = '\0';
|
||||
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
|
||||
int inode_reserve(const char *path, inode_t **inode)
|
||||
{
|
||||
int ret;
|
||||
inode_t *node = NULL;
|
||||
|
||||
VFS_NULL_PARA_CHK(path != NULL && inode != NULL);
|
||||
*inode = NULL;
|
||||
|
||||
/* Handle paths that are interpreted as the root directory */
|
||||
if (path[0] == '\0' || path[0] != '/') {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = inode_alloc();
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
inode_ptr_get(ret, &node);
|
||||
|
||||
ret = inode_set_name(path, &node);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*inode = node;
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
|
||||
int inode_release(const char *path)
|
||||
{
|
||||
int ret;
|
||||
inode_t *node;
|
||||
|
||||
VFS_NULL_PARA_CHK(path != NULL);
|
||||
|
||||
node = inode_open(path);
|
||||
if (node == NULL) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = inode_del(node);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return VFS_SUCCESS;
|
||||
}
|
||||
|
||||
118
Living_SDK/kernel/vfs/vfs_register.c
Normal file
118
Living_SDK/kernel/vfs/vfs_register.c
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <aos/aos.h>
|
||||
#include <vfs_conf.h>
|
||||
#include <vfs_err.h>
|
||||
#include <vfs_register.h>
|
||||
|
||||
extern aos_mutex_t g_vfs_mutex;
|
||||
|
||||
int aos_register_driver(const char *path, file_ops_t *ops, void *arg)
|
||||
{
|
||||
inode_t *node = NULL;
|
||||
int err, ret;
|
||||
|
||||
err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ret = inode_reserve(path, &node);
|
||||
if (ret == VFS_SUCCESS) {
|
||||
/* now populate it with char specific information */
|
||||
INODE_SET_CHAR(node);
|
||||
|
||||
node->ops.i_ops = ops;
|
||||
node->i_arg = arg;
|
||||
|
||||
/* creat device lock. */
|
||||
ret = aos_mutex_new(&node->mutex);
|
||||
}
|
||||
|
||||
/* step out critical area for type is allocated */
|
||||
err = aos_mutex_unlock(&g_vfs_mutex);
|
||||
if (err != 0) {
|
||||
if (node->i_name != NULL) {
|
||||
aos_free(node->i_name);
|
||||
}
|
||||
|
||||
memset(node, 0, sizeof(inode_t));
|
||||
return err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_unregister_driver(const char *path)
|
||||
{
|
||||
int err, ret;
|
||||
|
||||
err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ret = inode_release(path);
|
||||
|
||||
err = aos_mutex_unlock(&g_vfs_mutex);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_register_fs(const char *path, fs_ops_t *ops, void *arg)
|
||||
{
|
||||
inode_t *node = NULL;
|
||||
int err, ret;
|
||||
|
||||
err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ret = inode_reserve(path, &node);
|
||||
if (ret == VFS_SUCCESS) {
|
||||
INODE_SET_FS(node);
|
||||
|
||||
node->ops.i_fops = ops;
|
||||
node->i_arg = arg;
|
||||
}
|
||||
|
||||
err = aos_mutex_unlock(&g_vfs_mutex );
|
||||
if (err != 0) {
|
||||
if (node->i_name != NULL) {
|
||||
aos_free(node->i_name);
|
||||
}
|
||||
|
||||
memset(node, 0, sizeof(inode_t));
|
||||
return err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int aos_unregister_fs(const char *path)
|
||||
{
|
||||
int err, ret;
|
||||
|
||||
err = aos_mutex_lock(&g_vfs_mutex, AOS_WAIT_FOREVER);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
ret = inode_release(path);
|
||||
|
||||
err = aos_mutex_unlock(&g_vfs_mutex);
|
||||
if (err != 0) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue