import RT-Thread@9217865c without bsp, libcpu and components/net

This commit is contained in:
Zihao Yu 2023-05-20 16:23:33 +08:00
commit e2376a3709
1414 changed files with 390370 additions and 0 deletions

View file

@ -0,0 +1,10 @@
This folder contains:
| sub-folders | description |
| ----------- | ------------------------- |
| aio | Asynchronous I/O |
| mman | Memory-Mapped I/O |
| poll | Nonblocking I/O |
| stdio | Standard Input/Output I/O |
| termios | Terminal I/O |

View file

@ -0,0 +1,15 @@
# RT-Thread building script for component
import os
from building import *
cwd = GetCurrentDir()
group = []
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')

View file

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = ['aio.c']
CPPPATH = [cwd]
group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_AIO'], CPPPATH = CPPPATH)
Return('group')

View file

@ -0,0 +1,463 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/12/30 Bernard The first version.
*/
#include <rtthread.h>
#include <rthw.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/errno.h>
#include "aio.h"
struct rt_workqueue* aio_queue = NULL;
/**
* The aio_cancel() function shall attempt to cancel one or more asynchronous I/O
* requests currently outstanding against file descriptor fildes. The aiocbp
* argument points to the asynchronous I/O control block for a particular request
* to be canceled. If aiocbp is NULL, then all outstanding cancelable asynchronous
* I/O requests against fildes shall be canceled.
*
* Normal asynchronous notification shall occur for asynchronous I/O operations
* that are successfully canceled. If there are requests that cannot be canceled,
* then the normal asynchronous completion process shall take place for those
* requests when they are completed.
*
* For requested operations that are successfully canceled, the associated error
* status shall be set to [ECANCELED] and the return status shall be -1. For
* requested operations that are not successfully canceled, the aiocbp shall not
* be modified by aio_cancel().
*
* If aiocbp is not NULL, then if fildes does not have the same value as the file
* descriptor with which the asynchronous operation was initiated, unspecified results occur.
*
* Which operations are cancelable is implementation-defined.
*/
int aio_cancel(int fd, struct aiocb *cb)
{
rt_err_t ret;
if (!cb) return -EINVAL;
if (cb->aio_fildes != fd) return -EINVAL;
ret = rt_workqueue_cancel_work_sync(aio_queue, &(cb->aio_work));
if (ret == RT_EOK)
{
errno = -ECANCELED;
return -1;
}
return 0;
}
/**
* The aio_error() function shall return the error status associated with the
* aiocb structure referenced by the aiocbp argument. The error status for an
* asynchronous I/O operation is the errno value that would be set by the corresponding
* read(), write(),
*/
int aio_error (const struct aiocb *cb)
{
if (cb)
{
return cb->aio_result;
}
return -EINVAL;
}
/**
* The aio_fsync() function shall asynchronously perform a file synchronization
* operation, as specified by the op argument, for I/O operations associated with
* the file indicated by the file descriptor aio_fildes member of the aiocb
* structure referenced by the aiocbp argument and queued at the time of the
* call to aio_fsync(). The function call shall return when the synchronization
* request has been initiated or queued to the file or device (even when the data
* cannot be synchronized immediately).
*
* option: If op is O_DSYNC, all currently queued I/O operations shall be completed
* as if by a call to fdatasync(); that is, as defined for synchronized I/O data
* integrity completion.
*
* option: If op is O_SYNC, all currently queued I/O operations shall be completed
* as if by a call to fsync(); that is, as defined for synchronized I/O file integrity
* completion. If the aio_fsync() function fails, or if the operation queued by
* aio_fsync() fails, then outstanding I/O operations are not guaranteed to have
* been completed.
*
* If aio_fsync() succeeds, then it is only the I/O that was queued at the time
* of the call to aio_fsync() that is guaranteed to be forced to the relevant
* completion state. The completion of subsequent I/O on the file descriptor is
* not guaranteed to be completed in a synchronized fashion.
*
* The aiocbp argument refers to an asynchronous I/O control block. The aiocbp
* value may be used as an argument to aio_error() and aio_return() in order to
* determine the error status and return status, respectively, of the asynchronous
* operation while it is proceeding. When the request is queued, the error status
* for the operation is [EINPROGRESS]. When all data has been successfully transferred,
* the error status shall be reset to reflect the success or failure of the operation.
* If the operation does not complete successfully, the error status for the
* operation shall be set to indicate the error. The aio_sigevent member determines
* the asynchronous notification to occur as specified in Signal Generation and
* Delivery when all operations have achieved synchronized I/O completion. All
* other members of the structure referenced by aiocbp are ignored. If the control
* block referenced by aiocbp becomes an illegal address prior to asynchronous
* I/O completion, then the behavior is undefined.
*
* If the aio_fsync() function fails or aiocbp indicates an error condition,
* data is not guaranteed to have been successfully transferred.
*/
static void aio_fync_work(struct rt_work* work, void* work_data)
{
int result;
rt_base_t level;
struct aiocb *cb = (struct aiocb*)work_data;
RT_ASSERT(cb != RT_NULL);
result = fsync(cb->aio_fildes);
/* modify result */
level = rt_hw_interrupt_disable();
if (result < 0)
cb->aio_result = errno;
else
cb->aio_result = 0;
rt_hw_interrupt_enable(level);
return ;
}
int aio_fsync(int op, struct aiocb *cb)
{
rt_base_t level;
if (!cb) return -EINVAL;
level = rt_hw_interrupt_disable();
cb->aio_result = -EINPROGRESS;
rt_hw_interrupt_enable(level);
rt_work_init(&(cb->aio_work), aio_fync_work, cb);
rt_workqueue_dowork(aio_queue, &(cb->aio_work));
return 0;
}
static void aio_read_work(struct rt_work* work, void* work_data)
{
int len;
rt_base_t level;
uint8_t *buf_ptr;
struct aiocb *cb = (struct aiocb*)work_data;
buf_ptr = (uint8_t*)cb->aio_buf;
/* seek to offset */
lseek(cb->aio_fildes, cb->aio_offset, SEEK_SET);
len = read(cb->aio_fildes, &buf_ptr[cb->aio_offset], cb->aio_nbytes);
/* modify result */
level = rt_hw_interrupt_disable();
if (len <= 0)
cb->aio_result = errno;
else
cb->aio_result = len;
rt_hw_interrupt_enable(level);
return ;
}
/**
* The aio_read() function shall read aiocbp->aio_nbytes from the file associated
* with aiocbp->aio_fildes into the buffer pointed to by aiocbp->aio_buf. The
* function call shall return when the read request has been initiated or queued
* to the file or device (even when the data cannot be delivered immediately).
*
* If prioritized I/O is supported for this file, then the asynchronous operation
* shall be submitted at a priority equal to a base scheduling priority minus
* aiocbp->aio_reqprio. If Thread Execution Scheduling is not supported, then
* the base scheduling priority is that of the calling process;
*
* otherwise, the base scheduling priority is that of the calling thread.
*
* The aiocbp value may be used as an argument to aio_error() and aio_return()
* in order to determine the error status and return status, respectively, of
* the asynchronous operation while it is proceeding. If an error condition is
* encountered during queuing, the function call shall return without having
* initiated or queued the request. The requested operation takes place at the
* absolute position in the file as given by aio_offset, as if lseek() were called
* immediately prior to the operation with an offset equal to aio_offset and a
* whence equal to SEEK_SET. After a successful call to enqueue an asynchronous
* I/O operation, the value of the file offset for the file is unspecified.
*
* The aio_sigevent member specifies the notification which occurs when the
* request is completed.
*
* The aiocbp->aio_lio_opcode field shall be ignored by aio_read().
*
* The aiocbp argument points to an aiocb structure. If the buffer pointed to by
* aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal
* address prior to asynchronous I/O completion, then the behavior is undefined.
*
* Simultaneous asynchronous operations using the same aiocbp produce undefined
* results.
*
* If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes,
* the behavior of this function shall be according to the definitions of synchronized
* I/O data integrity completion and synchronized I/O file integrity completion.
*
* For any system action that changes the process memory space while an asynchronous
* I/O is outstanding to the address range being changed, the result of that action
* is undefined.
*
* For regular files, no data transfer shall occur past the offset maximum
* established in the open file description associated with aiocbp->aio_fildes.
*
*/
int aio_read(struct aiocb *cb)
{
rt_base_t level;
if (!cb) return -EINVAL;
if (cb->aio_offset < 0) return -EINVAL;
level = rt_hw_interrupt_disable();
cb->aio_result = -EINPROGRESS;
rt_hw_interrupt_enable(level);
/* en-queue read work */
rt_work_init(&(cb->aio_work), aio_read_work, cb);
rt_workqueue_dowork(aio_queue, &(cb->aio_work));
return 0;
}
/**
* The aio_return() function shall return the return status associated with the
* aiocb structure referenced by the aiocbp argument. The return status for an
* asynchronous I/O operation is the value that would be returned by the corresponding
* read(), write(), or fsync() function call. If the error status for the operation
* is equal to [EINPROGRESS], then the return status for the operation is undefined.
* The aio_return() function may be called exactly once to retrieve the return
* status of a given asynchronous operation; thereafter, if the same aiocb structure
* is used in a call to aio_return() or aio_error(), an error may be returned.
* When the aiocb structure referred to by aiocbp is used to submit another asynchronous
* operation, then aio_return() may be successfully used to retrieve the return
* status of that operation.
*/
ssize_t aio_return(struct aiocb *cb)
{
if (cb)
{
if (cb->aio_result < 0)
rt_set_errno(cb->aio_result);
return cb->aio_result;
}
return -EINVAL;
}
/**
* The aio_suspend() function shall suspend the calling thread until at least
* one of the asynchronous I/O operations referenced by the list argument has
* completed, until a signal interrupts the function, or, if timeout is not NULL,
* until the time interval specified by timeout has passed. If any of the aiocb
* structures in the list correspond to completed asynchronous I/O operations
* (that is, the error status for the operation is not equal to [EINPROGRESS])
* at the time of the call, the function shall return without suspending the
* calling thread. The list argument is an array of pointers to asynchronous I/O
* control blocks. The nent argument indicates the number of elements in the
* array. Each aiocb structure pointed to has been used in initiating an asynchronous
* I/O request via aio_read(), aio_write(), or lio_listio(). This array may
* contain null pointers, which are ignored. If this array contains pointers
* that refer to aiocb structures that have not been used in submitting asynchronous
* I/O, the effect is undefined.
*
* If the time interval indicated in the timespec structure pointed to by timeout
* passes before any of the I/O operations referenced by list are completed, then
* aio_suspend() shall return with an error.
*/
int aio_suspend(const struct aiocb *const list[], int nent,
const struct timespec *timeout)
{
return -ENOSYS;
}
static void aio_write_work(struct rt_work* work, void* work_data)
{
rt_base_t level;
int len, oflags;
uint8_t *buf_ptr;
struct aiocb *cb = (struct aiocb*)work_data;
buf_ptr = (uint8_t*)cb->aio_buf;
/* whether seek offset */
oflags = fcntl(cb->aio_fildes, F_GETFL, 0);
if ((oflags & O_APPEND) == 0)
{
lseek(cb->aio_fildes, SEEK_SET, cb->aio_offset);
}
/* write data */
len = write(cb->aio_fildes, buf_ptr, cb->aio_nbytes);
/* modify result */
level = rt_hw_interrupt_disable();
if (len <= 0)
cb->aio_result = errno;
else
cb->aio_result = len;
rt_hw_interrupt_enable(level);
return;
}
/**
* The aio_write() function shall write aiocbp->aio_nbytes to the file associated
* with aiocbp->aio_fildes from the buffer pointed to by aiocbp->aio_buf. The
* function shall return when the write request has been initiated or, at a minimum,
* queued to the file or device.
*
* The aiocbp argument may be used as an argument to aio_error() and aio_return()
* in order to determine the error status and return status, respectively, of the
* asynchronous operation while it is proceeding.
*
* The aiocbp argument points to an aiocb structure. If the buffer pointed to by
* aiocbp->aio_buf or the control block pointed to by aiocbp becomes an illegal
* address prior to asynchronous I/O completion, then the behavior is undefined.
*
* If O_APPEND is not set for the file descriptor aio_fildes, then the requested
* operation shall take place at the absolute position in the file as given by
* aio_offset, as if lseek() were called immediately prior to the operation with
* an offset equal to aio_offset and a whence equal to SEEK_SET. If O_APPEND is
* set for the file descriptor, or if aio_fildes is associated with a device that
* is incapable of seeking, write operations append to the file in the same order
* as the calls were made, except under circumstances described in Asynchronous
* I/O. After a successful call to enqueue an asynchronous I/O operation, the value
* of the file offset for the file is unspecified.
*
* The aio_sigevent member specifies the notification which occurs when the request
* is completed.
*
* The aiocbp->aio_lio_opcode field shall be ignored by aio_write().
*
* Simultaneous asynchronous operations using the same aiocbp produce undefined
* results.
*
* If synchronized I/O is enabled on the file associated with aiocbp->aio_fildes,
* the behavior of this function shall be according to the definitions of synchronized
* I/O data integrity completion, and synchronized I/O file integrity completion.
*
* For regular files, no data transfer shall occur past the offset maximum established
* in the open file description associated with aiocbp->aio_fildes.
*/
int aio_write(struct aiocb *cb)
{
int oflags;
rt_base_t level;
if (!cb || (cb->aio_buf == NULL)) return -EINVAL;
/* check access mode */
oflags = fcntl(cb->aio_fildes, F_GETFL, 0);
if ((oflags & O_ACCMODE) != O_WRONLY ||
(oflags & O_ACCMODE) != O_RDWR)
return -EINVAL;
level = rt_hw_interrupt_disable();
cb->aio_result = -EINPROGRESS;
rt_hw_interrupt_enable(level);
rt_work_init(&(cb->aio_work), aio_write_work, cb);
rt_workqueue_dowork(aio_queue, &(cb->aio_work));
return 0;
}
/**
* The lio_listio() function shall initiate a list of I/O requests with a single
* function call.
*
* The mode argument takes one of the values LIO_WAIT or LIO_NOWAIT declared in
* <aio.h> and determines whether the function returns when the I/O operations
* have been completed, or as soon as the operations have been queued. If the
* mode argument is LIO_WAIT, the function shall wait until all I/O is complete
* and the sig argument shall be ignored.
*
* If the mode argument is LIO_NOWAIT, the function shall return immediately, and
* asynchronous notification shall occur, according to the sig argument, when all
* the I/O operations complete. If sig is NULL, then no asynchronous notification
* shall occur. If sig is not NULL, asynchronous notification occurs as specified
* in Signal Generation and Delivery when all the requests in list have completed.
*
* The I/O requests enumerated by list are submitted in an unspecified order.
*
* The list argument is an array of pointers to aiocb structures. The array contains
* nent elements. The array may contain NULL elements, which shall be ignored.
*
* If the buffer pointed to by list or the aiocb structures pointed to by the
* elements of the array list become illegal addresses before all asynchronous I/O
* completed and, if necessary, the notification is sent, then the behavior is
* undefined. If the buffers pointed to by the aio_buf member of the aiocb structure
* pointed to by the elements of the array list become illegal addresses prior to
* the asynchronous I/O associated with that aiocb structure being completed, the
* behavior is undefined.
*
* The aio_lio_opcode field of each aiocb structure specifies the operation to be
* performed. The supported operations are LIO_READ, LIO_WRITE, and LIO_NOP; these
* symbols are defined in <aio.h>. The LIO_NOP operation causes the list entry to
* be ignored. If the aio_lio_opcode element is equal to LIO_READ, then an I/O operation
* is submitted as if by a call to aio_read() with the aiocbp equal to the address
* of the aiocb structure. If the aio_lio_opcode element is equal to LIO_WRITE, then
* an I/O operation is submitted as if by a call to aio_write() with the aiocbp equal
* to the address of the aiocb structure.
*
* The aio_fildes member specifies the file descriptor on which the operation is to
* be performed.
*
* The aio_buf member specifies the address of the buffer to or from which the data
* is transferred.
*
* The aio_nbytes member specifies the number of bytes of data to be transferred.
*
* The members of the aiocb structure further describe the I/O operation to be
* performed, in a manner identical to that of the corresponding aiocb structure
* when used by the aio_read() and aio_write() functions.
*
* The nent argument specifies how many elements are members of the list; that is,
* the length of the array.
*
* The behavior of this function is altered according to the definitions of synchronized
* I/O data integrity completion and synchronized I/O file integrity completion if
* synchronized I/O is enabled on the file associated with aio_fildes.
*
* For regular files, no data transfer shall occur past the offset maximum established
* in the open file description associated with aiocbp->aio_fildes.
*
* If sig->sigev_notify is SIGEV_THREAD and sig->sigev_notify_attributes is a
* non-null pointer and the block pointed to by this pointer becomes an illegal
* address prior to all asynchronous I/O being completed, then the behavior is
* undefined.
*/
int lio_listio(int mode, struct aiocb * const list[], int nent,
struct sigevent *sig)
{
return -ENOSYS;
}
int aio_system_init(void)
{
aio_queue = rt_workqueue_create("aio", 2048, RT_THREAD_PRIORITY_MAX/2);
RT_ASSERT(aio_queue != NULL);
return 0;
}
INIT_COMPONENT_EXPORT(aio_system_init);

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/12/30 Bernard The first version.
*/
#ifndef __AIO_H__
#define __AIO_H__
#include <stdio.h>
#include <sys/signal.h>
#include <rtdevice.h>
struct aiocb
{
int aio_fildes; /* File descriptor. */
off_t aio_offset; /* File offset. */
volatile void *aio_buf; /* Location of buffer. */
size_t aio_nbytes; /* Length of transfer. */
int aio_reqprio; /* Request priority offset. */
struct sigevent aio_sigevent; /* Signal number and value. */
int aio_lio_opcode; /* Operation to be performed. */
int aio_result;
struct rt_work aio_work;
};
int aio_cancel(int fd, struct aiocb *cb);
int aio_error (const struct aiocb *cb);
int aio_fsync(int op, struct aiocb *cb);
int aio_read(struct aiocb *cb);
ssize_t aio_return(struct aiocb *cb);
int aio_suspend(const struct aiocb *const list[], int nent,
const struct timespec *timeout);
int aio_write(struct aiocb *cb);
int lio_listio(int mode, struct aiocb * const list[], int nent,
struct sigevent *sig);
#endif

