ref: fdc89f1a20889c0295534f58dc2e82ce8c55a18b
doc/BLEFS.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# BLE FS --- The BLE FS protocol in InfiniTime is mostly Adafruit's BLE file transfer protocol, as described in [adafruit/Adafruit_CircuitPython_BLE_File_Transfer](https://github.com/adafruit/Adafruit_CircuitPython_BLE_File_Transfer). There are some deviations, such as the status codes. These will be described later in the document. --- ## UUIDs There are two relevant UUIDs in this protocol: the version characteristic, and the raw transfer characteristic. ### Version UUID: `adaf0100-4669-6c65-5472-616e73666572` The version characteristic returns the version of the protocol to which the sender adheres. It returns a single unsigned 32-bit integer. The latest version at the time of writing this is 4. ### Transfer UUID: `adaf0200-4669-6c65-5472-616e73666572` The transfer characteristic is responsible for all the data transfer between the client and the watch. It supports write and notify. Writing a packet on the characteristic results in a response via notify. --- ## Usage The separator for paths is `/`, and absolute paths must start with `/`. All of the following commands and responses are transferred via the transfer characteristic ### Read file To begin reading a file, a header must first be sent. The header packet should be formatted like so: - Command (single byte): `0x10` - 1 byte of padding - Unsigned 16-bit integer encoding the length of the file path. - Unsigned 32-bit integer encoding the location at which to start reading the first chunk. - Unsigned 32-bit integer encoding the amount of bytes to be read. - File path: UTF-8 encoded string that is _not_ null terminated. To continue reading the file after this initial packet, the following packet should be sent until all the data has been received. No close command is required after the data has been received. - Command (single byte): `0x12` - Status: `0x01` - 2 bytes of padding - Unsigned 32-bit integer encoding the location at which to start reading the next chunk. - Unsigned 32-bit integer encoding the amount of bytes to be read. This may be different from the size in the header. Both of these commands receive the following response: - Command (single byte): `0x11` - Status (signed 8-bit integer) - 2 bytes of padding - Unsigned 32-bit integer encoding the offset of this chunk - Unsigned 32-bit integer encoding the total size of the file - Unsigned 32-bit integer encoding the amount of data in the current chunk - Contents of the current chunk ### Write file To begin writing to a file, a header must first be sent. The header packet should be formatted like so: - Command (single byte): `0x20` - 1 byte of padding - Unsigned 16-bit integer encoding the length of the file path. - Unsigned 32-bit integer encoding the location at which to start writing to the file. - Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. This will be used as the modification time. At the time of writing, this is not implemented in InfiniTime, but may be in the future. - Unsigned 32-bit integer encoding the size of the file that will be sent - File path: UTF-8 encoded string that is _not_ null terminated. To continue reading the file after this initial packet, the following packet should be sent until all the data has been sent and a response had been received with 0 free space. No close command is required after the data has been received. - Command (single byte): `0x22` - Status: `0x01` - 2 bytes of padding. - Unsigned 32-bit integer encoding the location at which to write the next chunk. - Unsigned 32-bit integer encoding the amount of bytes to be written. - Data Both of these commands receive the following response: - Command (single byte): `0x21` - Status (signed 8-bit integer) - 2 bytes of padding - Unsigned 32-bit integer encoding the current offset in the file - Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. This will be used as the modification time. At the time of writing, this is not implemented in InfiniTime, but may be in the future. - Unsigned 32-bit integer encoding the amount of data the client can send until the file is full. ### Delete file - Command (single byte): `0x30` - 1 byte of padding - Unsigned 16-bit integer encoding the length of the file path. - File path: UTF-8 encoded string that is _not_ null terminated. The response to this packet will be as follows: - Command (single byte): `0x31` - Status (signed 8-bit integer) ### Make directory - Command (single byte): `0x40` - 1 byte of padding - Unsigned 16-bit integer encoding the length of the file path. - 4 bytes of padding - Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. - File path: UTF-8 encoded string that is _not_ null terminated. The response to this packet will be as follows: - Command (single byte): `0x41` - Status (signed 8-bit integer) - 6 bytes of padding - Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. ### List directory Paths returned by this command are relative to the path given in the request - Command (single byte): `0x50` - 1 byte of padding - Unsigned 16-bit integer encoding the length of the file path. - File path: UTF-8 encoded string that is _not_ null terminated. The response to this packet will be as follows. Responses will be sent until the final entry, which will have entry number == total entries - Command (single byte): `0x51` - Status (signed 8-bit integer) - Unsigned 16-bit integer encoding the length of the file path. - Unsigned 32-bit integer encoding the entry number - Unsigned 32-bit integer encoding the total amount of entries - Flags: unsigned 32-bit integer - Bit 0: Set when entry is a directory - Bits 1-7: Reserved - Unsigned 64-bit integer encoding the unix timestamp of the modification time with nanosecond resolution - Unsigned 32-bit integer encoding the size of the file - Path: UTF-8 encoded string that is _not_ null terminated. ### Move file or directory - Command (single byte): `0x60` - 1 byte of padding - Unsigned 16-bit integer encoding the length of the old path - Unsigned 16-bit integer encoding the length of the new path - Old path: UTF-8 encoded string that is _not_ null terminated. - 1 byte of padding - Newpath: UTF-8 encoded string that is _not_ null terminated. The response to this packet will be as follows: - Command (single byte): `0x61` - Status (signed 8-bit integer) --- ## Deviations This section describes the differences between Adafruit's spec and InfiniTime's implementation. ### Status codes The status codes returned by InfiniTime are a signed 8-bit integer, rather than an unsigned one as described in the spec. InfiniTime uses LittleFS error codes rather than the ones described in the spec. Those codes can be found in [lfs.h](https://github.com/littlefs-project/littlefs/blob/master/lfs.h#L70). |