├── .github └── stale.yml ├── .gitignore ├── LICENSE ├── README.md ├── lv_fs_fatfs.c ├── lv_fs_if.c ├── lv_fs_if.h ├── lv_fs_pc.c └── lv_fs_posix.c /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 21 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - architecture 8 | - pinned 9 | # Label to use when marking an issue as stale 10 | staleLabel: stale 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue or pull request has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Littlev Graphics Library 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # File System Interface 2 | 3 | **This repository is merged into the lvgl repository. See https://docs.lvgl.io/master/libs/fs.html** 4 | 5 | LVGL has a [File system](https://docs.lvgl.io/master/overview/file-system.html) module to attach memories which can manipulate with files. Here you can find interfaces to 6 | 7 | - FATFS 8 | - PC (Linux and Windows using C standard function .e.g fopen, fread) 9 | - POSIX (Linux and Windows using POSIX function .e.g open, read) 10 | file systems. 11 | 12 | You still need to provide the drivers and libraries, this repo gives "only" the bridge between FATFS/PC/etc and LittlevGL. 13 | 14 | ## Usage 15 | 1. Add these lines to you `lv_conf.h`: 16 | ```c 17 | /*File system interface*/ 18 | #define LV_USE_FS_IF 1 19 | #if LV_USE_FS_IF 20 | # define LV_FS_IF_FATFS '\0' 21 | # define LV_FS_IF_PC '\0' 22 | # define LV_FS_IF_POSIX '\0' 23 | #endif /*LV_USE_FS_IF*/ 24 | ``` 25 | 26 | 2. Enable an interface you need by changing `'\0'` to letter you want to use for that drive. E.g. `'S'` for SD card with FATFS. 27 | 28 | 3. Call `lv_fs_if_init()` (after `lv_init()`) to register the enabled interfaces. 29 | -------------------------------------------------------------------------------- /lv_fs_fatfs.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_fs_fatfs.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "lv_fs_if.h" 10 | 11 | #if LV_USE_FS_IF 12 | #if LV_FS_IF_FATFS != '\0' 13 | #include "ff.h" 14 | 15 | /********************* 16 | * DEFINES 17 | *********************/ 18 | 19 | /********************** 20 | * TYPEDEFS 21 | **********************/ 22 | 23 | /********************** 24 | * STATIC PROTOTYPES 25 | **********************/ 26 | static void fs_init(void); 27 | 28 | static void * fs_open (lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); 29 | static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p); 30 | static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); 31 | static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 32 | static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); 33 | static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); 34 | static void * fs_dir_open (lv_fs_drv_t * drv, const char *path); 35 | static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn); 36 | static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p); 37 | 38 | /********************** 39 | * STATIC VARIABLES 40 | **********************/ 41 | 42 | /********************** 43 | * MACROS 44 | **********************/ 45 | 46 | /********************** 47 | * GLOBAL FUNCTIONS 48 | **********************/ 49 | 50 | void lv_fs_if_fatfs_init(void) 51 | { 52 | /*---------------------------------------------------- 53 | * Initialize your storage device and File System 54 | * -------------------------------------------------*/ 55 | fs_init(); 56 | 57 | /*--------------------------------------------------- 58 | * Register the file system interface in LittlevGL 59 | *--------------------------------------------------*/ 60 | 61 | /* Add a simple drive to open images */ 62 | static lv_fs_drv_t fs_drv; /*A driver descriptor*/ 63 | lv_fs_drv_init(&fs_drv); 64 | 65 | /*Set up fields...*/ 66 | fs_drv.letter = LV_FS_IF_FATFS; 67 | fs_drv.open_cb = fs_open; 68 | fs_drv.close_cb = fs_close; 69 | fs_drv.read_cb = fs_read; 70 | fs_drv.write_cb = fs_write; 71 | fs_drv.seek_cb = fs_seek; 72 | fs_drv.tell_cb = fs_tell; 73 | 74 | fs_drv.dir_close_cb = fs_dir_close; 75 | fs_drv.dir_open_cb = fs_dir_open; 76 | fs_drv.dir_read_cb = fs_dir_read; 77 | 78 | lv_fs_drv_register(&fs_drv); 79 | } 80 | 81 | /********************** 82 | * STATIC FUNCTIONS 83 | **********************/ 84 | 85 | /* Initialize your Storage device and File system. */ 86 | static void fs_init(void) 87 | { 88 | /* Initialize the SD card and FatFS itself. 89 | * Better to do it in your code to keep this library utouched for easy updating*/ 90 | } 91 | 92 | /** 93 | * Open a file 94 | * @param drv pointer to a driver where this function belongs 95 | * @param file_p pointer to a file_t variable 96 | * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) 97 | * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR 98 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 99 | */ 100 | static void * fs_open (lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) 101 | { 102 | uint8_t flags = 0; 103 | 104 | if(mode == LV_FS_MODE_WR) flags = FA_WRITE | FA_OPEN_ALWAYS; 105 | else if(mode == LV_FS_MODE_RD) flags = FA_READ; 106 | else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS; 107 | 108 | FIL * f = lv_mem_alloc(sizeof(FIL)); 109 | if(f == NULL) return NULL; 110 | 111 | FRESULT res = f_open(f, path, flags); 112 | 113 | if(res == FR_OK) { 114 | f_lseek(f, 0); 115 | return f; 116 | } else { 117 | lv_mem_free(f); 118 | return NULL; 119 | } 120 | } 121 | 122 | 123 | /** 124 | * Close an opened file 125 | * @param drv pointer to a driver where this function belongs 126 | * @param file_p pointer to a file_t variable. (opened with lv_ufs_open) 127 | * @return LV_FS_RES_OK: no error, the file is read 128 | * any error from lv_fs_res_t enum 129 | */ 130 | static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p) 131 | { 132 | f_close(file_p); 133 | lv_mem_free(file_p); 134 | return LV_FS_RES_OK; 135 | } 136 | 137 | /** 138 | * Read data from an opened file 139 | * @param drv pointer to a driver where this function belongs 140 | * @param file_p pointer to a file_t variable. 141 | * @param buf pointer to a memory block where to store the read data 142 | * @param btr number of Bytes To Read 143 | * @param br the real number of read bytes (Byte Read) 144 | * @return LV_FS_RES_OK: no error, the file is read 145 | * any error from lv_fs_res_t enum 146 | */ 147 | static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) 148 | { 149 | FRESULT res = f_read(file_p, buf, btr, (UINT*)br); 150 | if(res == FR_OK) return LV_FS_RES_OK; 151 | else return LV_FS_RES_UNKNOWN; 152 | } 153 | 154 | /** 155 | * Write into a file 156 | * @param drv pointer to a driver where this function belongs 157 | * @param file_p pointer to a file_t variable 158 | * @param buf pointer to a buffer with the bytes to write 159 | * @param btr Bytes To Write 160 | * @param br the number of real written bytes (Bytes Written). NULL if unused. 161 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 162 | */ 163 | static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) 164 | { 165 | FRESULT res = f_write(file_p, buf, btw, (UINT*)bw); 166 | if(res == FR_OK) return LV_FS_RES_OK; 167 | else return LV_FS_RES_UNKNOWN; 168 | } 169 | 170 | /** 171 | * Set the read write pointer. Also expand the file size if necessary. 172 | * @param drv pointer to a driver where this function belongs 173 | * @param file_p pointer to a file_t variable. (opened with lv_ufs_open ) 174 | * @param pos the new position of read write pointer 175 | * @param whence only LV_SEEK_SET is supported 176 | * @return LV_FS_RES_OK: no error, the file is read 177 | * any error from lv_fs_res_t enum 178 | */ 179 | static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) 180 | { 181 | switch (whence) 182 | { 183 | case LV_FS_SEEK_SET: 184 | f_lseek(file_p, pos); 185 | break; 186 | case LV_FS_SEEK_CUR: 187 | f_lseek(file_p, f_tell((FIL *)file_p) + pos); 188 | break; 189 | case LV_FS_SEEK_END: 190 | f_lseek(file_p, f_size((FIL *)file_p) + pos); 191 | break; 192 | default: 193 | break; 194 | } 195 | return LV_FS_RES_OK; 196 | } 197 | 198 | /** 199 | * Give the position of the read write pointer 200 | * @param drv pointer to a driver where this function belongs 201 | * @param file_p pointer to a file_t variable. 202 | * @param pos_p pointer to to store the result 203 | * @return LV_FS_RES_OK: no error, the file is read 204 | * any error from lv_fs_res_t enum 205 | */ 206 | static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) 207 | { 208 | *pos_p = f_tell(((FIL *)file_p)); 209 | return LV_FS_RES_OK; 210 | } 211 | 212 | /** 213 | * Initialize a 'fs_read_dir_t' variable for directory reading 214 | * @param drv pointer to a driver where this function belongs 215 | * @param dir_p pointer to a 'fs_read_dir_t' variable 216 | * @param path path to a directory 217 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 218 | */ 219 | static void * fs_dir_open (lv_fs_drv_t * drv, const char *path) 220 | { 221 | DIR * d = lv_mem_alloc(sizeof(DIR)); 222 | if(d == NULL) return NULL; 223 | 224 | FRESULT res = f_opendir(d, path); 225 | if(res != FR_OK) { 226 | lv_mem_free(d); 227 | d = NULL; 228 | } 229 | return d; 230 | } 231 | 232 | /** 233 | * Read the next filename form a directory. 234 | * The name of the directories will begin with '/' 235 | * @param drv pointer to a driver where this function belongs 236 | * @param dir_p pointer to an initialized 'fs_read_dir_t' variable 237 | * @param fn pointer to a buffer to store the filename 238 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 239 | */ 240 | static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn) 241 | { 242 | FRESULT res; 243 | FILINFO fno; 244 | fn[0] = '\0'; 245 | 246 | do { 247 | res = f_readdir(dir_p, &fno); 248 | if(res != FR_OK) return LV_FS_RES_UNKNOWN; 249 | 250 | if(fno.fattrib & AM_DIR) { 251 | fn[0] = '/'; 252 | strcpy(&fn[1], fno.fname); 253 | } 254 | else strcpy(fn, fno.fname); 255 | 256 | } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); 257 | 258 | return LV_FS_RES_OK; 259 | } 260 | 261 | /** 262 | * Close the directory reading 263 | * @param drv pointer to a driver where this function belongs 264 | * @param dir_p pointer to an initialized 'fs_read_dir_t' variable 265 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 266 | */ 267 | static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p) 268 | { 269 | f_closedir(dir_p); 270 | lv_mem_free(dir_p); 271 | return LV_FS_RES_OK; 272 | } 273 | 274 | #endif /*LV_USE_FS_IF*/ 275 | #endif /*LV_FS_IF_FATFS*/ 276 | -------------------------------------------------------------------------------- /lv_fs_if.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_fs_if.c 3 | * 4 | */ 5 | 6 | /********************* 7 | * INCLUDES 8 | *********************/ 9 | #include "lv_fs_if.h" 10 | 11 | #if LV_USE_FS_IF 12 | 13 | /********************* 14 | * DEFINES 15 | *********************/ 16 | 17 | /********************** 18 | * TYPEDEFS 19 | **********************/ 20 | 21 | /********************** 22 | * STATIC PROTOTYPES 23 | **********************/ 24 | #if LV_FS_IF_FATFS != '\0' 25 | void lv_fs_if_fatfs_init(void); 26 | #endif 27 | 28 | #if LV_FS_IF_PC != '\0' 29 | void lv_fs_if_pc_init(void); 30 | #endif 31 | 32 | 33 | #if LV_FS_IF_POSIX != '\0' 34 | void lv_fs_if_posix_init(void); 35 | #endif 36 | 37 | /********************** 38 | * STATIC VARIABLES 39 | **********************/ 40 | 41 | /********************** 42 | * MACROS 43 | **********************/ 44 | 45 | /********************** 46 | * GLOBAL FUNCTIONS 47 | **********************/ 48 | 49 | /** 50 | * Register driver(s) for the File system interface 51 | */ 52 | void lv_fs_if_init(void) 53 | { 54 | #if LV_FS_IF_FATFS != '\0' 55 | lv_fs_if_fatfs_init(); 56 | #endif 57 | 58 | #if LV_FS_IF_PC != '\0' 59 | lv_fs_if_pc_init(); 60 | #endif 61 | 62 | #if LV_FS_IF_POSIX != '\0' 63 | lv_fs_if_posix_init(); 64 | #endif 65 | 66 | } 67 | 68 | /********************** 69 | * STATIC FUNCTIONS 70 | **********************/ 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /lv_fs_if.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_fs_if.h 3 | * 4 | */ 5 | 6 | #ifndef LV_FS_IF_H 7 | #define LV_FS_IF_H 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /********************* 14 | * INCLUDES 15 | *********************/ 16 | #if LV_LVGL_H_INCLUDE_SIMPLE 17 | #include 18 | #else 19 | #include 20 | #endif 21 | 22 | #if LV_USE_FS_IF 23 | 24 | /********************* 25 | * DEFINES 26 | *********************/ 27 | 28 | /********************** 29 | * TYPEDEFS 30 | **********************/ 31 | 32 | /********************** 33 | * GLOBAL PROTOTYPES 34 | **********************/ 35 | 36 | /** 37 | * Register driver(s) for the File system interface 38 | */ 39 | void lv_fs_if_init(void); 40 | 41 | /********************** 42 | * MACROS 43 | **********************/ 44 | 45 | #endif /*LV_USE_FS_IF*/ 46 | 47 | #ifdef __cplusplus 48 | } /* extern "C" */ 49 | #endif 50 | 51 | #endif /*LV_FS_IF_H*/ 52 | 53 | -------------------------------------------------------------------------------- /lv_fs_pc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_fs_pc.c 3 | * 4 | */ 5 | 6 | 7 | /********************* 8 | * INCLUDES 9 | *********************/ 10 | #include "lv_fs_if.h" 11 | #if LV_USE_FS_IF 12 | #if LV_FS_IF_PC != '\0' 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #ifdef WIN32 19 | #include 20 | #endif 21 | 22 | /********************* 23 | * DEFINES 24 | *********************/ 25 | #ifndef LV_FS_PC_PATH 26 | # ifndef WIN32 27 | # define LV_FS_PC_PATH "./" /*Projet root*/ 28 | # else 29 | # define LV_FS_PC_PATH ".\\" /*Projet root*/ 30 | # endif 31 | #endif /*LV_FS_PATH*/ 32 | 33 | /********************** 34 | * TYPEDEFS 35 | **********************/ 36 | 37 | /********************** 38 | * STATIC PROTOTYPES 39 | **********************/ 40 | static void * fs_open (lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); 41 | static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p); 42 | static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); 43 | static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 44 | static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); 45 | static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); 46 | static void * fs_dir_open (lv_fs_drv_t * drv, const char *path); 47 | static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn); 48 | static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p); 49 | 50 | /********************** 51 | * STATIC VARIABLES 52 | **********************/ 53 | 54 | /********************** 55 | * MACROS 56 | **********************/ 57 | 58 | /********************** 59 | * GLOBAL FUNCTIONS 60 | **********************/ 61 | 62 | /** 63 | * Register a driver for the File system interface 64 | */ 65 | void lv_fs_if_pc_init(void) 66 | { 67 | /*--------------------------------------------------- 68 | * Register the file system interface in LittlevGL 69 | *--------------------------------------------------*/ 70 | 71 | /* Add a simple drive to open images */ 72 | static lv_fs_drv_t fs_drv; /*A driver descriptor*/ 73 | lv_fs_drv_init(&fs_drv); 74 | 75 | /*Set up fields...*/ 76 | fs_drv.letter = LV_FS_IF_PC; 77 | fs_drv.open_cb = fs_open; 78 | fs_drv.close_cb = fs_close; 79 | fs_drv.read_cb = fs_read; 80 | fs_drv.write_cb = fs_write; 81 | fs_drv.seek_cb = fs_seek; 82 | fs_drv.tell_cb = fs_tell; 83 | 84 | fs_drv.dir_close_cb = fs_dir_close; 85 | fs_drv.dir_open_cb = fs_dir_open; 86 | fs_drv.dir_read_cb = fs_dir_read; 87 | 88 | lv_fs_drv_register(&fs_drv); 89 | 90 | char cur_path[512]; 91 | getcwd(cur_path, sizeof(cur_path)); 92 | LV_LOG_USER("LV_FS_PC is initialized with."); 93 | LV_LOG_USER("The following path is considered as root directory:\n%s", cur_path); 94 | } 95 | 96 | /********************** 97 | * STATIC FUNCTIONS 98 | **********************/ 99 | 100 | /** 101 | * Open a file 102 | * @param drv pointer to a driver where this function belongs 103 | * @param file_p pointer to a file_t variable 104 | * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) 105 | * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR 106 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 107 | */ 108 | static void * fs_open (lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) 109 | { 110 | (void) drv; /*Unused*/ 111 | errno = 0; 112 | 113 | const char * flags = ""; 114 | 115 | if(mode == LV_FS_MODE_WR) flags = "wb"; 116 | else if(mode == LV_FS_MODE_RD) flags = "rb"; 117 | else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = "rb+"; 118 | 119 | /*Make the path relative to the current directory (the projects root folder)*/ 120 | 121 | #ifndef WIN32 122 | char buf[256]; 123 | sprintf(buf, LV_FS_PC_PATH "%s", path); 124 | #else 125 | char buf[256]; 126 | sprintf(buf, LV_FS_PC_PATH "%s", path); 127 | #endif 128 | 129 | FILE * f = fopen(buf, flags); 130 | if(f == NULL) return NULL; 131 | 132 | /*Be sure we are the beginning of the file*/ 133 | fseek(f, 0, SEEK_SET); 134 | 135 | return f; 136 | } 137 | 138 | 139 | /** 140 | * Close an opened file 141 | * @param drv pointer to a driver where this function belongs 142 | * @param file_p pointer to a file_t variable. (opened with lv_ufs_open) 143 | * @return LV_FS_RES_OK: no error, the file is read 144 | * any error from lv_fs_res_t enum 145 | */ 146 | static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p) 147 | { 148 | (void) drv; /*Unused*/ 149 | fclose(file_p); 150 | return LV_FS_RES_OK; 151 | } 152 | 153 | /** 154 | * Read data from an opened file 155 | * @param drv pointer to a driver where this function belongs 156 | * @param file_p pointer to a file_t variable. 157 | * @param buf pointer to a memory block where to store the read data 158 | * @param btr number of Bytes To Read 159 | * @param br the real number of read bytes (Byte Read) 160 | * @return LV_FS_RES_OK: no error, the file is read 161 | * any error from lv_fs_res_t enum 162 | */ 163 | static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) 164 | { 165 | (void) drv; /*Unused*/ 166 | *br = fread(buf, 1, btr, file_p); 167 | return LV_FS_RES_OK; 168 | } 169 | 170 | /** 171 | * Write into a file 172 | * @param drv pointer to a driver where this function belongs 173 | * @param file_p pointer to a file_t variable 174 | * @param buf pointer to a buffer with the bytes to write 175 | * @param btr Bytes To Write 176 | * @param br the number of real written bytes (Bytes Written). NULL if unused. 177 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 178 | */ 179 | static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) 180 | { 181 | (void) drv; /*Unused*/ 182 | *bw = fwrite(buf, 1, btw, file_p); 183 | return LV_FS_RES_OK; 184 | } 185 | 186 | /** 187 | * Set the read write pointer. Also expand the file size if necessary. 188 | * @param drv pointer to a driver where this function belongs 189 | * @param file_p pointer to a file_t variable. (opened with lv_ufs_open ) 190 | * @param pos the new position of read write pointer 191 | * @return LV_FS_RES_OK: no error, the file is read 192 | * any error from lv_fs_res_t enum 193 | */ 194 | static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) 195 | { 196 | (void) drv; /*Unused*/ 197 | fseek(file_p, pos, whence); 198 | return LV_FS_RES_OK; 199 | } 200 | 201 | /** 202 | * Give the position of the read write pointer 203 | * @param drv pointer to a driver where this function belongs 204 | * @param file_p pointer to a file_t variable. 205 | * @param pos_p pointer to to store the result 206 | * @return LV_FS_RES_OK: no error, the file is read 207 | * any error from lv_fs_res_t enum 208 | */ 209 | static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) 210 | { 211 | (void) drv; /*Unused*/ 212 | *pos_p = ftell(file_p); 213 | return LV_FS_RES_OK; 214 | } 215 | 216 | 217 | #ifdef WIN32 218 | static char next_fn[256]; 219 | #endif 220 | 221 | /** 222 | * Initialize a 'fs_read_dir_t' variable for directory reading 223 | * @param drv pointer to a driver where this function belongs 224 | * @param dir_p pointer to a 'fs_read_dir_t' variable 225 | * @param path path to a directory 226 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 227 | */ 228 | static void * fs_dir_open (lv_fs_drv_t * drv, const char *path) 229 | { 230 | (void) drv; /*Unused*/ 231 | #ifndef WIN32 232 | /*Make the path relative to the current directory (the projects root folder)*/ 233 | char buf[256]; 234 | sprintf(buf, LV_FS_PC_PATH "/%s", path); 235 | return opendir(buf); 236 | #else 237 | HANDLE d = INVALID_HANDLE_VALUE; 238 | WIN32_FIND_DATA fdata; 239 | 240 | /*Make the path relative to the current directory (the projects root folder)*/ 241 | char buf[256]; 242 | sprintf(buf, LV_FS_PC_PATH "\\%s\\*", path); 243 | 244 | strcpy(next_fn, ""); 245 | d = FindFirstFile(buf, &fdata); 246 | do { 247 | if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { 248 | continue; 249 | } else { 250 | 251 | if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 252 | { 253 | sprintf(next_fn, "/%s", fdata.cFileName); 254 | } else { 255 | sprintf(next_fn, "%s", fdata.cFileName); 256 | } 257 | break; 258 | } 259 | } while(FindNextFileA(d, &fdata)); 260 | 261 | return d; 262 | #endif 263 | } 264 | 265 | /** 266 | * Read the next filename form a directory. 267 | * The name of the directories will begin with '/' 268 | * @param drv pointer to a driver where this function belongs 269 | * @param dir_p pointer to an initialized 'fs_read_dir_t' variable 270 | * @param fn pointer to a buffer to store the filename 271 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 272 | */ 273 | static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn) 274 | { 275 | (void) drv; /*Unused*/ 276 | 277 | #ifndef WIN32 278 | struct dirent *entry; 279 | do { 280 | entry = readdir(dir_p); 281 | 282 | if(entry) { 283 | if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name); 284 | else strcpy(fn, entry->d_name); 285 | } else { 286 | strcpy(fn, ""); 287 | } 288 | } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); 289 | #else 290 | strcpy(fn, next_fn); 291 | 292 | strcpy(next_fn, ""); 293 | WIN32_FIND_DATA fdata; 294 | 295 | if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK; 296 | do { 297 | if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { 298 | continue; 299 | } else { 300 | 301 | if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 302 | { 303 | sprintf(next_fn, "/%s", fdata.cFileName); 304 | } else { 305 | sprintf(next_fn, "%s", fdata.cFileName); 306 | } 307 | break; 308 | } 309 | } while(FindNextFile(dir_p, &fdata)); 310 | 311 | #endif 312 | return LV_FS_RES_OK; 313 | } 314 | 315 | /** 316 | * Close the directory reading 317 | * @param drv pointer to a driver where this function belongs 318 | * @param dir_p pointer to an initialized 'fs_read_dir_t' variable 319 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 320 | */ 321 | static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p) 322 | { 323 | (void) drv; /*Unused*/ 324 | #ifndef WIN32 325 | closedir(dir_p); 326 | #else 327 | FindClose(dir_p); 328 | #endif 329 | return LV_FS_RES_OK; 330 | } 331 | 332 | #endif /*LV_USE_FS_IF*/ 333 | #endif /*LV_FS_IF_FATFS*/ 334 | -------------------------------------------------------------------------------- /lv_fs_posix.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file lv_fs_posix.c 3 | * 4 | */ 5 | 6 | 7 | /********************* 8 | * INCLUDES 9 | *********************/ 10 | #include "lv_fs_if.h" 11 | #if LV_USE_FS_IF 12 | #if LV_FS_IF_POSIX != '\0' 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #ifdef WIN32 20 | #include 21 | #endif 22 | 23 | /********************* 24 | * DEFINES 25 | *********************/ 26 | #ifndef LV_FS_POSIX_PATH 27 | # ifndef WIN32 28 | # define LV_FS_POSIX_PATH "./" /*Project root*/ 29 | # else 30 | # define LV_FS_POSIX_PATH ".\\" /*Project root*/ 31 | # endif 32 | #endif /*LV_FS_PATH*/ 33 | 34 | /********************** 35 | * TYPEDEFS 36 | **********************/ 37 | 38 | /********************** 39 | * STATIC PROTOTYPES 40 | **********************/ 41 | static void * fs_open (lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); 42 | static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p); 43 | static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); 44 | static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 45 | static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); 46 | static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); 47 | static void * fs_dir_open (lv_fs_drv_t * drv, const char *path); 48 | static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn); 49 | static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p); 50 | 51 | /********************** 52 | * STATIC VARIABLES 53 | **********************/ 54 | 55 | /********************** 56 | * MACROS 57 | **********************/ 58 | 59 | /********************** 60 | * GLOBAL FUNCTIONS 61 | **********************/ 62 | 63 | /** 64 | * Register a driver for the File system interface 65 | */ 66 | void lv_fs_if_posix_init(void) 67 | { 68 | /*--------------------------------------------------- 69 | * Register the file system interface in LittlevGL 70 | *--------------------------------------------------*/ 71 | 72 | /* Add a simple drive to open images */ 73 | static lv_fs_drv_t fs_drv; /*A driver descriptor*/ 74 | lv_fs_drv_init(&fs_drv); 75 | 76 | /*Set up fields...*/ 77 | fs_drv.letter = LV_FS_IF_POSIX; 78 | fs_drv.open_cb = fs_open; 79 | fs_drv.close_cb = fs_close; 80 | fs_drv.read_cb = fs_read; 81 | fs_drv.write_cb = fs_write; 82 | fs_drv.seek_cb = fs_seek; 83 | fs_drv.tell_cb = fs_tell; 84 | 85 | fs_drv.dir_close_cb = fs_dir_close; 86 | fs_drv.dir_open_cb = fs_dir_open; 87 | fs_drv.dir_read_cb = fs_dir_read; 88 | 89 | lv_fs_drv_register(&fs_drv); 90 | } 91 | 92 | /********************** 93 | * STATIC FUNCTIONS 94 | **********************/ 95 | 96 | /** 97 | * Open a file 98 | * @param drv pointer to a driver where this function belongs 99 | * @param file_p pointer to a file_t variable 100 | * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) 101 | * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR 102 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 103 | */ 104 | static void * fs_open (lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) 105 | { 106 | (void) drv; /*Unused*/ 107 | errno = 0; 108 | 109 | uint32_t flags = 0; 110 | if(mode == LV_FS_MODE_WR) flags = O_WRONLY; 111 | else if(mode == LV_FS_MODE_RD) flags = O_RDONLY; 112 | else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD)) flags = O_RDWR; 113 | 114 | /*Make the path relative to the current directory (the projects root folder)*/ 115 | char buf[256]; 116 | sprintf(buf, LV_FS_POSIX_PATH "%s", path); 117 | 118 | 119 | int f = open(buf, flags); 120 | if(f < 0) return NULL; 121 | 122 | /*Be sure we are the beginning of the file*/ 123 | lseek(f, 0, SEEK_SET); 124 | 125 | int * fp = lv_mem_alloc(sizeof(int)); 126 | if(fp == NULL) return NULL; 127 | *fp = f; 128 | 129 | return fp; 130 | } 131 | 132 | 133 | /** 134 | * Close an opened file 135 | * @param drv pointer to a driver where this function belongs 136 | * @param file_p pointer to a file_t variable. (opened with lv_ufs_open) 137 | * @return LV_FS_RES_OK: no error, the file is read 138 | * any error from lv_fs_res_t enum 139 | */ 140 | static lv_fs_res_t fs_close (lv_fs_drv_t * drv, void * file_p) 141 | { 142 | (void) drv; /*Unused*/ 143 | int * fp = file_p; 144 | close(*fp); 145 | lv_mem_free(file_p); 146 | return LV_FS_RES_OK; 147 | } 148 | 149 | /** 150 | * Read data from an opened file 151 | * @param drv pointer to a driver where this function belongs 152 | * @param file_p pointer to a file_t variable. 153 | * @param buf pointer to a memory block where to store the read data 154 | * @param btr number of Bytes To Read 155 | * @param br the real number of read bytes (Byte Read) 156 | * @return LV_FS_RES_OK: no error, the file is read 157 | * any error from lv_fs_res_t enum 158 | */ 159 | static lv_fs_res_t fs_read (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) 160 | { 161 | (void) drv; /*Unused*/ 162 | int * fp = file_p; 163 | *br = read(*fp, buf, btr); 164 | return LV_FS_RES_OK; 165 | } 166 | 167 | /** 168 | * Write into a file 169 | * @param drv pointer to a driver where this function belongs 170 | * @param file_p pointer to a file_t variable 171 | * @param buf pointer to a buffer with the bytes to write 172 | * @param btr Bytes To Write 173 | * @param br the number of real written bytes (Bytes Written). NULL if unused. 174 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 175 | */ 176 | static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) 177 | { 178 | (void) drv; /*Unused*/ 179 | int * fp = file_p; 180 | *bw = write(*fp, buf, btw); 181 | return LV_FS_RES_OK; 182 | } 183 | 184 | /** 185 | * Set the read write pointer. Also expand the file size if necessary. 186 | * @param drv pointer to a driver where this function belongs 187 | * @param file_p pointer to a file_t variable. (opened with lv_ufs_open ) 188 | * @param pos the new position of read write pointer 189 | * @return LV_FS_RES_OK: no error, the file is read 190 | * any error from lv_fs_res_t enum 191 | */ 192 | static lv_fs_res_t fs_seek (lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) 193 | { 194 | (void) drv; /*Unused*/ 195 | int * fp = file_p; 196 | lseek(*fp, pos, whence); 197 | return LV_FS_RES_OK; 198 | } 199 | 200 | /** 201 | * Give the position of the read write pointer 202 | * @param drv pointer to a driver where this function belongs 203 | * @param file_p pointer to a file_t variable. 204 | * @param pos_p pointer to to store the result 205 | * @return LV_FS_RES_OK: no error, the file is read 206 | * any error from lv_fs_res_t enum 207 | */ 208 | static lv_fs_res_t fs_tell (lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) 209 | { 210 | (void) drv; /*Unused*/ 211 | int * fp = file_p; 212 | *pos_p = lseek(*fp, 0, SEEK_CUR); 213 | return LV_FS_RES_OK; 214 | } 215 | 216 | 217 | #ifdef WIN32 218 | static char next_fn[256]; 219 | #endif 220 | 221 | /** 222 | * Initialize a 'fs_read_dir_t' variable for directory reading 223 | * @param drv pointer to a driver where this function belongs 224 | * @param dir_p pointer to a 'fs_read_dir_t' variable 225 | * @param path path to a directory 226 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 227 | */ 228 | static void * fs_dir_open (lv_fs_drv_t * drv, const char *path) 229 | { 230 | (void) drv; /*Unused*/ 231 | #ifndef WIN32 232 | /*Make the path relative to the current directory (the projects root folder)*/ 233 | char buf[256]; 234 | sprintf(buf, LV_FS_POSIX_PATH "/%s", path); 235 | return opendir(buf); 236 | #else 237 | HANDLE d = INVALID_HANDLE_VALUE; 238 | WIN32_FIND_DATA fdata; 239 | 240 | /*Make the path relative to the current directory (the projects root folder)*/ 241 | char buf[256]; 242 | sprintf(buf, LV_FS_PC_PATH "\\%s\\*", path); 243 | 244 | strcpy(next_fn, ""); 245 | d = FindFirstFile(buf, &fdata); 246 | do { 247 | if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { 248 | continue; 249 | } else { 250 | 251 | if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 252 | { 253 | sprintf(next_fn, "/%s", fdata.cFileName); 254 | } else { 255 | sprintf(next_fn, "%s", fdata.cFileName); 256 | } 257 | break; 258 | } 259 | } while(FindNextFileA(d, &fdata)); 260 | 261 | return d; 262 | #endif 263 | } 264 | 265 | /** 266 | * Read the next filename form a directory. 267 | * The name of the directories will begin with '/' 268 | * @param drv pointer to a driver where this function belongs 269 | * @param dir_p pointer to an initialized 'fs_read_dir_t' variable 270 | * @param fn pointer to a buffer to store the filename 271 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 272 | */ 273 | static lv_fs_res_t fs_dir_read (lv_fs_drv_t * drv, void * dir_p, char *fn) 274 | { 275 | // (void) drv; /*Unused*/ 276 | 277 | // #ifndef WIN32 278 | // struct dirent *entry; 279 | // do { 280 | // entry = readdir(dir_p); 281 | 282 | // if(entry) { 283 | // if(entry->d_type == DT_DIR) sprintf(fn, "/%s", entry->d_name); 284 | // else strcpy(fn, entry->d_name); 285 | // } else { 286 | // strcpy(fn, ""); 287 | // } 288 | // } while(strcmp(fn, "/.") == 0 || strcmp(fn, "/..") == 0); 289 | // #else 290 | // strcpy(fn, next_fn); 291 | 292 | // strcpy(next_fn, ""); 293 | // WIN32_FIND_DATA fdata; 294 | 295 | // if(FindNextFile(dir_p, &fdata) == false) return LV_FS_RES_OK; 296 | // do { 297 | // if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0) { 298 | // continue; 299 | // } else { 300 | 301 | // if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 302 | // { 303 | // sprintf(next_fn, "/%s", fdata.cFileName); 304 | // } else { 305 | // sprintf(next_fn, "%s", fdata.cFileName); 306 | // } 307 | // break; 308 | // } 309 | // } while(FindNextFile(dir_p, &fdata)); 310 | 311 | // #endif 312 | return LV_FS_RES_OK; 313 | } 314 | 315 | /** 316 | * Close the directory reading 317 | * @param drv pointer to a driver where this function belongs 318 | * @param dir_p pointer to an initialized 'fs_read_dir_t' variable 319 | * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 320 | */ 321 | static lv_fs_res_t fs_dir_close (lv_fs_drv_t * drv, void * dir_p) 322 | { 323 | (void) drv; /*Unused*/ 324 | #ifndef WIN32 325 | closedir(dir_p); 326 | #else 327 | FindClose(dir_p); 328 | #endif 329 | return LV_FS_RES_OK; 330 | } 331 | 332 | #endif /*LV_USE_FS_IF*/ 333 | #endif /*LV_FS_IF_FATFS*/ 334 | --------------------------------------------------------------------------------