View file

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = ['mman.c']
CPPPATH = [cwd]
group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_MMAN'], CPPPATH = CPPPATH)
Return('group')

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/11/30 Bernard The first version.
*/
#include <stdint.h>
#include <stdio.h>
#include <rtthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/errno.h>
#include "sys/mman.h"
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset)
{
uint8_t *mem;
if (addr)
{
mem = addr;
}
else mem = (uint8_t *)malloc(length);
if (mem)
{
off_t cur;
size_t read_bytes;
cur = lseek(fd, 0, SEEK_SET);
lseek(fd, offset, SEEK_SET);
read_bytes = read(fd, mem, length);
if (read_bytes != length)
{
if (addr == RT_NULL)
{
/* read failed */
free(mem);
mem = RT_NULL;
}
}
lseek(fd, cur, SEEK_SET);
return mem;
}
errno = ENOMEM;
return MAP_FAILED;
}
int munmap(void *addr, size_t length)
{
if (addr)
{
free(addr);
return 0;
}
return -1;
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/11/30 Bernard The first version.
*/
#ifndef __SYS_MMAN_H__
#define __SYS_MMAN_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#define MAP_FAILED ((void *) -1)
#define MAP_SHARED 0x01
#define MAP_PRIVATE 0x02
#define MAP_TYPE 0x0f
#define MAP_FIXED 0x10
#define MAP_ANON 0x20
#define MAP_ANONYMOUS MAP_ANON
#define MAP_NORESERVE 0x4000
#define MAP_GROWSDOWN 0x0100
#define MAP_DENYWRITE 0x0800
#define MAP_EXECUTABLE 0x1000
#define MAP_LOCKED 0x2000
#define MAP_POPULATE 0x8000
#define MAP_NONBLOCK 0x10000
#define MAP_STACK 0x20000
#define MAP_HUGETLB 0x40000
#define MAP_FILE 0
#define PROT_NONE 0
#define PROT_READ 1
#define PROT_WRITE 2
#define PROT_EXEC 4
#define PROT_GROWSDOWN 0x01000000
#define PROT_GROWSUP 0x02000000
#define MS_ASYNC 1
#define MS_INVALIDATE 2
#define MS_SYNC 4
#define MCL_CURRENT 1
#define MCL_FUTURE 2
#define MCL_ONFAULT 4
void *mmap (void *start, size_t len, int prot, int flags, int fd, off_t off);
int munmap (void *start, size_t len);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,17 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = []
CPPPATH = [cwd]
if GetDepend('RT_USING_POSIX_POLL'):
src += ['poll.c']
if GetDepend('RT_USING_POSIX_SELECT'):
src += ['select.c']
group = DefineGroup('POSIX', src, depend = [''], CPPPATH = CPPPATH)
Return('group')

View file

@ -0,0 +1,228 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016-12-28 Bernard first version
* 2018-03-09 Bernard Add protection for pt->triggered.
*/
#include <stdint.h>
#include <rthw.h>
#include <rtthread.h>
#include <dfs_file.h>
#include "poll.h"
struct rt_poll_node;
struct rt_poll_table
{
rt_pollreq_t req;
rt_uint32_t triggered; /* the waited thread whether triggered */
rt_thread_t polling_thread;
struct rt_poll_node *nodes;
};
struct rt_poll_node
{
struct rt_wqueue_node wqn;
struct rt_poll_table *pt;
struct rt_poll_node *next;
};
static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key)
{
struct rt_poll_node *pn;
if (key && !((rt_ubase_t)key & wait->key))
return -1;
pn = rt_container_of(wait, struct rt_poll_node, wqn);
pn->pt->triggered = 1;
return __wqueue_default_wake(wait, key);
}
static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req)
{
struct rt_poll_table *pt;
struct rt_poll_node *node;
node = (struct rt_poll_node *)rt_malloc(sizeof(struct rt_poll_node));
if (node == RT_NULL)
return;
pt = rt_container_of(req, struct rt_poll_table, req);
node->wqn.key = req->_key;
rt_list_init(&(node->wqn.list));
node->wqn.polling_thread = pt->polling_thread;
node->wqn.wakeup = __wqueue_pollwake;
node->next = pt->nodes;
node->pt = pt;
pt->nodes = node;
rt_wqueue_add(wq, &node->wqn);
}
static void poll_table_init(struct rt_poll_table *pt)
{
pt->req._proc = _poll_add;
pt->triggered = 0;
pt->nodes = RT_NULL;
pt->polling_thread = rt_thread_self();
}
static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
{
rt_int32_t timeout;
int ret = 0;
struct rt_thread *thread;
rt_base_t level;
thread = pt->polling_thread;
timeout = rt_tick_from_millisecond(msec);
level = rt_hw_interrupt_disable();
if (timeout != 0 && !pt->triggered)
{
if (rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE) == RT_EOK)
{
if (timeout > 0)
{
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));
}
rt_hw_interrupt_enable(level);
rt_schedule();
level = rt_hw_interrupt_disable();
}
}
ret = !pt->triggered;
rt_hw_interrupt_enable(level);
return ret;
}
static int do_pollfd(struct pollfd *pollfd, rt_pollreq_t *req)
{
int mask = 0;
int fd;
fd = pollfd->fd;
if (fd >= 0)
{
struct dfs_file *f = fd_get(fd);
mask = POLLNVAL;
if (f)
{
mask = POLLMASK_DEFAULT;
if (f->vnode->fops->poll)
{
req->_key = pollfd->events | POLLERR | POLLHUP;
mask = f->vnode->fops->poll(f, req);
/* dealwith the device return error -1*/
if (mask < 0)
{
pollfd->revents = 0;
return mask;
}
}
/* Mask out unneeded events. */
mask &= pollfd->events | POLLERR | POLLHUP;
}
}
pollfd->revents = mask;
return mask;
}
static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, int msec)
{
int num;
int istimeout = 0;
nfds_t n;
struct pollfd *pf;
int ret = 0;
if (msec == 0)
{
pt->req._proc = RT_NULL;
istimeout = 1;
}
while (1)
{
pf = fds;
num = 0;
pt->triggered = 0;
for (n = 0; n < nfds; n ++)
{
ret = do_pollfd(pf, &pt->req);
if(ret < 0)
{
/*dealwith the device return error -1 */
pt->req._proc = RT_NULL;
return ret;
}
else if(ret > 0)
{
num ++;
pt->req._proc = RT_NULL;
}
pf ++;
}
pt->req._proc = RT_NULL;
if (num || istimeout)
break;
if (poll_wait_timeout(pt, msec))
istimeout = 1;
}
return num;
}
static void poll_teardown(struct rt_poll_table *pt)
{
struct rt_poll_node *node, *next;
next = pt->nodes;
while (next)
{
node = next;
rt_wqueue_remove(&node->wqn);
next = node->next;
rt_free(node);
}
}
int poll(struct pollfd *fds, nfds_t nfds, int timeout)
{
int num;
struct rt_poll_table table;
poll_table_init(&table);
num = poll_do(fds, nfds, &table, timeout);
poll_teardown(&table);
return num;
}

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-09-11 Meco Man First version
*/
#ifndef __POLL_H__
#define __POLL_H__
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(POLLIN) && !defined(POLLOUT)
#define POLLIN (0x01)
#define POLLRDNORM (0x01)
#define POLLRDBAND (0x01)
#define POLLPRI (0x01)
#define POLLOUT (0x02)
#define POLLWRNORM (0x02)
#define POLLWRBAND (0x02)
#define POLLERR (0x04)
#define POLLHUP (0x08)
#define POLLNVAL (0x10)
typedef unsigned int nfds_t;
struct pollfd
{
int fd;
short events;
short revents;
};
#endif /* !defined(POLLIN) && !defined(POLLOUT) */
#define POLLMASK_DEFAULT (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
#ifdef __cplusplus
}
#endif
#endif /* __POLL_H__ */

