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