Rizky Ardi Maulana / mbed-os
Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed Microcontroller Library
elessair 0:f269e3021894 2 * Copyright (c) 2006-2013 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16
elessair 0:f269e3021894 17 #ifdef TARGET_NRF51822 /* DFU only supported on nrf51 platforms */
elessair 0:f269e3021894 18
elessair 0:f269e3021894 19 #ifndef __BLE_DFU_SERVICE_H__
elessair 0:f269e3021894 20 #define __BLE_DFU_SERVICE_H__
elessair 0:f269e3021894 21
elessair 0:f269e3021894 22 #include "ble/BLE.h"
elessair 0:f269e3021894 23 #include "ble/UUID.h"
elessair 0:f269e3021894 24
elessair 0:f269e3021894 25 extern "C" {
elessair 0:f269e3021894 26 #include "dfu_app_handler.h"
elessair 0:f269e3021894 27 }
elessair 0:f269e3021894 28
elessair 0:f269e3021894 29 extern const uint8_t DFUServiceBaseUUID[];
elessair 0:f269e3021894 30 extern const uint16_t DFUServiceShortUUID;
elessair 0:f269e3021894 31 extern const uint16_t DFUServiceControlCharacteristicShortUUID;
elessair 0:f269e3021894 32
elessair 0:f269e3021894 33 extern const uint8_t DFUServiceUUID[];
elessair 0:f269e3021894 34 extern const uint8_t DFUServiceControlCharacteristicUUID[];
elessair 0:f269e3021894 35 extern const uint8_t DFUServicePacketCharacteristicUUID[];
elessair 0:f269e3021894 36
elessair 0:f269e3021894 37 /**
elessair 0:f269e3021894 38 * @class DFUService
elessair 0:f269e3021894 39 * @brief Device Firmware Update Service.
elessair 0:f269e3021894 40 */
elessair 0:f269e3021894 41 class DFUService {
elessair 0:f269e3021894 42 public:
elessair 0:f269e3021894 43 /**
elessair 0:f269e3021894 44 * @brief Signature for the handover callback. The application may provide this
elessair 0:f269e3021894 45 * callback when setting up the DFU service. The callback is then
elessair 0:f269e3021894 46 * invoked before handing control over to the bootloader.
elessair 0:f269e3021894 47 */
elessair 0:f269e3021894 48 typedef void (*ResetPrepare_t)(void);
elessair 0:f269e3021894 49
elessair 0:f269e3021894 50 public:
elessair 0:f269e3021894 51 /**
elessair 0:f269e3021894 52 * @brief Adds Device Firmware Update Service to an existing BLE object.
elessair 0:f269e3021894 53 *
elessair 0:f269e3021894 54 * @param[ref] _ble
elessair 0:f269e3021894 55 * BLE object for the underlying controller.
elessair 0:f269e3021894 56 * @param[in] _handoverCallback
elessair 0:f269e3021894 57 * Application-specific handover callback.
elessair 0:f269e3021894 58 */
elessair 0:f269e3021894 59 DFUService(BLE &_ble, ResetPrepare_t _handoverCallback = NULL) :
elessair 0:f269e3021894 60 ble(_ble),
elessair 0:f269e3021894 61 controlPoint(DFUServiceControlCharacteristicUUID, controlBytes, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
elessair 0:f269e3021894 62 packet(DFUServicePacketCharacteristicUUID, packetBytes, SIZEOF_PACKET_BYTES, SIZEOF_PACKET_BYTES,
elessair 0:f269e3021894 63 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE),
elessair 0:f269e3021894 64 controlBytes(),
elessair 0:f269e3021894 65 packetBytes() {
elessair 0:f269e3021894 66 static bool serviceAdded = false; /* We only add the DFU service once. */
elessair 0:f269e3021894 67 if (serviceAdded) {
elessair 0:f269e3021894 68 return;
elessair 0:f269e3021894 69 }
elessair 0:f269e3021894 70
elessair 0:f269e3021894 71 /* Set an initial value for control bytes, so that the application's DFU service can
elessair 0:f269e3021894 72 * be distinguished from the real DFU service provided by the bootloader. */
elessair 0:f269e3021894 73 controlBytes[0] = 0xFF;
elessair 0:f269e3021894 74 controlBytes[1] = 0xFF;
elessair 0:f269e3021894 75
elessair 0:f269e3021894 76 GattCharacteristic *dfuChars[] = {&controlPoint, &packet};
elessair 0:f269e3021894 77 GattService dfuService(DFUServiceUUID, dfuChars, sizeof(dfuChars) / sizeof(GattCharacteristic *));
elessair 0:f269e3021894 78
elessair 0:f269e3021894 79 ble.addService(dfuService);
elessair 0:f269e3021894 80 handoverCallback = _handoverCallback;
elessair 0:f269e3021894 81 serviceAdded = true;
elessair 0:f269e3021894 82
elessair 0:f269e3021894 83 ble.onDataWritten(this, &DFUService::onDataWritten);
elessair 0:f269e3021894 84 }
elessair 0:f269e3021894 85
elessair 0:f269e3021894 86 /**
elessair 0:f269e3021894 87 * @brief Get the handle for the value attribute of the control characteristic.
elessair 0:f269e3021894 88 */
elessair 0:f269e3021894 89 uint16_t getControlHandle(void) const {
elessair 0:f269e3021894 90 return controlPoint.getValueHandle();
elessair 0:f269e3021894 91 }
elessair 0:f269e3021894 92
elessair 0:f269e3021894 93 /**
elessair 0:f269e3021894 94 * @brief This callback allows the DFU service to receive the initial trigger to
elessair 0:f269e3021894 95 * hand control over to the bootloader. First, the application is given a
elessair 0:f269e3021894 96 * chance to clean up.
elessair 0:f269e3021894 97 *
elessair 0:f269e3021894 98 * @param[in] params
elessair 0:f269e3021894 99 * Information about the characterisitc being updated.
elessair 0:f269e3021894 100 */
elessair 0:f269e3021894 101 virtual void onDataWritten(const GattWriteCallbackParams *params) {
elessair 0:f269e3021894 102 if (params->handle == controlPoint.getValueHandle()) {
elessair 0:f269e3021894 103 /* At present, writing anything will do the trick - this needs to be improved. */
elessair 0:f269e3021894 104 if (handoverCallback) {
elessair 0:f269e3021894 105 handoverCallback();
elessair 0:f269e3021894 106 }
elessair 0:f269e3021894 107
elessair 0:f269e3021894 108 // Call bootloader_start implicitly trough a event handler call
elessair 0:f269e3021894 109 // it is a work around for bootloader_start not being public in sdk 8.1
elessair 0:f269e3021894 110 ble_dfu_t p_dfu;
elessair 0:f269e3021894 111 ble_dfu_evt_t p_evt;
elessair 0:f269e3021894 112
elessair 0:f269e3021894 113 p_dfu.conn_handle = params->connHandle;
elessair 0:f269e3021894 114 p_evt.ble_dfu_evt_type = BLE_DFU_START;
elessair 0:f269e3021894 115
elessair 0:f269e3021894 116 dfu_app_on_dfu_evt(&p_dfu, &p_evt);
elessair 0:f269e3021894 117 }
elessair 0:f269e3021894 118 }
elessair 0:f269e3021894 119
elessair 0:f269e3021894 120 protected:
elessair 0:f269e3021894 121 static const unsigned SIZEOF_CONTROL_BYTES = 2;
elessair 0:f269e3021894 122 static const unsigned SIZEOF_PACKET_BYTES = 20;
elessair 0:f269e3021894 123
elessair 0:f269e3021894 124 protected:
elessair 0:f269e3021894 125 BLE &ble;
elessair 0:f269e3021894 126
elessair 0:f269e3021894 127 /**< Writing to the control characteristic triggers the handover to DFU
elessair 0:f269e3021894 128 * bootloader. At present, writing anything will do the trick - this needs
elessair 0:f269e3021894 129 * to be improved. */
elessair 0:f269e3021894 130 WriteOnlyArrayGattCharacteristic<uint8_t, SIZEOF_CONTROL_BYTES> controlPoint;
elessair 0:f269e3021894 131
elessair 0:f269e3021894 132 /**< The packet characteristic in this service doesn't do anything meaningful;
elessair 0:f269e3021894 133 * it is only a placeholder to mimic the corresponding characteristic in the
elessair 0:f269e3021894 134 * actual DFU service implemented by the bootloader. Without this, some
elessair 0:f269e3021894 135 * FOTA clients might get confused, because service definitions change after
elessair 0:f269e3021894 136 * handing control over to the bootloader. */
elessair 0:f269e3021894 137 GattCharacteristic packet;
elessair 0:f269e3021894 138
elessair 0:f269e3021894 139 uint8_t controlBytes[SIZEOF_CONTROL_BYTES];
elessair 0:f269e3021894 140 uint8_t packetBytes[SIZEOF_PACKET_BYTES];
elessair 0:f269e3021894 141
elessair 0:f269e3021894 142 static ResetPrepare_t handoverCallback; /**< Application-specific handover callback. */
elessair 0:f269e3021894 143 };
elessair 0:f269e3021894 144
elessair 0:f269e3021894 145 #endif /* #ifndef __BLE_DFU_SERVICE_H__*/
elessair 0:f269e3021894 146 #endif /* #ifdef TARGET_NRF51822 */