View file

@ -0,0 +1,177 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2016-12-28 Bernard first version
*/
#include <rtthread.h>
#include <poll.h>
#include <sys/select.h>
static void fdszero(fd_set *set, int nfds)
{
fd_mask *m;
int n;
/*
The 'sizeof(fd_set)' of the system space may differ from user space,
so the actual size of the 'fd_set' is determined here with the parameter 'nfds'
*/
m = (fd_mask *)set;
for (n = 0; n < nfds; n += (sizeof(fd_mask) * 8))
{
rt_memset(m, 0, sizeof(fd_mask));
m ++;
}
}
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
{
int fd;
int npfds;
int msec;
int ndx;
int ret;
struct pollfd *pollset = RT_NULL;
/* How many pollfd structures do we need to allocate? */
for (fd = 0, npfds = 0; fd < nfds; fd++)
{
/* Check if any monitor operation is requested on this fd */
if ((readfds && FD_ISSET(fd, readfds)) ||
(writefds && FD_ISSET(fd, writefds)) ||
(exceptfds && FD_ISSET(fd, exceptfds)))
{
npfds++;
}
}
/* Allocate the descriptor list for poll() */
if (npfds > 0)
{
pollset = (struct pollfd *)rt_calloc(npfds, sizeof(struct pollfd));
if (!pollset)
{
return -1;
}
}
/* Initialize the descriptor list for poll() */
for (fd = 0, ndx = 0; fd < nfds; fd++)
{
int incr = 0;
/* The readfs set holds the set of FDs that the caller can be assured
* of reading from without blocking. Note that POLLHUP is included as
* a read-able condition. POLLHUP will be reported at the end-of-file
* or when a connection is lost. In either case, the read() can then
* be performed without blocking.
*/
if (readfds && FD_ISSET(fd, readfds))
{
pollset[ndx].fd = fd;
pollset[ndx].events |= POLLIN;
incr = 1;
}
if (writefds && FD_ISSET(fd, writefds))
{
pollset[ndx].fd = fd;
pollset[ndx].events |= POLLOUT;
incr = 1;
}
if (exceptfds && FD_ISSET(fd, exceptfds))
{
pollset[ndx].fd = fd;
incr = 1;
}
ndx += incr;
}
RT_ASSERT(ndx == npfds);
/* Convert the timeout to milliseconds */
if (timeout)
{
msec = (int)timeout->tv_sec * 1000 + (int)timeout->tv_usec / 1000;
}
else
{
msec = -1;
}
/* Then let poll do all of the real work. */
ret = poll(pollset, npfds, msec);
/* Now set up the return values */
if (readfds)
{
fdszero(readfds, nfds);
}
if (writefds)
{
fdszero(writefds, nfds);
}
if (exceptfds)
{
fdszero(exceptfds, nfds);
}
/* Convert the poll descriptor list back into selects 3 bitsets */
if (ret > 0)
{
ret = 0;
for (ndx = 0; ndx < npfds; ndx++)
{
/* Check for read conditions. Note that POLLHUP is included as a
* read condition. POLLHUP will be reported when no more data will
* be available (such as when a connection is lost). In either
* case, the read() can then be performed without blocking.
*/
if (readfds)
{
if (pollset[ndx].revents & (POLLIN | POLLHUP))
{
FD_SET(pollset[ndx].fd, readfds);
ret++;
}
}
/* Check for write conditions */
if (writefds)
{
if (pollset[ndx].revents & POLLOUT)
{
FD_SET(pollset[ndx].fd, writefds);
ret++;
}
}
/* Check for exceptions */
if (exceptfds)
{
if (pollset[ndx].revents & POLLERR)
{
FD_SET(pollset[ndx].fd, exceptfds);
ret++;
}
}
}
}
if (pollset) rt_free(pollset);
return ret;
}

