|
| 1 | +# Original author: mhepp(https://forum.lvgl.io/u/mhepp/summary) |
| 2 | +# Copyright (c) 2024 - 2025 Kevin G. Schlosser |
| 3 | +# Added directory support, upstreamed at https://github.com/lvgl-micropython/lvgl_micropython/issues/398 |
| 4 | + |
| 5 | + |
| 6 | +importlvglaslv |
| 7 | +importstruct |
| 8 | + |
| 9 | + |
| 10 | +def_fs_open_cb(drv,path,mode): |
| 11 | + |
| 12 | +ifmode==lv.FS_MODE.WR: |
| 13 | +p_mode='wb' |
| 14 | +elifmode==lv.FS_MODE.RD: |
| 15 | +p_mode='rb' |
| 16 | +elifmode==lv.FS_MODE.WR|lv.FS_MODE.RD: |
| 17 | +p_mode='rb+' |
| 18 | +else: |
| 19 | +raiseRuntimeError("fs_open_callback() - open mode error, %s is invalid mode"%mode) |
| 20 | + |
| 21 | +try: |
| 22 | +f=open(path,p_mode) |
| 23 | + |
| 24 | +exceptOSErrorase: |
| 25 | +raiseRuntimeError("fs_open_callback(%s) exception: %s"% (path,e)) |
| 26 | + |
| 27 | +return {'file' :f,'path':path} |
| 28 | + |
| 29 | + |
| 30 | +def_fs_close_cb(drv,fs_file): |
| 31 | +try: |
| 32 | +fs_file.__cast__()['file'].close() |
| 33 | +exceptOSErrorase: |
| 34 | +raiseRuntimeError("fs_close_callback(%s) exception: %s"% (fs_file.__cast__()['path'],e)) |
| 35 | + |
| 36 | +returnlv.FS_RES.OK |
| 37 | + |
| 38 | + |
| 39 | +def_fs_read_cb(drv,fs_file,buf,btr,br): |
| 40 | +try: |
| 41 | +tmp_data=fs_file.__cast__()['file'].read(btr) |
| 42 | +buf.__dereference__(btr)[0:len(tmp_data)]=tmp_data |
| 43 | +br.__dereference__(4)[0:4]=struct.pack("<L",len(tmp_data)) |
| 44 | +exceptOSErrorase: |
| 45 | +raiseRuntimeError("fs_read_callback(%s) exception %s"% (fs_file.__cast__()['path'],e)) |
| 46 | + |
| 47 | +returnlv.FS_RES.OK |
| 48 | + |
| 49 | + |
| 50 | +def_fs_seek_cb(drv,fs_file,pos,whence): |
| 51 | +try: |
| 52 | +fs_file.__cast__()['file'].seek(pos,whence) |
| 53 | +exceptOSErrorase: |
| 54 | +raiseRuntimeError("fs_seek_callback(%s) exception %s"% (fs_file.__cast__()['path'],e)) |
| 55 | + |
| 56 | +returnlv.FS_RES.OK |
| 57 | + |
| 58 | + |
| 59 | +def_fs_tell_cb(drv,fs_file,pos): |
| 60 | +try: |
| 61 | +tpos=fs_file.__cast__()['file'].tell() |
| 62 | +pos.__dereference__(4)[0:4]=struct.pack("<L",tpos) |
| 63 | +exceptOSErrorase: |
| 64 | +raiseRuntimeError("fs_tell_callback(%s) exception %s"% (fs_file.__cast__()['path'],e)) |
| 65 | + |
| 66 | +returnlv.FS_RES.OK |
| 67 | + |
| 68 | + |
| 69 | +def_fs_write_cb(drv,fs_file,buf,btw,bw): |
| 70 | +try: |
| 71 | +wr=fs_file.__cast__()['file'].write(buf.__dereference__(btw)[0:btw]) |
| 72 | +bw.__dereference__(4)[0:4]=struct.pack("<L",wr) |
| 73 | +exceptOSErrorase: |
| 74 | +raiseRuntimeError("fs_write_callback(%s) exception %s"% (fs_file.__cast__()['path'],e)) |
| 75 | + |
| 76 | +returnlv.FS_RES.OK |
| 77 | + |
| 78 | +def_fs_dir_open_cb(drv,path): |
| 79 | +#print(f"_fs_dir_open_cb for path '{path}'") |
| 80 | +try: |
| 81 | +importos# for ilistdir() |
| 82 | +return {'iterator' :os.ilistdir(path)} |
| 83 | +exceptExceptionase: |
| 84 | +print(f"_fs_dir_open_cb exception:{e}") |
| 85 | +returnNone |
| 86 | + |
| 87 | +def_fs_dir_read_cb(drv,lv_fs_dir_t,buf,btr): |
| 88 | +try: |
| 89 | +iterator=lv_fs_dir_t.__cast__()['iterator'] |
| 90 | +nextfile=iterator.__next__() |
| 91 | +#print(f"nextfile: {nextfile}") |
| 92 | +filename=nextfile[0] |
| 93 | +entry_type=nextfile[1]# Type field |
| 94 | +ifentry_type==0x4000: |
| 95 | +#print(f"{filename} is a directory") |
| 96 | +filename=f"/{filename}" |
| 97 | +# Convert filename to bytes with null terminator |
| 98 | +tmp_data_bytes=filename.encode()+b'\x00' |
| 99 | +buf.__dereference__(btr)[0:len(tmp_data_bytes)]=tmp_data_bytes |
| 100 | +returnlv.FS_RES.OK |
| 101 | +exceptStopIteration: |
| 102 | +# Clear buffer and return FS_ERR when iteration ends |
| 103 | +buf.__dereference__(btr)[0:1]=b'\x00'# Empty string (null byte) |
| 104 | +returnlv.FS_RES.NOT_EX# Next entry "does not exist" |
| 105 | +exceptExceptionase: |
| 106 | +print(f"_fs_dir_read_cb exception:{e}") |
| 107 | +returnlv.FS_RES.UNKNOWN |
| 108 | + |
| 109 | +def_fs_dir_close_cb(drv,lv_fs_dir_t): |
| 110 | +#print(f"_fs_dir_close_cb called") |
| 111 | +# No need to cleanup the iterator so nothing to do |
| 112 | +returnlv.FS_RES.OK |
| 113 | + |
| 114 | +deffs_register(fs_drv,letter,cache_size=500): |
| 115 | + |
| 116 | +fs_drv.init() |
| 117 | +fs_drv.letter=ord(letter) |
| 118 | +fs_drv.open_cb=_fs_open_cb |
| 119 | +fs_drv.read_cb=_fs_read_cb |
| 120 | +fs_drv.write_cb=_fs_write_cb |
| 121 | +fs_drv.seek_cb=_fs_seek_cb |
| 122 | +fs_drv.tell_cb=_fs_tell_cb |
| 123 | +fs_drv.close_cb=_fs_close_cb |
| 124 | +fs_drv.dir_open_cb=_fs_dir_open_cb |
| 125 | +fs_drv.dir_read_cb=_fs_dir_read_cb |
| 126 | +#fs_drv.dir_close_cb = _fs_dir_close_cb |
| 127 | + |
| 128 | +ifcache_size>=0: |
| 129 | +fs_drv.cache_size=cache_size |
| 130 | + |
| 131 | +fs_drv.register() |
| 132 | + |