acid-drop- Hacking the planet from a LilyGo T-Deck using custom firmware |
git clone git://git.acid.vegas/acid-drop.git |
Log | Files | Refs | Archive | README | LICENSE |
lv_fs_win32.c (13912B)
1 /** 2 * @file lv_fs_win32.c 3 * 4 */ 5 6 7 /********************* 8 * INCLUDES 9 *********************/ 10 #include "../../../lvgl.h" 11 #if LV_USE_FS_WIN32 != '\0' 12 13 #include <windows.h> 14 #include <stdio.h> 15 16 /********************* 17 * DEFINES 18 *********************/ 19 #define MAX_PATH_LEN 256 20 21 /********************** 22 * TYPEDEFS 23 **********************/ 24 typedef struct { 25 HANDLE dir_p; 26 char next_fn[MAX_PATH_LEN]; 27 lv_fs_res_t next_error; 28 } dir_handle_t; 29 30 /********************** 31 * STATIC PROTOTYPES 32 **********************/ 33 34 static bool is_dots_name(const char * name); 35 static lv_fs_res_t fs_error_from_win32(DWORD error); 36 static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode); 37 static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p); 38 static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br); 39 static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw); 40 static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence); 41 static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p); 42 static void * fs_dir_open(lv_fs_drv_t * drv, const char * path); 43 static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn); 44 static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p); 45 46 /********************** 47 * STATIC VARIABLES 48 **********************/ 49 50 /********************** 51 * MACROS 52 **********************/ 53 54 /********************** 55 * GLOBAL FUNCTIONS 56 **********************/ 57 58 /** 59 * Register a driver for the File system interface 60 */ 61 void lv_fs_win32_init(void) 62 { 63 /*--------------------------------------------------- 64 * Register the file system interface in LVGL 65 *--------------------------------------------------*/ 66 67 /*Add a simple drive to open images*/ 68 static lv_fs_drv_t fs_drv; /*A driver descriptor*/ 69 lv_fs_drv_init(&fs_drv); 70 71 /*Set up fields...*/ 72 fs_drv.letter = LV_FS_WIN32_LETTER; 73 fs_drv.cache_size = LV_FS_WIN32_CACHE_SIZE; 74 75 fs_drv.open_cb = fs_open; 76 fs_drv.close_cb = fs_close; 77 fs_drv.read_cb = fs_read; 78 fs_drv.write_cb = fs_write; 79 fs_drv.seek_cb = fs_seek; 80 fs_drv.tell_cb = fs_tell; 81 82 fs_drv.dir_close_cb = fs_dir_close; 83 fs_drv.dir_open_cb = fs_dir_open; 84 fs_drv.dir_read_cb = fs_dir_read; 85 86 lv_fs_drv_register(&fs_drv); 87 } 88 89 /********************** 90 * STATIC FUNCTIONS 91 **********************/ 92 93 /** 94 * Check the dots name 95 * @param name file or dir name 96 * @return true if the name is dots name 97 */ 98 static bool is_dots_name(const char * name) 99 { 100 return name[0] == '.' && (!name[1] || (name[1] == '.' && !name[2])); 101 } 102 103 /** 104 * Convert Win32 error code to error from lv_fs_res_t enum 105 * @param error Win32 error code 106 * @return LV_FS_RES_OK: no error, the file is read 107 * any error from lv_fs_res_t enum 108 */ 109 static lv_fs_res_t fs_error_from_win32(DWORD error) 110 { 111 lv_fs_res_t res; 112 113 switch(error) { 114 case ERROR_SUCCESS: 115 res = LV_FS_RES_OK; 116 break; 117 case ERROR_BAD_UNIT: 118 case ERROR_NOT_READY: 119 case ERROR_CRC: 120 case ERROR_SEEK: 121 case ERROR_NOT_DOS_DISK: 122 case ERROR_WRITE_FAULT: 123 case ERROR_READ_FAULT: 124 case ERROR_GEN_FAILURE: 125 case ERROR_WRONG_DISK: 126 res = LV_FS_RES_HW_ERR; 127 break; 128 case ERROR_INVALID_HANDLE: 129 case ERROR_INVALID_TARGET_HANDLE: 130 res = LV_FS_RES_FS_ERR; 131 break; 132 case ERROR_FILE_NOT_FOUND: 133 case ERROR_PATH_NOT_FOUND: 134 case ERROR_INVALID_DRIVE: 135 case ERROR_NO_MORE_FILES: 136 case ERROR_SECTOR_NOT_FOUND: 137 case ERROR_BAD_NETPATH: 138 case ERROR_BAD_NET_NAME: 139 case ERROR_BAD_PATHNAME: 140 case ERROR_FILENAME_EXCED_RANGE: 141 res = LV_FS_RES_NOT_EX; 142 break; 143 case ERROR_DISK_FULL: 144 res = LV_FS_RES_FULL; 145 break; 146 case ERROR_SHARING_VIOLATION: 147 case ERROR_LOCK_VIOLATION: 148 case ERROR_DRIVE_LOCKED: 149 res = LV_FS_RES_LOCKED; 150 break; 151 case ERROR_ACCESS_DENIED: 152 case ERROR_CURRENT_DIRECTORY: 153 case ERROR_WRITE_PROTECT: 154 case ERROR_NETWORK_ACCESS_DENIED: 155 case ERROR_CANNOT_MAKE: 156 case ERROR_FAIL_I24: 157 case ERROR_SEEK_ON_DEVICE: 158 case ERROR_NOT_LOCKED: 159 case ERROR_LOCK_FAILED: 160 res = LV_FS_RES_DENIED; 161 break; 162 case ERROR_BUSY: 163 res = LV_FS_RES_BUSY; 164 break; 165 case ERROR_TIMEOUT: 166 res = LV_FS_RES_TOUT; 167 break; 168 case ERROR_NOT_SAME_DEVICE: 169 case ERROR_DIRECT_ACCESS_HANDLE: 170 res = LV_FS_RES_NOT_IMP; 171 break; 172 case ERROR_TOO_MANY_OPEN_FILES: 173 case ERROR_ARENA_TRASHED: 174 case ERROR_NOT_ENOUGH_MEMORY: 175 case ERROR_INVALID_BLOCK: 176 case ERROR_OUT_OF_PAPER: 177 case ERROR_SHARING_BUFFER_EXCEEDED: 178 case ERROR_NOT_ENOUGH_QUOTA: 179 res = LV_FS_RES_OUT_OF_MEM; 180 break; 181 case ERROR_INVALID_FUNCTION: 182 case ERROR_INVALID_ACCESS: 183 case ERROR_INVALID_DATA: 184 case ERROR_BAD_COMMAND: 185 case ERROR_BAD_LENGTH: 186 case ERROR_INVALID_PARAMETER: 187 case ERROR_NEGATIVE_SEEK: 188 res = LV_FS_RES_INV_PARAM; 189 break; 190 default: 191 res = LV_FS_RES_UNKNOWN; 192 break; 193 } 194 195 return res; 196 } 197 198 /** 199 * Open a file 200 * @param drv pointer to a driver where this function belongs 201 * @param path path to the file beginning with the driver letter (e.g. S:/folder/file.txt) 202 * @param mode read: FS_MODE_RD, write: FS_MODE_WR, both: FS_MODE_RD | FS_MODE_WR 203 * @return pointer to FIL struct or NULL in case of fail 204 */ 205 static void * fs_open(lv_fs_drv_t * drv, const char * path, lv_fs_mode_t mode) 206 { 207 LV_UNUSED(drv); 208 209 DWORD desired_access = 0; 210 211 if(mode & LV_FS_MODE_RD) { 212 desired_access |= GENERIC_READ; 213 } 214 215 if(mode & LV_FS_MODE_WR) { 216 desired_access |= GENERIC_WRITE; 217 } 218 219 /*Make the path relative to the current directory (the projects root folder)*/ 220 221 char buf[MAX_PATH]; 222 lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s", path); 223 224 return (void *)CreateFileA( 225 buf, 226 desired_access, 227 FILE_SHARE_READ, 228 NULL, 229 OPEN_EXISTING, 230 FILE_ATTRIBUTE_NORMAL, 231 NULL); 232 } 233 234 /** 235 * Close an opened file 236 * @param drv pointer to a driver where this function belongs 237 * @param file_p pointer to a FILE variable. (opened with fs_open) 238 * @return LV_FS_RES_OK: no error, the file is read 239 * any error from lv_fs_res_t enum 240 */ 241 static lv_fs_res_t fs_close(lv_fs_drv_t * drv, void * file_p) 242 { 243 LV_UNUSED(drv); 244 return CloseHandle((HANDLE)file_p) 245 ? LV_FS_RES_OK 246 : fs_error_from_win32(GetLastError()); 247 } 248 249 /** 250 * Read data from an opened file 251 * @param drv pointer to a driver where this function belongs 252 * @param file_p pointer to a FILE variable. 253 * @param buf pointer to a memory block where to store the read data 254 * @param btr number of Bytes To Read 255 * @param br the real number of read bytes (Byte Read) 256 * @return LV_FS_RES_OK: no error, the file is read 257 * any error from lv_fs_res_t enum 258 */ 259 static lv_fs_res_t fs_read(lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) 260 { 261 LV_UNUSED(drv); 262 return ReadFile((HANDLE)file_p, buf, btr, (LPDWORD)br, NULL) 263 ? LV_FS_RES_OK 264 : fs_error_from_win32(GetLastError()); 265 } 266 267 /** 268 * Write into a file 269 * @param drv pointer to a driver where this function belongs 270 * @param file_p pointer to a FILE variable 271 * @param buf pointer to a buffer with the bytes to write 272 * @param btw Bytes To Write 273 * @param bw the number of real written bytes (Bytes Written). NULL if unused. 274 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 275 */ 276 static lv_fs_res_t fs_write(lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw) 277 { 278 LV_UNUSED(drv); 279 return WriteFile((HANDLE)file_p, buf, btw, (LPDWORD)bw, NULL) 280 ? LV_FS_RES_OK 281 : fs_error_from_win32(GetLastError()); 282 } 283 284 /** 285 * Set the read write pointer. Also expand the file size if necessary. 286 * @param drv pointer to a driver where this function belongs 287 * @param file_p pointer to a FILE variable. (opened with fs_open ) 288 * @param pos the new position of read write pointer 289 * @return LV_FS_RES_OK: no error, the file is read 290 * any error from lv_fs_res_t enum 291 */ 292 static lv_fs_res_t fs_seek(lv_fs_drv_t * drv, void * file_p, uint32_t pos, lv_fs_whence_t whence) 293 { 294 LV_UNUSED(drv); 295 296 DWORD move_method = (DWORD) -1; 297 if(whence == LV_FS_SEEK_SET) { 298 move_method = FILE_BEGIN; 299 } 300 else if(whence == LV_FS_SEEK_CUR) { 301 move_method = FILE_CURRENT; 302 } 303 else if(whence == LV_FS_SEEK_END) { 304 move_method = FILE_END; 305 } 306 307 LARGE_INTEGER distance_to_move; 308 distance_to_move.QuadPart = pos; 309 return SetFilePointerEx((HANDLE)file_p, distance_to_move, NULL, move_method) 310 ? LV_FS_RES_OK 311 : fs_error_from_win32(GetLastError()); 312 } 313 314 /** 315 * Give the position of the read write pointer 316 * @param drv pointer to a driver where this function belongs 317 * @param file_p pointer to a FILE variable. 318 * @param pos_p pointer to to store the result 319 * @return LV_FS_RES_OK: no error, the file is read 320 * any error from lv_fs_res_t enum 321 */ 322 static lv_fs_res_t fs_tell(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) 323 { 324 LV_UNUSED(drv); 325 326 if(!pos_p) { 327 return LV_FS_RES_INV_PARAM; 328 } 329 330 LARGE_INTEGER file_pointer; 331 file_pointer.QuadPart = 0; 332 333 LARGE_INTEGER distance_to_move; 334 distance_to_move.QuadPart = 0; 335 if(SetFilePointerEx( 336 (HANDLE)file_p, 337 distance_to_move, 338 &file_pointer, 339 FILE_CURRENT)) { 340 if(file_pointer.QuadPart > LONG_MAX) { 341 return LV_FS_RES_INV_PARAM; 342 } 343 else { 344 *pos_p = file_pointer.LowPart; 345 return LV_FS_RES_OK; 346 } 347 } 348 else { 349 return fs_error_from_win32(GetLastError()); 350 } 351 } 352 353 /** 354 * Initialize a 'DIR' or 'HANDLE' variable for directory reading 355 * @param drv pointer to a driver where this function belongs 356 * @param path path to a directory 357 * @return pointer to an initialized 'DIR' or 'HANDLE' variable 358 */ 359 static void * fs_dir_open(lv_fs_drv_t * drv, const char * path) 360 { 361 LV_UNUSED(drv); 362 dir_handle_t * handle = (dir_handle_t *)lv_mem_alloc(sizeof(dir_handle_t)); 363 handle->dir_p = INVALID_HANDLE_VALUE; 364 handle->next_error = LV_FS_RES_OK; 365 WIN32_FIND_DATA fdata; 366 367 /*Make the path relative to the current directory (the projects root folder)*/ 368 char buf[MAX_PATH_LEN]; 369 #ifdef LV_FS_WIN32_PATH 370 lv_snprintf(buf, sizeof(buf), LV_FS_WIN32_PATH "%s\\*", path); 371 #else 372 lv_snprintf(buf, sizeof(buf), "%s\\*", path); 373 #endif 374 375 strcpy(handle->next_fn, ""); 376 handle->dir_p = FindFirstFile(buf, &fdata); 377 do { 378 if(is_dots_name(fdata.cFileName)) { 379 continue; 380 } 381 else { 382 if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 383 lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName); 384 } 385 else { 386 lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName); 387 } 388 break; 389 } 390 } while(FindNextFileA(handle->dir_p, &fdata)); 391 392 if(handle->dir_p == INVALID_HANDLE_VALUE) { 393 lv_mem_free(handle); 394 handle->next_error = fs_error_from_win32(GetLastError()); 395 return INVALID_HANDLE_VALUE; 396 } 397 else { 398 handle->next_error = LV_FS_RES_OK; 399 return handle; 400 } 401 } 402 403 /** 404 * Read the next filename from a directory. 405 * The name of the directories will begin with '/' 406 * @param drv pointer to a driver where this function belongs 407 * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable 408 * @param fn pointer to a buffer to store the filename 409 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 410 */ 411 static lv_fs_res_t fs_dir_read(lv_fs_drv_t * drv, void * dir_p, char * fn) 412 { 413 LV_UNUSED(drv); 414 dir_handle_t * handle = (dir_handle_t *)dir_p; 415 strcpy(fn, handle->next_fn); 416 lv_fs_res_t current_error = handle->next_error; 417 strcpy(handle->next_fn, ""); 418 419 WIN32_FIND_DATA fdata; 420 421 while(FindNextFileA(handle->dir_p, &fdata)) { 422 if(is_dots_name(fdata.cFileName)) { 423 continue; 424 } 425 else { 426 if(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 427 lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "/%s", fdata.cFileName); 428 } 429 else { 430 lv_snprintf(handle->next_fn, sizeof(handle->next_fn), "%s", fdata.cFileName); 431 } 432 break; 433 } 434 } 435 436 if(handle->next_fn[0] == '\0') { 437 handle->next_error = fs_error_from_win32(GetLastError()); 438 } 439 440 return current_error; 441 } 442 443 /** 444 * Close the directory reading 445 * @param drv pointer to a driver where this function belongs 446 * @param dir_p pointer to an initialized 'DIR' or 'HANDLE' variable 447 * @return LV_FS_RES_OK or any error from lv_fs_res_t enum 448 */ 449 static lv_fs_res_t fs_dir_close(lv_fs_drv_t * drv, void * dir_p) 450 { 451 LV_UNUSED(drv); 452 dir_handle_t * handle = (dir_handle_t *)dir_p; 453 lv_fs_res_t res = FindClose(handle->dir_p) 454 ? LV_FS_RES_OK 455 : fs_error_from_win32(GetLastError()); 456 lv_mem_free(handle); 457 return res; 458 } 459 460 #else /*LV_USE_FS_WIN32 == 0*/ 461 462 #if defined(LV_FS_WIN32_LETTER) && LV_FS_WIN32_LETTER != '\0' 463 #warning "LV_USE_FS_WIN32 is not enabled but LV_FS_WIN32_LETTER is set" 464 #endif 465 466 #endif