summaryrefslogtreecommitdiff
path: root/src/Components/Ble/DfuService.h
blob: 73846c86440ce9813eb80848d55fc86edcd2c35c (plain)
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
#pragma once

#include <cstdint>
#include <array>

#include <host/ble_gap.h>

namespace Pinetime {
  namespace System {
    class SystemTask;
  }
  namespace Drivers {
    class SpiNorFlash;
  }
  namespace Controllers {
    class Ble;

    class DfuService {
      public:
        DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
                   Pinetime::Drivers::SpiNorFlash &spiNorFlash);

        void Init();

        bool Validate();

        int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
        void OnNotificationTimer();
        void OnTimeout();

        void Reset();

      private:
        Pinetime::System::SystemTask &systemTask;
        Pinetime::Controllers::Ble &bleController;
        Pinetime::Drivers::SpiNorFlash &spiNorFlash;

        static constexpr uint16_t dfuServiceId{0x1530};
        static constexpr uint16_t packetCharacteristicId{0x1532};
        static constexpr uint16_t controlPointCharacteristicId{0x1531};
        static constexpr uint16_t revisionCharacteristicId{0x1534};

        uint16_t revision{0x0008};

        static constexpr ble_uuid128_t serviceUuid{
                .u {.type = BLE_UUID_TYPE_128},
                .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
                          0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}
        };

        static constexpr ble_uuid128_t packetCharacteristicUuid{
                .u {.type = BLE_UUID_TYPE_128},
                .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
                          0xDE, 0xEF, 0x12, 0x12, 0x32, 0x15, 0x00, 0x00}
        };

        static constexpr ble_uuid128_t controlPointCharacteristicUuid{
                .u {.type = BLE_UUID_TYPE_128},
                .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
                          0xDE, 0xEF, 0x12, 0x12, 0x31, 0x15, 0x00, 0x00}
        };

        static constexpr ble_uuid128_t revisionCharacteristicUuid{
                .u {.type = BLE_UUID_TYPE_128},
                .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
                          0xDE, 0xEF, 0x12, 0x12, 0x34, 0x15, 0x00, 0x00}
        };

        struct ble_gatt_chr_def characteristicDefinition[4];
        struct ble_gatt_svc_def serviceDefinition[2];
        uint16_t packetCharacteristicHandle;
        uint16_t controlPointCharacteristicHandle;
        uint16_t revisionCharacteristicHandle;

        enum class States : uint8_t {
            Idle, Init, Start, Data, Validate, Validated
        };
        States state = States::Idle;

        enum class ImageTypes : uint8_t {
            NoImage = 0x00,
            SoftDevice = 0x01,
            Bootloader = 0x02,
            SoftDeviceAndBootloader = 0x03,
            Application = 0x04
        };

        enum class Opcodes : uint8_t {
            StartDFU = 0x01,
            InitDFUParameters = 0x02,
            ReceiveFirmwareImage = 0x03,
            ValidateFirmware = 0x04,
            ActivateImageAndReset = 0x05,
            PacketReceiptNotificationRequest = 0x08,
            Response = 0x10,
            PacketReceiptNotification = 0x11
        };

        enum class ErrorCodes {
            NoError = 0x01,
            InvalidState = 0x02,
            NotSupported = 0x03,
            DataSizeExceedsLimits = 0x04,
            CrcError = 0x05,
            OperationFailed = 0x06
        };

        uint8_t nbPacketsToNotify = 0;
        uint32_t nbPacketReceived = 0;
        uint32_t bytesReceived = 0;
        uint32_t writeOffset = 0x40000;

        uint32_t softdeviceSize = 0;
        uint32_t bootloaderSize = 0;
        uint32_t applicationSize = 0;
        static constexpr uint32_t maxImageSize = 475136;
        uint16_t expectedCrc = 0;

        int SendDfuRevision(os_mbuf *om) const;

        void SendNotification(uint16_t connectionHandle, const uint8_t *data, const size_t size);

        int WritePacketHandler(uint16_t connectionHandle, os_mbuf *om);

        int ControlPointHandler(uint16_t connectionHandle, os_mbuf *om);

        uint8_t tempBuffer[200];

        uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc);

        void WriteMagicNumber();
        TimerHandle_t notificationTimer;
        TimerHandle_t timeoutTimer;

        uint16_t notificatonConnectionHandle = 0;
        size_t notificationSize = 0;
        uint8_t notificationBuffer[10];
    };
  }
}