{
  "name": "Bootloader",
  "status": "stable",
  "shortId": "bootloader",
  "camelName": "bootloader",
  "shortName": "bootloader",
  "extends": [
    "_base"
  ],
  "notes": {
    "short": "Allows flashing (reprogramming) devices over Jacdac.\n\nThis is typically implemented by having a separate _bootloader_ mode, as opposed to _application_ mode\non the module to be flashed.\nThe bootloader mode is entered on every device reset, for about 300ms.\nThe bootloader will generally not announce itself, until it gets some command.\nOnce it gets the command, it will stay in application mode.\n\nTypically, you ask the module (in application mode) to reset, while sending broadcast\n`info` commands to all bootloaders every 100ms or so.\nAlternatively, you ask the the user to disconnect and re-connect the module, while\nbroadcasting `info` commands.\nThe second method works even if the application is damaged (eg., due to an aborted flash).\n\nWhen device is in bootloader mode, the device ID may change compared to application mode,\nby flipping the first bit in the first byte of the device identifier."
  },
  "classIdentifier": 536516936,
  "enums": {
    "Error": {
      "name": "Error",
      "storage": 4,
      "members": {
        "NoError": 0,
        "PacketTooSmall": 1,
        "OutOfFlashableRange": 2,
        "InvalidPageOffset": 3,
        "NotPageAligned": 4
      }
    }
  },
  "constants": {},
  "packets": [
    {
      "kind": "report",
      "name": "command_not_implemented",
      "identifier": 3,
      "description": "This report may be emitted by a server in response to a command (action or register operation)\nthat it does not understand.\nThe `service_command` and `packet_crc` fields are copied from the command packet that was unhandled.\nNote that it's possible to get an ACK, followed by such an error report.",
      "fields": [
        {
          "name": "service_command",
          "type": "u16",
          "storage": 2,
          "isSimpleType": true
        },
        {
          "name": "packet_crc",
          "type": "u16",
          "storage": 2,
          "isSimpleType": true
        }
      ],
      "identifierName": "command_not_implemented",
      "packFormat": "u16 u16",
      "derived": "_base"
    },
    {
      "kind": "const",
      "name": "instance_name",
      "identifier": 265,
      "description": "A friendly name that describes the role of this service instance in the device.\nIt often corresponds to what's printed on the device:\nfor example, `A` for button A, or `S0` for servo channel 0.\nWords like `left` should be avoided because of localization issues (unless they are printed on the device).",
      "fields": [
        {
          "name": "_",
          "type": "string",
          "storage": 0
        }
      ],
      "optional": true,
      "identifierName": "instance_name",
      "packFormat": "s",
      "derived": "_base"
    },
    {
      "kind": "ro",
      "name": "status_code",
      "identifier": 259,
      "description": "Reports the current state or error status of the device. ``code`` is a standardized value from \nthe Jacdac status/error codes. ``vendor_code`` is any vendor specific error code describing the device\nstate. This report is typically not queried, when a device has an error, it will typically\nadd this report in frame along with the announce packet. If a service implements this register,\nit should also support the ``status_code_changed`` event defined below.",
      "fields": [
        {
          "name": "code",
          "type": "u16",
          "storage": 2,
          "isSimpleType": true
        },
        {
          "name": "vendor_code",
          "type": "u16",
          "storage": 2,
          "isSimpleType": true
        }
      ],
      "optional": true,
      "identifierName": "status_code",
      "packFormat": "u16 u16",
      "derived": "_base"
    },
    {
      "kind": "rw",
      "name": "client_variant",
      "identifier": 9,
      "description": "An optional register in the format of a URL query string where the client can provide hints how\nthe device twin should be rendered. If the register is not implemented, the client library can simulate the register client side.",
      "fields": [
        {
          "name": "_",
          "type": "string",
          "storage": 0
        }
      ],
      "optional": true,
      "identifierName": "client_variant",
      "packFormat": "s",
      "derived": "_base"
    },
    {
      "kind": "event",
      "name": "status_code_changed",
      "identifier": 4,
      "description": "Notifies that the status code of the service changed.",
      "fields": [
        {
          "name": "code",
          "type": "u16",
          "storage": 2,
          "isSimpleType": true
        },
        {
          "name": "vendor_code",
          "type": "u16",
          "storage": 2,
          "isSimpleType": true
        }
      ],
      "optional": true,
      "identifierName": "status_code_changed",
      "packFormat": "u16 u16",
      "derived": "_base"
    },
    {
      "kind": "command",
      "name": "info",
      "identifier": 0,
      "description": "The `service_class` is always `0x1ffa9948`. The `product_identifier` identifies the kind of firmware\nthat \"fits\" this device.",
      "fields": [],
      "identifierName": "announce",
      "hasReport": true
    },
    {
      "kind": "report",
      "name": "info",
      "identifier": 0,
      "description": "The `service_class` is always `0x1ffa9948`. The `product_identifier` identifies the kind of firmware\nthat \"fits\" this device.",
      "fields": [
        {
          "name": "service_class",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "page_size",
          "unit": "B",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "flashable_size",
          "unit": "B",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "product_identifier",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        }
      ],
      "secondary": true,
      "packFormat": "u32 u32 u32 u32"
    },
    {
      "kind": "command",
      "name": "set_session",
      "identifier": 129,
      "description": "The flashing server should generate a random id, and use this command to set it.",
      "fields": [
        {
          "name": "session_id",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        }
      ],
      "hasReport": true,
      "packFormat": "u32"
    },
    {
      "kind": "report",
      "name": "set_session",
      "identifier": 129,
      "description": "The flashing server should generate a random id, and use this command to set it.",
      "fields": [
        {
          "name": "session_id",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        }
      ],
      "secondary": true,
      "packFormat": "u32"
    },
    {
      "kind": "command",
      "name": "page_data",
      "identifier": 128,
      "description": "Use to send flashing data. A physical page is split into `chunk_max + 1` chunks, where `chunk_no = 0 ... chunk_max`.\nEach chunk is stored at `page_address + page_offset`. `page_address` has to be equal in all chunks,\nand is included in response.\nOnly the last chunk causes writing to flash and elicits response.\n\nErrors not listed are also possible. Errors larger than `0xffff` indicate de-synchronization on chunk numbers.\n\nWhile this command is technically `unique`, the bootloader client will retry failed pages.\nBootloaders typically will not support reliable commands delivered over pipes.",
      "fields": [
        {
          "name": "page_address",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "page_offset",
          "type": "u16",
          "storage": 2,
          "isSimpleType": true
        },
        {
          "name": "chunk_no",
          "type": "u8",
          "storage": 1,
          "isSimpleType": true
        },
        {
          "name": "chunk_max",
          "type": "u8",
          "storage": 1,
          "isSimpleType": true
        },
        {
          "name": "session_id",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "reserved0",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "reserved1",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "reserved2",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "reserved3",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "page_data",
          "type": "bytes",
          "storage": 208,
          "isSimpleType": true,
          "maxBytes": 208
        }
      ],
      "unique": true,
      "hasReport": true,
      "packFormat": "u32 u16 u8 u8 u32 u32 u32 u32 u32 b[208]"
    },
    {
      "kind": "report",
      "name": "page_data",
      "identifier": 128,
      "description": "Use to send flashing data. A physical page is split into `chunk_max + 1` chunks, where `chunk_no = 0 ... chunk_max`.\nEach chunk is stored at `page_address + page_offset`. `page_address` has to be equal in all chunks,\nand is included in response.\nOnly the last chunk causes writing to flash and elicits response.\n\nErrors not listed are also possible. Errors larger than `0xffff` indicate de-synchronization on chunk numbers.\n\nWhile this command is technically `unique`, the bootloader client will retry failed pages.\nBootloaders typically will not support reliable commands delivered over pipes.",
      "fields": [
        {
          "name": "session_id",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        },
        {
          "name": "page_error",
          "type": "Error",
          "storage": 4
        },
        {
          "name": "page_address",
          "type": "u32",
          "storage": 4,
          "isSimpleType": true
        }
      ],
      "secondary": true,
      "packFormat": "u32 u32 u32"
    }
  ],
  "tags": [
    "C",
    "management"
  ]
}