fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088
Fork of mbed-src by
cpp/stdio.cpp
- Committer:
- mbed_official
- Date:
- 2012-11-20
- Revision:
- 0:fd0d7bdfcdc2
- Child:
- 1:62685faffa05
File content as of revision 0:fd0d7bdfcdc2:
/* mbed Microcontroller Library * Copyright (c) 2006-2012 ARM Limited * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "platform.h" #include "FileHandle.h" #include "FileSystemLike.h" #include "serial_api.h" #include <errno.h> #ifdef __ARMCC_VERSION # include <rt_sys.h> # define PREFIX(x) _sys##x # define OPEN_MAX _SYS_OPEN # ifdef __MICROLIB # pragma import(__use_full_stdio) # endif #else # include <sys/stat.h> # include <sys/unistd.h> # include <sys/syslimits.h> # define PREFIX(x) x #endif using namespace mbed; extern const char __stdin_name[] = "/stdin"; extern const char __stdout_name[] = "/stdout"; extern const char __stderr_name[] = "/stderr"; /* newlib has the filehandle field in the FILE struct as a short, so * we can't just return a Filehandle* from _open and instead have to * put it in a filehandles array and return the index into that array * (or rather index+3, as filehandles 0-2 are stdin/out/err). */ static FileHandle *filehandles[OPEN_MAX]; FileHandle::~FileHandle() { /* Remove all open filehandles for this */ for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { if (filehandles[fh_i] == this) { filehandles[fh_i] = NULL; } } } #if DEVICE_SERIAL extern int stdio_uart_inited; extern serial_t stdio_uart; #endif static void init_serial() { #if DEVICE_SERIAL if (stdio_uart_inited) return; serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); serial_format(&stdio_uart, 8, ParityNone, 1); serial_baud(&stdio_uart, 9600); #endif } #ifdef __ARMCC_VERSION static int rvct_openmode_to_posix(int openmode) { /* RVCT openmode -> POSIX flags */ int tmpmode = openmode; if (tmpmode & OPEN_PLUS) { openmode = O_RDWR; } else if(tmpmode & OPEN_W) { openmode = O_WRONLY; } else if(tmpmode & OPEN_A) { openmode = O_WRONLY|O_APPEND; } else { openmode = O_RDONLY; } /* a, w, a+, w+ all create if file does not already exist */ if (tmpmode & (OPEN_A|OPEN_W)) { openmode |= O_CREAT; } /* w and w+ truncate */ if (tmpmode & OPEN_W) { openmode |= O_TRUNC; } return openmode; } #endif extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) { /* Use the posix convention that stdin,out,err are filehandles 0,1,2. */ if (std::strcmp(name, __stdin_name) == 0) { init_serial(); return 0; } else if (std::strcmp(name, __stdout_name) == 0) { init_serial(); return 1; } else if (std::strcmp(name,__stderr_name) == 0) { init_serial(); return 2; } // find the first empty slot in filehandles unsigned int fh_i; for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { if (filehandles[fh_i] == NULL) break; } if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) { return -1; } FileHandle *res; /* FILENAME: ":0x12345678" describes a FileLike* */ if (name[0] == ':') { void *p; sscanf(name, ":%p", &p); res = (FileHandle*)p; /* FILENAME: "/file_system/file_name" */ } else { FilePath path(name); FileSystemLike *fs = path.fileSystem(); if (fs == NULL) return -1; #ifdef __ARMCC_VERSION openmode = rvct_openmode_to_posix(openmode); #endif res = fs->open(path.fileName(), openmode); /* NULL if fails */ } if (res == NULL) return -1; filehandles[fh_i] = res; return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err } extern "C" int PREFIX(_close)(FILEHANDLE fh) { if (fh < 3) return 0; FileHandle* fhc = filehandles[fh-3]; filehandles[fh-3] = NULL; if (fhc == NULL) return -1; return fhc->close(); } extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char* buffer, unsigned int length, int mode) { int n; // n is the number of bytes written if (fh < 3) { #if DEVICE_SERIAL if (!stdio_uart_inited) init_serial(); for (unsigned int i = 0; i < length; i++) { serial_putc(&stdio_uart, buffer[i]); } #endif n = length; } else { FileHandle* fhc = filehandles[fh-3]; if (fhc == NULL) return -1; n = fhc->write(buffer, length); } #ifdef __ARMCC_VERSION return length-n; #else return n; #endif } extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char* buffer, unsigned int length, int mode) { int n; // n is the number of bytes read if (fh < 3) { // only read a character at a time from stdin #if DEVICE_SERIAL *buffer = serial_getc(&stdio_uart); #endif n = 1; } else { FileHandle* fhc = filehandles[fh-3]; if (fhc == NULL) return -1; n = fhc->read(buffer, length); } #ifdef __ARMCC_VERSION return length-n; #else return n; #endif } #ifdef __ARMCC_VERSION extern "C" int PREFIX(_istty)(FILEHANDLE fh) #else extern "C" int isatty(FILEHANDLE fh) #endif { /* stdin, stdout and stderr should be tty */ if (fh < 3) return 1; FileHandle* fhc = filehandles[fh-3]; if (fhc == NULL) return -1; return fhc->isatty(); } #ifdef __ARMCC_VERSION extern "C" int PREFIX(_seek)(FILEHANDLE fh, long position) { if (fh < 3) return 0; FileHandle* fhc = filehandles[fh-3]; if (fhc == NULL || fhc->lseek(position, SEEK_SET) == -1) return -1; return 0; } #else extern "C" int _lseek(FILEHANDLE fh, int offset, int whence) { if (fh < 3) return 0; FileHandle *fhc = filehandles[fh-3]; if (fhc == NULL) return -1; return fhc->lseek(offset, whence); } #endif #ifdef __ARMCC_VERSION extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { if (fh < 3) return 0; FileHandle* fhc = filehandles[fh-3]; if (fhc == NULL) return -1; return fhc->fsync(); } extern "C" long PREFIX(_flen)(FILEHANDLE fh) { if (fh < 3) return 0; FileHandle* fhc = filehandles[fh-3]; if (fhc == NULL) return -1; return fhc->flen(); } #endif #ifndef __ARMCC_VERSION extern "C" int _fstat(int fd, struct stat *st) { if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) { st->st_mode = S_IFCHR; return 0; } errno = EBADF; return -1; } #endif namespace std { extern "C" int remove(const char *path) { FileSystemLike *fs = FilePath::getFileSystem(path); if (fs == NULL) return -1; return fs->remove(path); } extern "C" int rename(const char *oldname, const char *newname) { return -1; } extern "C" char *tmpnam(char *s) { return NULL; } extern "C" FILE *tmpfile() { return NULL; } } // namespace std #ifdef __ARMCC_VERSION extern "C" char *_sys_command_string(char *cmd, int len) { return NULL; } #endif extern "C" DIR *opendir(const char *path) { /* root dir is FileSystemLike */ if (path[0] == '/' && path[1] == 0) { return FileSystemLike::opendir(); } FileSystemLike *fs = FilePath::getFileSystem(path); if (fs == NULL) return NULL; return fs->opendir(path); } extern "C" struct dirent *readdir(DIR *dir) { return dir->readdir(); } extern "C" int closedir(DIR *dir) { return dir->closedir(); } extern "C" void rewinddir(DIR *dir) { dir->rewinddir(); } extern "C" off_t telldir(DIR *dir) { return dir->telldir(); } extern "C" void seekdir(DIR *dir, off_t off) { dir->seekdir(off); } extern "C" int mkdir(const char *path, mode_t mode) { FileSystemLike *fs = FilePath::getFileSystem(path); if (fs == NULL) return -1; return fs->mkdir(path, mode); } #if defined(TOOLCHAIN_GCC_CR) || defined(TOOLCHAIN_GCC_CS) || defined(TOOLCHAIN_GCC_ARM) /* prevents the exception handling name demangling code getting pulled in */ #include "error.h" namespace __gnu_cxx { void __verbose_terminate_handler() { error("Exception"); } } #endif // Make sure we are pulling in the retargeting module at link time volatile int stdio_retargeting_module;