syntax = "proto3";
package particle.ctrl;

import "control/extensions.proto";
import "cloud/describe.proto";

option java_package = "io.particle.firmwareprotos.ctrl";

enum StorageType {
  INVALID_STORAGE = 0;
  INTERNAL = 1; // Internal flash
}

enum SectionType {
  INVALID_SECTION = 0;
  FIRMWARE = 1; // Firmware module
  OTA_BACKUP = 2; // OTA backup
  FACTORY_BACKUP = 3; // Factory backup
  CONFIG = 4; // Device configuration
  EEPROM = 5; // Emulated EEPROM
}

enum FirmwareModuleType {
  INVALID_FIRMWARE_MODULE = 0;
  BOOTLOADER = 1; // Bootloader
  SYSTEM_PART = 2; // System part
  USER_PART = 3; // User part
  MONO_FIRMWARE = 4; // Monolithic firmware
  NCP_FIRMWARE = 5; // NCP firmware
  RADIO_STACK = 6; // Radio stack binary
}

enum FirmwareModuleValidityFlag {
  NO_VALIDATION_ERRORS = 0;
  INTEGRITY_CHECK_FAILED = 0x01; // Integrity check failed
  DEPENDENCY_CHECK_FAILED = 0x02; // Dependency check failed
}

enum SectionFlag {
  NO_SECTION_FLAGS = 0;
  CAN_READ = 0x01; // Section data is readable
  CAN_WRITE = 0x02; // Section data is writable
  CAN_CLEAR = 0x04; // Section can be cleared
  CAN_GET_SIZE = 0x08; // Actual size of the section data can be determined
  NEED_CLEAR = 0x10; // Section needs to be cleared before writing
}

enum FileFormat {
  BIN = 0; // Binary
  MINIZ = 1; // miniz compressed
}

// Start the firmware update process
message StartFirmwareUpdateRequest {
  option (type_id) = 250; // CTRL_REQUEST_START_FIRMWARE_UPDATE
  uint32 size = 1; // Size of the firmware binary
  FileFormat format = 2; // Format of the firmware binary
}

message StartFirmwareUpdateReply {
  uint32 chunk_size = 1; // Maximum chunk size
}

// Finish the firmware update process
message FinishFirmwareUpdateRequest {
  option (type_id) = 251;  // CTRL_REQUEST_FINISH_FIRMWARE_UPDATE
  bool validate_only = 1; // When `true` it will only validate the integity of the update but won't write it to flash
}

message FinishFirmwareUpdateReply {
}

// Cancel the firmware update
message CancelFirmwareUpdateRequest {
  option (type_id) = 252;  // CTRL_REQUEST_CANCEL_FIRMWARE_UPDATE
}

message CancelFirmwareUpdateReply {
}

// Send the firmware update file
message FirmwareUpdateDataRequest {
  option (type_id) = 253;  // CTRL_REQUEST_FIRMWARE_UPDATE_DATA
  bytes data = 1;
}

message FirmwareUpdateDataReply {
}

// Describe the built-in storage
message DescribeStorageRequest {
  option (type_id) = 260; // CTRL_REQUEST_DESCRIBE_STORAGE
}

message DescribeStorageReply {
  message Section {
    message FirmwareModule {
      FirmwareModuleType type = 1; // Firmware module type
      uint32 index = 2; // Section index
    }
    SectionType type = 1; // Section type
    uint32 size = 2; // Section size
    uint32 flags = 3; // SectionFlag flags
    FirmwareModule firmware_module = 4; // Firmware module
  }
  message Storage {
    StorageType type = 1; // Storage type
    uint32 flags = 2; // SectionFlag flags
    repeated Section sections = 3; // Storage sections
  }
  repeated Storage storage = 1; // Storages
}

message ReadSectionDataRequest {
  option (type_id) = 261;  // CTRL_REQUEST_READ_SECTION_DATA
  uint32 storage = 1; // Storage index
  uint32 section = 2; // Section index
  uint32 offset = 3; // Offset
  uint32 size = 4; // Size
}

message ReadSectionDataReply {
  bytes data = 1; // Section data
}

message WriteSectionDataRequest {
  option (type_id) = 262;  // CTRL_REQUEST_WRITE_SECTION_DATA
  uint32 storage = 1; // Storage index
  uint32 section = 2; // Section index
  uint32 offset = 3; // Offset
  bytes data = 4; // Size
}

message WriteSectionDataReply {
}

message ClearSectionDataRequest {
  option (type_id) = 263;  // CTRL_REQUEST_CLEAR_SECTION_DATA
  uint32 storage = 1; // Storage index
  uint32 section = 2; // Section index
}

message ClearSectionDataReply {
}

message GetSectionDataSizeRequest {
  option (type_id) = 264;  // CTRL_REQUEST_GET_SECTION_DATA_SIZE
  uint32 storage = 1; // Storage index
  uint32 section = 2; // Section index
}

message GetSectionDataSizeReply {
  uint32 size = 1; // Section data size
}

/**
 * Get firmware module info.
 */
message GetModuleInfoRequest {
  option (type_id) = 90; // CTRL_REQUEST_GET_MODULE_INFO
}

message GetModuleInfoReply {
  // Deprecated
  message Dependency {
    FirmwareModuleType type = 1; // Module type
    uint32 index = 2; // Module index
    uint32 version = 3; // Module version
  }
  message Module {
    FirmwareModuleType type = 1; // Module type
    uint32 index = 2; // Module index
    uint32 version = 3; // Module version
    uint32 size = 4; // Module size
    uint32 validity = 5; // Validity flags (see FirmwareModuleValidityFlag)
    repeated Dependency dependencies = 6; // Module dependencies
  }
  repeated Module modules_deprecated = 1; // Firmware modules
  // /Deprecated

  // TODO: move these messages to common place
  repeated particle.cloud.FirmwareModule modules = 2; ///< Firmware modules
}

/**
 * Get asset info.
 */
message GetAssetInfoRequest {
  option (type_id) = 91; // CTRL_REQUEST_GET_ASSET_INFO
}

message GetAssetInfoReply {
  repeated particle.cloud.FirmwareModuleAsset available = 1; ///< List of valid assets currently present in device storage
  repeated particle.cloud.FirmwareModuleAsset required = 2; ///< List of valid assets currently present in device storage
}
