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