View file

@ -0,0 +1,22 @@
# RT-Thread building script for component
import os
from building import *
src = []
cwd = GetCurrentDir()
CPPPATH = [cwd]
group = []
if GetDepend('RT_USING_POSIX_STDIO'):
src += ['libc.c']
group = DefineGroup('POSIX', src, depend = [''], CPPPATH = CPPPATH)
list = os.listdir(cwd)
for d in list:
path = os.path.join(cwd, d)
if os.path.isfile(os.path.join(path, 'SConscript')):
group = group + SConscript(os.path.join(d, 'SConscript'))
Return('group')

View file

@ -0,0 +1,221 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/10/15 bernard the first version
*/
#include <rtthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/errno.h>
#include "libc.h"
#define STDIO_DEVICE_NAME_MAX 32
int sys_dup2(int oldfd, int new);
int libc_system_init(void)
{
#ifdef RT_USING_POSIX_STDIO
rt_device_t dev_console;
dev_console = rt_console_get_device();
if (dev_console)
{
int fd = libc_stdio_set_console(dev_console->parent.name, O_RDWR);
if (fd < 0)
{
return -1;
}
/* set fd (0, 1, 2) */
sys_dup2(fd, 0);
sys_dup2(fd, 1);
sys_dup2(fd, 2);
}
#endif /* RT_USING_POSIX_STDIO */
return 0;
}
INIT_COMPONENT_EXPORT(libc_system_init);
#if defined(RT_USING_POSIX_STDIO) && defined(RT_USING_NEWLIBC)
static FILE* std_console = NULL;
int libc_stdio_set_console(const char* device_name, int mode)
{
FILE *fp;
char name[STDIO_DEVICE_NAME_MAX];
char *file_mode;
rt_snprintf(name, sizeof(name) - 1, "/dev/%s", device_name);
name[STDIO_DEVICE_NAME_MAX - 1] = '\0';
if (mode == O_RDWR)
{
file_mode = "r+";
}
else if (mode == O_WRONLY)
{
file_mode = "wb";
}
else
{
file_mode = "rb";
}
fp = fopen(name, file_mode);
if (fp)
{
setvbuf(fp, NULL, _IONBF, 0);
if (std_console)
{
fclose(std_console);
std_console = NULL;
}
std_console = fp;
if (mode == O_RDWR)
{
_GLOBAL_REENT->_stdin = std_console;
}
else
{
_GLOBAL_REENT->_stdin = NULL;
}
if (mode == O_RDONLY)
{
_GLOBAL_REENT->_stdout = NULL;
_GLOBAL_REENT->_stderr = NULL;
}
else
{
_GLOBAL_REENT->_stdout = std_console;
_GLOBAL_REENT->_stderr = std_console;
}
_GLOBAL_REENT->__sdidinit = 1;
}
if (std_console)
return fileno(std_console);
return -1;
}
int libc_stdio_get_console(void)
{
if (std_console)
return fileno(std_console);
else
return -1;
}
#elif defined(RT_USING_POSIX_STDIO) && defined(RT_USING_MUSLLIBC)
static FILE* std_console = NULL;
int libc_stdio_set_console(const char* device_name, int mode)
{
FILE *fp;
char name[STDIO_DEVICE_NAME_MAX];
char *file_mode;
rt_snprintf(name, sizeof(name) - 1, "/dev/%s", device_name);
name[STDIO_DEVICE_NAME_MAX - 1] = '\0';
if (mode == O_RDWR) file_mode = "r+";
else if (mode == O_WRONLY) file_mode = "wb";
else file_mode = "rb";
fp = fopen(name, file_mode);
if (fp)
{
setvbuf(fp, NULL, _IONBF, 0);
if (std_console)
{
fclose(std_console);
std_console = NULL;
}
std_console = fp;
}
if (std_console)
{
int fd = fileno(std_console);
return fd;
}
return -1;
}
int libc_stdio_get_console(void)
{
int ret = -1;
if (std_console)
{
ret = fileno(std_console);
}
return ret;
}
#elif defined(RT_USING_POSIX_STDIO)
static int std_fd = -1;
int libc_stdio_set_console(const char* device_name, int mode)
{
int fd;
char name[STDIO_DEVICE_NAME_MAX];
rt_snprintf(name, sizeof(name) - 1, "/dev/%s", device_name);
name[STDIO_DEVICE_NAME_MAX - 1] = '\0';
fd = open(name, mode, 0);
if (fd >= 0)
{
if (std_fd >= 0)
{
close(std_fd);
}
std_fd = fd;
}
return std_fd;
}
int libc_stdio_get_console(void) {
return std_fd;
}
#endif /* defined(RT_USING_POSIX_STDIO) && defined(RT_USING_NEWLIBC) */
int isatty(int fd)
{
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
if(fd == STDOUT_FILENO || fd == STDERR_FILENO)
{
return 1;
}
#endif
#ifdef RT_USING_POSIX_STDIO
if(fd == STDIN_FILENO)
{
return 1;
}
#endif
rt_set_errno(ENOTTY);
return 0;
}
RTM_EXPORT(isatty);

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/10/15 bernard the first version
*/
#ifndef __RTT_LIBC_H__
#define __RTT_LIBC_H__
#include <rtconfig.h>
#ifdef __cplusplus
extern "C" {
#endif
int libc_system_init(void);
#ifdef RT_USING_POSIX_STDIO
int libc_stdio_get_console(void);
int libc_stdio_set_console(const char* device_name, int mode);
#endif /* RT_USING_POSIX_STDIO */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,11 @@
# RT-Thread building script for component
from building import *
cwd = GetCurrentDir()
src = ['termios.c']
CPPPATH = [cwd]
group = DefineGroup('POSIX', src, depend = ['RT_USING_POSIX_TERMIOS'], CPPPATH = CPPPATH)
Return('group')

View file

@ -0,0 +1,129 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/08/30 Bernard The first version
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/errno.h>
#include "termios.h"
#include <rtthread.h>
int tcgetattr(int fd, struct termios *tio)
{
/* Get the current serial port settings. */
if (ioctl(fd, TCGETA, tio))
return -1;
return 0;
}
int tcsetattr(int fd, int act, const struct termios *tio)
{
switch (act)
{
case TCSANOW:
/* make the change immediately */
return (ioctl(fd, TCSETA, (void*)tio));
case TCSADRAIN:
/*
* Don't make the change until all currently written data
* has been transmitted.
*/
return (ioctl(fd, TCSETAW, (void*)tio));
case TCSAFLUSH:
/* Don't make the change until all currently written data
* has been transmitted, at which point any received but
* unread data is also discarded.
*/
return (ioctl(fd, TCSETAF, (void*)tio));
default:
errno = EINVAL;
return (-1);
}
}
/**
* this function gets process group ID for session leader for controlling
* terminal
*
* @return always 0
*/
pid_t tcgetsid(int fd)
{
return 0;
}
speed_t cfgetospeed(const struct termios *tio)
{
return tio->c_cflag & CBAUD;
}
speed_t cfgetispeed(const struct termios *tio)
{
return cfgetospeed(tio);
}
int cfsetospeed(struct termios *tio, speed_t speed)
{
if (speed & ~CBAUD)
{
errno = EINVAL;
return -1;
}
tio->c_cflag &= ~CBAUD;
tio->c_cflag |= speed;
return 0;
}
int cfsetispeed(struct termios *tio, speed_t speed)
{
return speed ? cfsetospeed(tio, speed) : 0;
}
int tcsendbreak(int fd, int dur)
{
/* nonzero duration is implementation-defined, so ignore it */
return 0;
}
int tcflush(int fd, int queue)
{
return ioctl(fd, TCFLSH, (void*)(rt_ubase_t)queue);
}
int tcflow(int fd, int action)
{
return ioctl(fd, TCXONC, (void*)(rt_ubase_t)action);
}
/**
* this function waits for transmission of output
*/
int tcdrain(int fd)
{
return 0;
}
void cfmakeraw(struct termios *t)
{
t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
t->c_oflag &= ~OPOST;
t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
t->c_cflag &= ~(CSIZE|PARENB);
t->c_cflag |= CS8;
t->c_cc[VMIN] = 1;
t->c_cc[VTIME] = 0;
}
int cfsetspeed(struct termios *tio, speed_t speed)
{
return cfsetospeed(tio, speed);
}

View file

@ -0,0 +1,234 @@
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017/08/30 Bernard The first version
* 2021/12/10 linzhenxing put tty system
*/
#ifndef __TERMIOS_H__
#define __TERMIOS_H__
#include <sys/types.h>
#include <sys/ioctl.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned char cc_t;
typedef unsigned int speed_t;
typedef unsigned int tcflag_t;
#define NCCS 32
struct termios {
tcflag_t c_iflag;
tcflag_t c_oflag;
tcflag_t c_cflag;
tcflag_t c_lflag;
cc_t c_line;
cc_t c_cc[NCCS];
speed_t __c_ispeed;
speed_t __c_ospeed;
};
/* c_cc characters */
#define VINTR 0
#define VQUIT 1
#define VERASE 2
#define VKILL 3
#define VEOF 4
#define VTIME 5
#define VMIN 6
#define VSWTC 7
#define VSTART 8
#define VSTOP 9
#define VSUSP 10
#define VEOL 11
#define VREPRINT 12
#define VDISCARD 13
#define VWERASE 14
#define VLNEXT 15
#define VEOL2 16
/* c_iflag bits */
#define IGNBRK 0000001
#define BRKINT 0000002
#define IGNPAR 0000004
#define PARMRK 0000010
#define INPCK 0000020
#define ISTRIP 0000040
#define INLCR 0000100
#define IGNCR 0000200
#define ICRNL 0000400
#define IUCLC 0001000
#define IXON 0002000
#define IXANY 0004000
#define IXOFF 0010000
#define IMAXBEL 0020000
#define IUTF8 0040000
/* c_oflag bits */
#define OPOST 0000001
#define ONLCR 0000002
#define OLCUC 0000004
#define OCRNL 0000010
#define ONOCR 0000020
#define ONLRET 0000040
#define OFILL 00000100
#define OFDEL 00000200
#define NLDLY 00001400
#define NL0 00000000
#define NL1 00000400
#define NL2 00001000
#define NL3 00001400
#define TABDLY 00006000
#define TAB0 00000000
#define TAB1 00002000
#define TAB2 00004000
#define TAB3 00006000
#define CRDLY 00030000
#define KCR0 00000000
#define KCR1 00010000
#define KCR2 00020000
#define KCR3 00030000
#define FFDLY 00040000
#define FF0 00000000
#define FF1 00040000
#define BSDLY 00100000
#define BS0 00000000
#define BS1 00100000
#define VTDLY 00200000
#define VT0 00000000
#define VT1 00200000
#define XTABS 01000000
#define B0 0000000
#define B50 0000001
#define B75 0000002
#define B110 0000003
#define B134 0000004
#define B150 0000005
#define B200 0000006
#define B300 0000007
#define B600 0000010
#define B1200 0000011
#define B1800 0000012
#define B2400 0000013
#define B4800 0000014
#define B9600 0000015
#define B19200 0000016
#define B38400 0000017
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define B460800 0010004
#define B500000 0010005
#define B576000 0010006
#define B921600 0010007
#define B1000000 0010010
#define B1152000 0010011
#define B1500000 0010012
#define B2000000 0010013
#define B2500000 0010014
#define B3000000 0010015
#define B3500000 0010016
#define B4000000 0010017
#define CSIZE 0000060
#define CS5 0000000
#define CS6 0000020
#define CS7 0000040
#define CS8 0000060
#define CSTOPB 0000100
#define CREAD 0000200
#define PARENB 0000400
#define PARODD 0001000
#define HUPCL 0002000
#define CLOCAL 0004000
/* c_lflag bits */
#define ISIG 0000001
#define ICANON 0000002
#define XCASE 0000004
#define ECHO 0000010
#define ECHOE 0000020
#define ECHOK 0000040
#define ECHONL 0000100
#define NOFLSH 0000200
#define TOSTOP 0000400
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define IEXTEN 0100000
#define EXTPROC 0200000
#define TCOOFF 0
#define TCOON 1
#define TCIOFF 2
#define TCION 3
#define TCIFLUSH 0
#define TCOFLUSH 1
#define TCIOFLUSH 2
#define TCSANOW 0
#define TCSADRAIN 1
#define TCSAFLUSH 2
#define EXTA 0000016
#define EXTB 0000017
#define CBAUD 0010017
#define CBAUDEX 0010000
#define CIBAUD 002003600000
#define CMSPAR 010000000000
#define CRTSCTS 020000000000
#define XCASE 0000004
#define ECHOCTL 0001000
#define ECHOPRT 0002000
#define ECHOKE 0004000
#define FLUSHO 0010000
#define PENDIN 0040000
#define EXTPROC 0200000
/* intr=^C quit=^| erase=del kill=^U
eof=^D vtime=\0 vmin=\1 sxtc=\0
start=^Q stop=^S susp=^Z eol=\0
reprint=^R discard=^U werase=^W lnext=^V
eol2=\0
*/
#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
speed_t cfgetospeed (const struct termios *);
speed_t cfgetispeed (const struct termios *);
int cfsetospeed (struct termios *, speed_t);
int cfsetispeed (struct termios *, speed_t);
int tcgetattr (int, struct termios *);
int tcsetattr (int, int, const struct termios *);
int tcsendbreak (int, int);
int tcdrain (int);
int tcflush (int, int);
int tcflow (int, int);
pid_t tcgetsid (int);
void cfmakeraw(struct termios *);
int cfsetspeed(struct termios *, speed_t);
#ifdef __cplusplus
}
#endif
#endif