1 #include "../../../lvgl.h"
2 #if LV_USE_FS_ARDUINO_ESP_LITTLEFS
3 
4 #include "../../core/lv_global.h"
5 #include "LittleFS.h"
6 
7 #if !LV_FS_IS_VALID_LETTER(LV_FS_ARDUINO_ESP_LITTLEFS_LETTER)
8     #error "Invalid drive letter"
9 #endif
10 
11 typedef struct ArduinoEspLittleFile {
12     File file;
13 } ArduinoEspLittleFile;
14 
15 /**********************
16  *  STATIC PROTOTYPES
17  **********************/
18 static void fs_init(void);
19 static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode);
20 static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p);
21 static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br);
22 static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw);
23 static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence);
24 static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p);
25 
26 /**
27  * Register a driver for the LittleFS File System interface
28  */
lv_fs_arduino_esp_littlefs_init(void)29 extern "C" void lv_fs_arduino_esp_littlefs_init(void)
30 {
31     fs_init();
32 
33     lv_fs_drv_t * fs_drv = &(LV_GLOBAL_DEFAULT()->arduino_esp_littlefs_fs_drv);
34     lv_fs_drv_init(fs_drv);
35 
36     fs_drv->letter = LV_FS_ARDUINO_ESP_LITTLEFS_LETTER;
37     fs_drv->open_cb = fs_open;
38     fs_drv->close_cb = fs_close;
39     fs_drv->read_cb = fs_read;
40     fs_drv->write_cb = fs_write;
41     fs_drv->seek_cb = fs_seek;
42     fs_drv->tell_cb = fs_tell;
43 
44     fs_drv->dir_close_cb = NULL;
45     fs_drv->dir_open_cb = NULL;
46     fs_drv->dir_read_cb = NULL;
47 
48     lv_fs_drv_register(fs_drv);
49 }
50 
51 /**********************
52  *   STATIC FUNCTIONS
53  **********************/
54 
55 /*Initialize your Storage device and File system.*/
fs_init(void)56 static void fs_init(void)
57 {
58     LittleFS.begin();
59 }
60 
61 /**
62  * Open a file
63  * @param drv       pointer to a driver where this function belongs
64  * @param path      path to the file beginning with the driver letter (e.g. S:/folder/file.txt)
65  * @param mode      read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR
66  * @return          a file descriptor or NULL on error
67  */
fs_open(lv_fs_drv_t * drv,const char * path,lv_fs_mode_t mode)68 static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode)
69 {
70     LV_UNUSED(drv);
71 
72     const char * flags;
73     if(mode == LV_FS_MODE_WR)
74         flags = FILE_WRITE;
75     else if(mode == LV_FS_MODE_RD)
76         flags = FILE_READ;
77     else if(mode == (LV_FS_MODE_WR | LV_FS_MODE_RD))
78         flags = FILE_WRITE;
79 
80     char buf[LV_FS_MAX_PATH_LEN];
81     lv_snprintf(buf, sizeof(buf), LV_FS_ARDUINO_ESP_LITTLEFS_PATH "%s", path);
82 
83     File file = LittleFS.open(buf, flags);
84     if(!file) {
85         return NULL;
86     }
87 
88     ArduinoEspLittleFile * lf = new ArduinoEspLittleFile{file};
89 
90     return (void *)lf;
91 }
92 
93 /**
94  * Close an opened file
95  * @param drv       pointer to a driver where this function belongs
96  * @param file_p    pointer to a file_t variable. (opened with fs_open)
97  * @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum
98  */
fs_close(lv_fs_drv_t * drv,void * file_p)99 static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p)
100 {
101     LV_UNUSED(drv);
102     ArduinoEspLittleFile * lf = (ArduinoEspLittleFile *)file_p;
103     lf->file.close();
104     delete lf;
105 
106     return LV_FS_RES_OK;
107 }
108 
109 /**
110  * Read data from an opened file
111  * @param drv       pointer to a driver where this function belongs
112  * @param file_p    pointer to a file_t variable.
113  * @param buf       pointer to a memory block where to store the read data
114  * @param btr       number of Bytes To Read
115  * @param br        the real number of read bytes (Byte Read)
116  * @return          LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
117  */
fs_read(lv_fs_drv_t * drv,void * file_p,void * buf,uint32_t btr,uint32_t * br)118 static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
119 {
120     LV_UNUSED(drv);
121     ArduinoEspLittleFile * lf = (ArduinoEspLittleFile *)file_p;
122     *br = lf->file.read((uint8_t *)buf, btr);
123 
124     return (int32_t)(*br) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
125 }
126 
127 /**
128  * Write into a file
129  * @param drv       pointer to a driver where this function belongs
130  * @param file_p    pointer to a file_t variable
131  * @param buf       pointer to a buffer with the bytes to write
132  * @param btw       Bytes To Write
133  * @param bw        the number of real written bytes (Bytes Written)
134  * @return          LV_FS_RES_OK: no error or  any error from @lv_fs_res_t enum
135  */
fs_write(lv_fs_drv_t * drv,void * file_p,const void * buf,uint32_t btw,uint32_t * bw)136 static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
137 {
138     LV_UNUSED(drv);
139     ArduinoEspLittleFile * lf = (ArduinoEspLittleFile *)file_p;
140     *bw = lf->file.write((uint8_t *)buf, btw);
141 
142     return (int32_t)(*bw) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
143 }
144 
145 /**
146  * Set the read write pointer. Also expand the file size if necessary.
147  * @param drv       pointer to a driver where this function belongs
148  * @param file_p    pointer to a file_t variable. (opened with fs_open )
149  * @param pos       the new position of read write pointer
150  * @param whence    tells from where to interpret the `pos`. See @lv_fs_whence_t
151  * @return          LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
152  */
fs_seek(lv_fs_drv_t * drv,void * file_p,uint32_t pos,lv_fs_whence_t whence)153 static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence)
154 {
155     LV_UNUSED(drv);
156     SeekMode mode;
157     if(whence == LV_FS_SEEK_SET)
158         mode = SeekSet;
159     else if(whence == LV_FS_SEEK_CUR)
160         mode = SeekCur;
161     else if(whence == LV_FS_SEEK_END)
162         mode = SeekEnd;
163 
164     ArduinoEspLittleFile * lf = (ArduinoEspLittleFile *)file_p;
165 
166     int rc = lf->file.seek(pos, mode);
167 
168     return rc < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
169 }
170 
171 /**
172  * Give the position of the read write pointer
173  * @param drv       pointer to a driver where this function belongs
174  * @param file_p    pointer to a file_p variable
175  * @param pos_p     pointer to store the result
176  * @return          LV_FS_RES_OK: no error or any error from @lv_fs_res_t enum
177  */
fs_tell(lv_fs_drv_t * drv,void * file_p,uint32_t * pos_p)178 static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
179 {
180     LV_UNUSED(drv);
181     ArduinoEspLittleFile * lf = (ArduinoEspLittleFile *)file_p;
182 
183     *pos_p = lf->file.position();
184 
185     return (int32_t)(*pos_p) < 0 ? LV_FS_RES_UNKNOWN : LV_FS_RES_OK;
186 }
187 
188 #else /*LV_USE_FS_ARDUINO_ESP_LITTLEFS == 0*/
189 
190 #if defined(LV_FS_ARDUINO_ESP_LITTLEFS_LETTER) && LV_FS_ARDUINO_ESP_LITTLEFS_LETTER != '\0'
191     #warning "LV_USE_FS_ARDUINO_ESP_LITTLEFS is not enabled but LV_FS_ARDUINO_ESP_LITTLEFS_LETTER is set"
192 #endif
193 
194 #endif /*LV_USE_FS_ARDUINO_ESP_LITTLEFS*/
195