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 mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stdio.cpp Source File

stdio.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "platform.h"
00017 #include "FileHandle.h"
00018 #include "FileSystemLike.h"
00019 #include "FilePath.h"
00020 #include "serial_api.h"
00021 #include <errno.h>
00022 
00023 #if defined(__ARMCC_VERSION)
00024 #   include <rt_sys.h>
00025 #   define PREFIX(x)    _sys##x
00026 #   define OPEN_MAX     _SYS_OPEN
00027 #   ifdef __MICROLIB
00028 #       pragma import(__use_full_stdio)
00029 #   endif
00030 
00031 #elif defined(__ICCARM__)
00032 #   include <yfuns.h>
00033 #   define PREFIX(x)        _##x
00034 #   define OPEN_MAX         16
00035 
00036 #   define STDIN_FILENO     0
00037 #   define STDOUT_FILENO    1
00038 #   define STDERR_FILENO    2
00039 
00040 #else
00041 #   include <sys/stat.h>
00042 #   include <sys/unistd.h>
00043 #   include <sys/syslimits.h>
00044 #   define PREFIX(x)    x
00045 #endif
00046 
00047 using namespace mbed;
00048 
00049 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
00050 // Before version 5.03, we were using a patched version of microlib with proper names
00051 extern const char __stdin_name[]  = ":tt";
00052 extern const char __stdout_name[] = ":tt";
00053 extern const char __stderr_name[] = ":tt";
00054 
00055 #else
00056 extern const char __stdin_name[]  = "/stdin";
00057 extern const char __stdout_name[] = "/stdout";
00058 extern const char __stderr_name[] = "/stderr";
00059 #endif
00060 
00061 /* newlib has the filehandle field in the FILE struct as a short, so
00062  * we can't just return a Filehandle* from _open and instead have to
00063  * put it in a filehandles array and return the index into that array
00064  * (or rather index+3, as filehandles 0-2 are stdin/out/err).
00065  */
00066 static FileHandle *filehandles[OPEN_MAX];
00067 
00068 FileHandle::~FileHandle() {
00069     /* Remove all open filehandles for this */
00070     for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
00071         if (filehandles[fh_i] == this) {
00072             filehandles[fh_i] = NULL;
00073         }
00074     }
00075 }
00076 
00077 #if DEVICE_SERIAL
00078 extern int stdio_uart_inited;
00079 extern serial_t stdio_uart;
00080 #endif
00081 
00082 static void init_serial() {
00083 #if DEVICE_SERIAL
00084     if (stdio_uart_inited) return;
00085     serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
00086 #endif
00087 }
00088 
00089 static inline int openmode_to_posix(int openmode) {
00090     int posix = openmode;
00091 #ifdef __ARMCC_VERSION
00092     if (openmode & OPEN_PLUS) {
00093         posix = O_RDWR;
00094     } else if(openmode & OPEN_W) {
00095         posix = O_WRONLY;
00096     } else if(openmode & OPEN_A) {
00097         posix = O_WRONLY|O_APPEND;
00098     } else {
00099         posix = O_RDONLY;
00100     }
00101     /* a, w, a+, w+ all create if file does not already exist */
00102     if (openmode & (OPEN_A|OPEN_W)) {
00103         posix |= O_CREAT;
00104     }
00105     /* w and w+ truncate */
00106     if (openmode & OPEN_W) {
00107         posix |= O_TRUNC;
00108     }
00109 #elif defined(__ICCARM__)
00110     switch (openmode & _LLIO_RDWRMASK) {
00111         case _LLIO_RDONLY: posix = O_RDONLY; break;
00112         case _LLIO_WRONLY: posix = O_WRONLY; break;
00113         case _LLIO_RDWR  : posix = O_RDWR  ; break;
00114     }
00115     if (openmode & _LLIO_CREAT ) posix |= O_CREAT;
00116     if (openmode & _LLIO_APPEND) posix |= O_APPEND;
00117     if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC;
00118 #endif
00119     return posix;
00120 }
00121 
00122 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
00123     /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
00124      */
00125     if (std::strcmp(name, __stdin_name) == 0) {
00126         init_serial();
00127         return 0;
00128     } else if (std::strcmp(name, __stdout_name) == 0) {
00129         init_serial();
00130         return 1;
00131     } else if (std::strcmp(name, __stderr_name) == 0) {
00132         init_serial();
00133         return 2;
00134     }
00135 
00136     // find the first empty slot in filehandles
00137     unsigned int fh_i;
00138     for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
00139         if (filehandles[fh_i] == NULL) break;
00140     }
00141     if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) {
00142         return -1;
00143     }
00144 
00145     FileHandle *res;
00146 
00147     /* FILENAME: ":0x12345678" describes a FileLike* */
00148     if (name[0] == ':') {
00149         void *p;
00150         sscanf(name, ":%p", &p);
00151         res = (FileHandle*)p;
00152 
00153     /* FILENAME: "/file_system/file_name" */
00154     } else {
00155         FilePath path(name);
00156 
00157         if (path.isFile()) {
00158             res = path.file();
00159         } else {
00160             FileSystemLike *fs = path.fileSystem();
00161             if (fs == NULL) return -1;
00162             int posix_mode = openmode_to_posix(openmode);
00163             res = fs->open(path.fileName(), posix_mode); /* NULL if fails */
00164         }
00165     }
00166 
00167     if (res == NULL) return -1;
00168     filehandles[fh_i] = res;
00169 
00170     return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err
00171 }
00172 
00173 extern "C" int PREFIX(_close)(FILEHANDLE fh) {
00174     if (fh < 3) return 0;
00175 
00176     FileHandle* fhc = filehandles[fh-3];
00177     filehandles[fh-3] = NULL;
00178     if (fhc == NULL) return -1;
00179 
00180     return fhc->close();
00181 }
00182 
00183 #if defined(__ICCARM__)
00184 extern "C" size_t    __write (int        fh, const unsigned char *buffer, size_t length) {
00185 #else
00186 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) {
00187 #endif
00188     int n; // n is the number of bytes written
00189     if (fh < 3) {
00190 #if DEVICE_SERIAL
00191         if (!stdio_uart_inited) init_serial();
00192         for (unsigned int i = 0; i < length; i++) {
00193             serial_putc(&stdio_uart, buffer[i]);
00194         }
00195 #endif
00196         n = length;
00197     } else {
00198         FileHandle* fhc = filehandles[fh-3];
00199         if (fhc == NULL) return -1;
00200 
00201         n = fhc->write(buffer, length);
00202     }
00203 #ifdef __ARMCC_VERSION
00204     return length-n;
00205 #else
00206     return n;
00207 #endif
00208 }
00209 
00210 #if defined(__ICCARM__)
00211 extern "C" size_t    __read (int        fh, unsigned char *buffer, size_t       length) {
00212 #else
00213 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) {
00214 #endif
00215     int n; // n is the number of bytes read
00216     if (fh < 3) {
00217         // only read a character at a time from stdin
00218 #if DEVICE_SERIAL
00219         *buffer = serial_getc(&stdio_uart);
00220 #endif
00221         n = 1;
00222     } else {
00223         FileHandle* fhc = filehandles[fh-3];
00224         if (fhc == NULL) return -1;
00225 
00226         n = fhc->read(buffer, length);
00227     }
00228 #ifdef __ARMCC_VERSION
00229     return length-n;
00230 #else
00231     return n;
00232 #endif
00233 }
00234 
00235 #ifdef __ARMCC_VERSION
00236 extern "C" int PREFIX(_istty)(FILEHANDLE fh)
00237 #else
00238 extern "C" int _isatty(FILEHANDLE fh)
00239 #endif
00240 {
00241     /* stdin, stdout and stderr should be tty */
00242     if (fh < 3) return 1;
00243 
00244     FileHandle* fhc = filehandles[fh-3];
00245     if (fhc == NULL) return -1;
00246 
00247     return fhc->isatty();
00248 }
00249 
00250 extern "C"
00251 #if defined(__ARMCC_VERSION)
00252 int _sys_seek(FILEHANDLE fh, long position)
00253 #elif defined(__ICCARM__)
00254 long __lseek(int fh, long offset, int whence)
00255 #else
00256 int _lseek(FILEHANDLE fh, int offset, int whence)
00257 #endif
00258 {
00259     if (fh < 3) return 0;
00260 
00261     FileHandle* fhc = filehandles[fh-3];
00262     if (fhc == NULL) return -1;
00263 
00264 #if defined(__ARMCC_VERSION)
00265     return fhc->lseek(position, SEEK_SET);
00266 #else
00267     return fhc->lseek(offset, whence);
00268 #endif
00269 }
00270 
00271 #ifdef __ARMCC_VERSION
00272 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) {
00273     if (fh < 3) return 0;
00274 
00275     FileHandle* fhc = filehandles[fh-3];
00276     if (fhc == NULL) return -1;
00277 
00278     return fhc->fsync();
00279 }
00280 
00281 extern "C" long PREFIX(_flen)(FILEHANDLE fh) {
00282     if (fh < 3) return 0;
00283 
00284     FileHandle* fhc = filehandles[fh-3];
00285     if (fhc == NULL) return -1;
00286 
00287     return fhc->flen();
00288 }
00289 #endif
00290 
00291 
00292 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
00293 extern "C" int _fstat(int fd, struct stat *st) {
00294     if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) {
00295         st->st_mode = S_IFCHR;
00296         return  0;
00297     }
00298 
00299     errno = EBADF;
00300     return -1;
00301 }
00302 #endif
00303 
00304 namespace std {
00305 extern "C" int remove(const char *path) {
00306     FilePath fp(path);
00307     FileSystemLike *fs = fp.fileSystem();
00308     if (fs == NULL) return -1;
00309 
00310     return fs->remove(fp.fileName());
00311 }
00312 
00313 extern "C" int rename(const char *oldname, const char *newname) {
00314     return -1;
00315 }
00316 
00317 extern "C" char *tmpnam(char *s) {
00318     return NULL;
00319 }
00320 
00321 extern "C" FILE *tmpfile() {
00322     return NULL;
00323 }
00324 } // namespace std
00325 
00326 #ifdef __ARMCC_VERSION
00327 extern "C" char *_sys_command_string(char *cmd, int len) {
00328     return NULL;
00329 }
00330 #endif
00331 
00332 extern "C" DIR *opendir(const char *path) {
00333     /* root dir is FileSystemLike */
00334     if (path[0] == '/' && path[1] == 0) {
00335         return FileSystemLike::opendir();
00336     }
00337 
00338     FilePath fp(path);
00339     FileSystemLike* fs = fp.fileSystem();
00340     if (fs == NULL) return NULL;
00341 
00342     return fs->opendir(fp.fileName());
00343 }
00344 
00345 extern "C" struct dirent *readdir(DIR *dir) {
00346     return dir->readdir();
00347 }
00348 
00349 extern "C" int closedir(DIR *dir) {
00350     return dir->closedir();
00351 }
00352 
00353 extern "C" void rewinddir(DIR *dir) {
00354     dir->rewinddir();
00355 }
00356 
00357 extern "C" off_t telldir(DIR *dir) {
00358     return dir->telldir();
00359 }
00360 
00361 extern "C" void seekdir(DIR *dir, off_t off) {
00362     dir->seekdir(off);
00363 }
00364 
00365 extern "C" int mkdir(const char *path, mode_t mode) {
00366     FilePath fp(path);
00367     FileSystemLike *fs = fp.fileSystem();
00368     if (fs == NULL) return -1;
00369 
00370     return fs->mkdir(fp.fileName(), mode);
00371 }
00372 
00373 #if defined(TOOLCHAIN_GCC_CR) || defined(TOOLCHAIN_GCC_CS) || defined(TOOLCHAIN_GCC_ARM)
00374 /* prevents the exception handling name demangling code getting pulled in */
00375 #include "error.h"
00376 namespace __gnu_cxx {
00377     void __verbose_terminate_handler() {
00378         error("Exception");
00379     }
00380 }
00381 #endif