rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

View 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

View 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/

View 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/')

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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

View 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

View 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

View 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 */

View 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

View 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*/

View 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
View 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;
}

View 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
View 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
View 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

View 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
View 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;
}

View 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;
}