/** * @file protocol.h * @brief OTA Chunk Transfer Protocol Definitions */ #ifndef OTA_CHUNK_PROTOCOL_H #define OTA_CHUNK_PROTOCOL_H #include #include #include #ifdef __cplusplus extern "C" { #endif /* ========================================================================= * Protocol Constants * ========================================================================= */ #define CHUNK_PROTOCOL_VERSION 1 #define CHUNK_DEFAULT_SIZE 1024 #define CHUNK_MIN_SIZE 256 #define CHUNK_MAX_SIZE 65535 #define CHUNK_INDEX_MAX 65535 /* 2-byte unsigned */ /* Maximum file size: CHUNK_INDEX_MAX * CHUNK_MAX_SIZE ≈ 4.29 GB */ #define CHUNK_MAX_FILE_SIZE ((uint32_t)CHUNK_INDEX_MAX * CHUNK_MAX_SIZE) /* ========================================================================= * Protocol Structures * ========================================================================= */ /** * Chunk packet structure (network format) * * Layout: * +------------+----------------+----------+ * | chunk_idx | payload (N B) | crc32 | * | 2 B | N B | 4 B | * +------------+----------------+----------+ * * Note: This structure includes padding. Use packing for network transmission. */ #pragma pack(push, 1) typedef struct { uint16_t chunk_idx; /* Chunk index (little-endian) */ /* payload follows immediately */ /* crc32 follows payload */ } chunk_header_t; #pragma pack(pop) /** * Chunk data descriptor (in-memory representation) */ typedef struct { uint16_t chunk_idx; /* Chunk index */ uint16_t payload_len; /* Payload length */ uint8_t *payload; /* Payload pointer */ uint32_t crc32; /* CRC32 of payload */ } chunk_data_t; /** * Transfer state */ typedef enum { CHUNK_STATE_IDLE, CHUNK_STATE_FETCHING_SIZE, CHUNK_STATE_TRANSFERRING, CHUNK_STATE_RESUMING, CHUNK_STATE_COMPLETE, CHUNK_STATE_ERROR } chunk_state_t; /** * Error codes */ typedef enum { CHUNK_ERR_OK = 0, CHUNK_ERR_INVALID_PARAM = -1, CHUNK_ERR_MEMORY = -2, CHUNK_ERR_NETWORK = -3, CHUNK_ERR_CRC = -4, CHUNK_ERR_FILE_NOT_FOUND = -5, CHUNK_ERR_RANGE_INVALID = -6, CHUNK_ERR_TIMEOUT = -7, CHUNK_ERR_SERVER_ERROR = -8, } chunk_err_t; /* ========================================================================= * Callback Types * ========================================================================= */ /** * Chunk received callback * * @param chunk_idx Chunk index * @param data Payload data * @param len Payload length * @param user_ctx User context */ typedef void (*chunk_received_cb)(uint16_t chunk_idx, const uint8_t *data, uint16_t len, void *user_ctx); /** * Transfer complete callback * * @param total_bytes Total bytes transferred * @param user_ctx User context */ typedef void (*transfer_complete_cb)(uint32_t total_bytes, void *user_ctx); /** * Transfer error callback * * @param err_code Error code * @param user_ctx User context */ typedef void (*transfer_error_cb)(chunk_err_t err_code, void *user_ctx); /** * Progress update callback * * @param current_chunk Current chunk index * @param total_chunks Total chunks * @param user_ctx User context */ typedef void (*progress_cb)(uint16_t current_chunk, uint16_t total_chunks, void *user_ctx); /* ========================================================================= * Configuration Structures * ========================================================================= */ /** * Chunk client configuration */ typedef struct { const char *server_url; /* Server base URL */ uint16_t chunk_size; /* Chunk size in bytes */ uint32_t timeout_ms; /* Timeout in milliseconds */ /* Callbacks */ chunk_received_cb on_chunk_received; transfer_complete_cb on_complete; transfer_error_cb on_error; progress_cb on_progress; void *user_ctx; /* User context passed to callbacks */ } chunk_client_config_t; /** * Chunk server configuration */ typedef struct { uint16_t port; /* Server port */ const char *root_path; /* Root directory for files */ uint16_t chunk_size; /* Chunk size in bytes */ } chunk_server_config_t; /* ========================================================================= * CRC32 Functions * ========================================================================= */ /** * Calculate CRC32 (IEEE 802.3 polynomial) * * @param data Input data * @param len Input length * @return CRC32 value */ uint32_t chunk_crc32(const uint8_t *data, size_t len); /** * Update CRC32 with additional data * * @param crc Previous CRC value * @param data New data * @param len Data length * @return Updated CRC value */ uint32_t chunk_crc32_update(uint32_t crc, const uint8_t *data, size_t len); /* ========================================================================= * Client Functions * ========================================================================= */ /** * Initialize chunk client * * @param config Configuration structure * @return CHUNK_ERR_OK on success, error code otherwise */ chunk_err_t chunk_client_init(const chunk_client_config_t *config); /** * Start file download * * @param filename Filename to download * @return CHUNK_ERR_OK on success, error code otherwise */ chunk_err_t chunk_client_download(const char *filename); /** * Resume download from specific chunk * * @param filename Filename to download * @param start_chunk Chunk index to resume from * @return CHUNK_ERR_OK on success, error code otherwise */ chunk_err_t chunk_client_resume(const char *filename, uint16_t start_chunk); /** * Cancel current transfer */ void chunk_client_cancel(void); /** * Get current transfer state * * @return Current state */ chunk_state_t chunk_client_get_state(void); /** * Get current progress * * @param current_chunk Current chunk index (output) * @param total_chunks Total chunks (output) * @return CHUNK_ERR_OK on success */ chunk_err_t chunk_client_get_progress(uint16_t *current_chunk, uint16_t *total_chunks); /** * Cleanup client resources */ void chunk_client_cleanup(void); /* ========================================================================= * Server Functions (for reference / embedded use) * ========================================================================= */ /** * Initialize chunk server * * @param config Configuration structure * @return CHUNK_ERR_OK on success, error code otherwise */ chunk_err_t chunk_server_init(const chunk_server_config_t *config); /** * Start server (blocking) * * @return CHUNK_ERR_OK on success, error code otherwise */ chunk_err_t chunk_server_start(void); /** * Stop server */ void chunk_server_stop(void); /* ========================================================================= * Utility Functions * ========================================================================= */ /** * Calculate total chunks for a file * * @param file_size File size in bytes * @param chunk_size Chunk size in bytes * @return Total number of chunks */ static inline uint16_t chunk_calc_total_chunks(uint32_t file_size, uint16_t chunk_size) { return (uint16_t)((file_size + chunk_size - 1) / chunk_size); } /** * Calculate payload size for a chunk * * @param file_size File size in bytes * @param chunk_idx Chunk index * @param chunk_size Chunk size in bytes * @return Payload size for this chunk */ static inline uint16_t chunk_calc_payload_size(uint32_t file_size, uint16_t chunk_idx, uint16_t chunk_size) { uint32_t remaining = file_size - (uint32_t)chunk_idx * chunk_size; return (uint16_t)(remaining < chunk_size ? remaining : chunk_size); } #ifdef __cplusplus } #endif #endif /* OTA_CHUNK_PROTOCOL_H */