Add mbed_file_handle lookup function

Add a necessary helper to allow FileHandle objects to be obtained
from POSIX file descriptors.

Primary envisaged use case is to act on STDIN_FILENO etc, eg to
set it non-blocking or use sigio, or to use the enable API.
pull/9797/head
Kevin Bracey 2019-02-21 16:46:24 +02:00
parent 649856f3ff
commit f91d044b6c
2 changed files with 36 additions and 16 deletions

View File

@ -290,7 +290,7 @@ static FileHandle *get_console(int fd)
} }
/* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */ /* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
static FileHandle *get_fhc(int fd) FileHandle *mbed::mbed_file_handle(int fd)
{ {
if (fd >= OPEN_MAX) { if (fd >= OPEN_MAX) {
return NULL; return NULL;
@ -490,13 +490,13 @@ extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags)
/* Use the posix convention that stdin,out,err are filehandles 0,1,2. /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
*/ */
if (std::strcmp(name, __stdin_name) == 0) { if (std::strcmp(name, __stdin_name) == 0) {
get_fhc(STDIN_FILENO); mbed_file_handle(STDIN_FILENO);
return STDIN_FILENO; return STDIN_FILENO;
} else if (std::strcmp(name, __stdout_name) == 0) { } else if (std::strcmp(name, __stdout_name) == 0) {
get_fhc(STDOUT_FILENO); mbed_file_handle(STDOUT_FILENO);
return STDOUT_FILENO; return STDOUT_FILENO;
} else if (std::strcmp(name, __stderr_name) == 0) { } else if (std::strcmp(name, __stderr_name) == 0) {
get_fhc(STDERR_FILENO); mbed_file_handle(STDERR_FILENO);
return STDERR_FILENO; return STDERR_FILENO;
} }
#endif #endif
@ -555,7 +555,7 @@ extern "C" int PREFIX(_close)(FILEHANDLE fh)
extern "C" int close(int fildes) extern "C" int close(int fildes)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
filehandles[fildes] = NULL; filehandles[fildes] = NULL;
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
@ -667,7 +667,7 @@ finish:
extern "C" ssize_t write(int fildes, const void *buf, size_t length) extern "C" ssize_t write(int fildes, const void *buf, size_t length)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -761,8 +761,7 @@ extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int
extern "C" ssize_t read(int fildes, void *buf, size_t length) extern "C" ssize_t read(int fildes, void *buf, size_t length)
{ {
FileHandle *fhc = mbed_file_handle(fildes);
FileHandle *fhc = get_fhc(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -789,7 +788,7 @@ extern "C" int _isatty(FILEHANDLE fh)
extern "C" int isatty(int fildes) extern "C" int isatty(int fildes)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return 0; return 0;
@ -828,7 +827,7 @@ int _lseek(FILEHANDLE fh, int offset, int whence)
extern "C" off_t lseek(int fildes, off_t offset, int whence) extern "C" off_t lseek(int fildes, off_t offset, int whence)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -844,7 +843,7 @@ extern "C" off_t lseek(int fildes, off_t offset, int whence)
extern "C" int ftruncate(int fildes, off_t length) extern "C" int ftruncate(int fildes, off_t length)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -868,7 +867,7 @@ extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
extern "C" int fsync(int fildes) extern "C" int fsync(int fildes)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -886,7 +885,7 @@ extern "C" int fsync(int fildes)
#ifdef __ARMCC_VERSION #ifdef __ARMCC_VERSION
extern "C" long PREFIX(_flen)(FILEHANDLE fh) extern "C" long PREFIX(_flen)(FILEHANDLE fh)
{ {
FileHandle *fhc = get_fhc(fh); FileHandle *fhc = mbed_file_handle(fh);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -936,7 +935,7 @@ extern "C" int _fstat(int fh, struct stat *st)
extern "C" int fstat(int fildes, struct stat *st) extern "C" int fstat(int fildes, struct stat *st)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -949,7 +948,7 @@ extern "C" int fstat(int fildes, struct stat *st)
extern "C" int fcntl(int fildes, int cmd, ...) extern "C" int fcntl(int fildes, int cmd, ...)
{ {
FileHandle *fhc = get_fhc(fildes); FileHandle *fhc = mbed_file_handle(fildes);
if (fhc == NULL) { if (fhc == NULL) {
errno = EBADF; errno = EBADF;
return -1; return -1;
@ -994,7 +993,7 @@ extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
for (nfds_t n = 0; n < nfds; n++) { for (nfds_t n = 0; n < nfds; n++) {
// Underlying FileHandle poll returns POLLNVAL if given NULL, so // Underlying FileHandle poll returns POLLNVAL if given NULL, so
// we don't need to take special action. // we don't need to take special action.
fhs[n].fh = get_fhc(fds[n].fd); fhs[n].fh = mbed_file_handle(fds[n].fd);
fhs[n].events = fds[n].events; fhs[n].events = fds[n].events;
} }
int ret = poll(fhs, nfds, timeout); int ret = poll(fhs, nfds, timeout);

View File

@ -133,6 +133,27 @@ FileHandle *mbed_target_override_console(int fd);
*/ */
FileHandle *mbed_override_console(int fd); FileHandle *mbed_override_console(int fd);
/** Look up the Mbed file handle corresponding to a file descriptor
*
* This conversion function permits an application to find the underlying
* FileHandle object corresponding to a POSIX file descriptor.
*
* This allows access to specialized behavior only available via the
* FileHandle API.
*
* Example of saving power by disabling console input - for buffered serial,
* this would release the RX interrupt handler, which would release the
* deep sleep lock.
* @code
* mbed_file_handle(STDIN_FILENO)->enable_input(false);
* @endcode
*
* @param fd file descriptor
* @return FileHandle pointer
* NULL if descriptor does not correspond to a FileHandle (only
* possible if it's not open with current implementation).
*/
FileHandle *mbed_file_handle(int fd);
} }
typedef mbed::DirHandle DIR; typedef mbed::DirHandle DIR;