Flipper Zero Firmware
Loading...
Searching...
No Matches
expansion_protocol.h
Go to the documentation of this file.
1
12#pragma once
13
14#include <stddef.h>
15#include <stdint.h>
16#include <stdbool.h>
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
25#define EXPANSION_PROTOCOL_DEFAULT_BAUD_RATE (9600UL)
26
30#define EXPANSION_PROTOCOL_MAX_DATA_SIZE (64U)
31
35#define EXPANSION_PROTOCOL_TIMEOUT_MS (250U)
36
40#define EXPANSION_PROTOCOL_BAUD_CHANGE_DT_MS (25U)
41
53
62
70
71#pragma pack(push, 1)
72
76typedef struct {
77 uint8_t type;
79
83typedef struct {
86
90typedef struct {
91 uint8_t error;
93
97typedef struct {
98 uint32_t baud;
100
104typedef struct {
105 uint8_t command;
107
111typedef struct {
113 uint8_t size;
117
131
132#pragma pack(pop)
133
138
149typedef size_t (*ExpansionFrameReceiveCallback)(uint8_t* data, size_t data_size, void* context);
150
161typedef size_t (*ExpansionFrameSendCallback)(const uint8_t* data, size_t data_size, void* context);
162
171static inline size_t expansion_frame_get_encoded_size(const ExpansionFrame* frame) {
172 switch(frame->header.type) {
174 return sizeof(frame->header);
176 return sizeof(frame->header) + sizeof(frame->content.status);
178 return sizeof(frame->header) + sizeof(frame->content.baud_rate);
180 return sizeof(frame->header) + sizeof(frame->content.control);
182 return sizeof(frame->header) + sizeof(frame->content.data.size) + frame->content.data.size;
183 default:
184 return 0;
185 }
186}
187
199static inline bool expansion_frame_get_remaining_size(
200 const ExpansionFrame* frame,
201 size_t received_size,
202 size_t* remaining_size) {
203 if(received_size < sizeof(ExpansionFrameHeader)) {
204 // Frame type is unknown as of now
205 *remaining_size = sizeof(ExpansionFrameHeader);
206 return true;
207 }
208
209 const size_t received_content_size = received_size - sizeof(ExpansionFrameHeader);
210 size_t content_size;
211
212 switch(frame->header.type) {
214 content_size = 0;
215 break;
217 content_size = sizeof(frame->content.status);
218 break;
220 content_size = sizeof(frame->content.baud_rate);
221 break;
223 content_size = sizeof(frame->content.control);
224 break;
226 if(received_content_size < sizeof(frame->content.data.size)) {
227 // Data size is unknown as of now
228 content_size = sizeof(frame->content.data.size);
229 } else if(frame->content.data.size > sizeof(frame->content.data.bytes)) {
230 // Malformed frame or garbage input
231 return false;
232 } else {
233 content_size = sizeof(frame->content.data.size) + frame->content.data.size;
234 }
235 break;
236 default:
237 return false;
238 }
239
240 if(content_size > received_content_size) {
241 *remaining_size = content_size - received_content_size;
242 } else {
243 *remaining_size = 0;
244 }
245
246 return true;
247}
248
258
268static inline ExpansionFrameChecksum
269 expansion_protocol_get_checksum(const uint8_t* data, size_t data_size) {
270 ExpansionFrameChecksum checksum = 0;
271 for(size_t i = 0; i < data_size; ++i) {
272 checksum ^= data[i];
273 }
274 return checksum;
275}
276
287static inline ExpansionProtocolStatus expansion_protocol_decode(
288 ExpansionFrame* frame,
290 void* context) {
291 size_t total_size = 0;
292 size_t remaining_size;
293
294 while(true) {
295 if(!expansion_frame_get_remaining_size(frame, total_size, &remaining_size)) {
297 } else if(remaining_size == 0) {
298 break;
299 }
300
301 const size_t received_size =
302 receive((uint8_t*)frame + total_size, remaining_size, context);
303
304 if(received_size == 0) {
306 }
307
308 total_size += received_size;
309 }
310
311 ExpansionFrameChecksum checksum;
312 const size_t received_size = receive(&checksum, sizeof(checksum), context);
313
314 if(received_size != sizeof(checksum)) {
316 } else if(checksum != expansion_protocol_get_checksum((const uint8_t*)frame, total_size)) {
318 } else {
320 }
321}
322
331static inline ExpansionProtocolStatus expansion_protocol_encode(
332 const ExpansionFrame* frame,
334 void* context) {
335 const size_t encoded_size = expansion_frame_get_encoded_size(frame);
336 if(encoded_size == 0) {
338 }
339
340 const ExpansionFrameChecksum checksum =
341 expansion_protocol_get_checksum((const uint8_t*)frame, encoded_size);
342
343 if((send((const uint8_t*)frame, encoded_size, context) != encoded_size) ||
344 (send(&checksum, sizeof(checksum), context) != sizeof(checksum))) {
346 } else {
348 }
349}
350
351#ifdef __cplusplus
352}
353#endif
ExpansionFrameControlCommand
Enumeration of suported control commands.
Definition expansion_protocol.h:66
@ ExpansionFrameControlCommandStartRpc
Start an RPC session.
Definition expansion_protocol.h:67
@ ExpansionFrameControlCommandStopRpc
Stop an open RPC session.
Definition expansion_protocol.h:68
ExpansionProtocolStatus
Enumeration of protocol parser statuses.
Definition expansion_protocol.h:252
@ ExpansionProtocolStatusErrorFormat
Invalid frame type.
Definition expansion_protocol.h:254
@ ExpansionProtocolStatusOk
No error has occurred.
Definition expansion_protocol.h:253
@ ExpansionProtocolStatusErrorChecksum
Checksum mismatch.
Definition expansion_protocol.h:255
@ ExpansionProtocolStatusErrorCommunication
Input/output error.
Definition expansion_protocol.h:256
ExpansionFrameError
Enumeration of possible error types.
Definition expansion_protocol.h:57
@ ExpansionFrameErrorNone
No error occurred.
Definition expansion_protocol.h:58
@ ExpansionFrameErrorUnknown
An unknown error has occurred (generic response).
Definition expansion_protocol.h:59
@ ExpansionFrameErrorBaudRate
Requested baud rate is not supported.
Definition expansion_protocol.h:60
ExpansionFrameType
Enumeration of supported frame types.
Definition expansion_protocol.h:45
@ ExpansionFrameTypeData
Data frame.
Definition expansion_protocol.h:50
@ ExpansionFrameTypeHeartbeat
Heartbeat frame.
Definition expansion_protocol.h:46
@ ExpansionFrameTypeReserved
Special value.
Definition expansion_protocol.h:51
@ ExpansionFrameTypeControl
Control frame.
Definition expansion_protocol.h:49
@ ExpansionFrameTypeStatus
Status report frame.
Definition expansion_protocol.h:47
@ ExpansionFrameTypeBaudRate
Baud rate negotiation frame.
Definition expansion_protocol.h:48
#define EXPANSION_PROTOCOL_MAX_DATA_SIZE
Maximum data size per frame, in bytes.
Definition expansion_protocol.h:30
size_t(* ExpansionFrameReceiveCallback)(uint8_t *data, size_t data_size, void *context)
Receive function type declaration.
Definition expansion_protocol.h:149
size_t(* ExpansionFrameSendCallback)(const uint8_t *data, size_t data_size, void *context)
Send function type declaration.
Definition expansion_protocol.h:161
uint8_t ExpansionFrameChecksum
Expansion checksum type.
Definition expansion_protocol.h:137
Baud rate frame contents.
Definition expansion_protocol.h:97
uint32_t baud
Requested baud rate.
Definition expansion_protocol.h:98
Control frame contents.
Definition expansion_protocol.h:104
uint8_t command
Control command number.
Definition expansion_protocol.h:105
Data frame contents.
Definition expansion_protocol.h:111
uint8_t bytes[EXPANSION_PROTOCOL_MAX_DATA_SIZE]
Data bytes.
Definition expansion_protocol.h:115
uint8_t size
Size of the data.
Definition expansion_protocol.h:113
Frame header structure.
Definition expansion_protocol.h:76
uint8_t type
Type of the frame.
Definition expansion_protocol.h:77
Heartbeat frame contents.
Definition expansion_protocol.h:83
Expansion protocol frame structure.
Definition expansion_protocol.h:121
ExpansionFrameStatus status
Status frame contents.
Definition expansion_protocol.h:125
ExpansionFrameData data
Data frame contents.
Definition expansion_protocol.h:128
ExpansionFrameHeader header
Header of the frame.
Definition expansion_protocol.h:122
ExpansionFrameBaudRate baud_rate
Baud rate frame contents.
Definition expansion_protocol.h:126
union ExpansionFrame::@4 content
Contents of the frame.
ExpansionFrameHeartbeat heartbeat
Heartbeat frame contents.
Definition expansion_protocol.h:124
ExpansionFrameControl control
Control frame contents.
Definition expansion_protocol.h:127
Status frame contents.
Definition expansion_protocol.h:90
uint8_t error
Reported error code.
Definition expansion_protocol.h:91