aboutsummaryrefslogtreecommitdiffstats
path: root/arduino/libraries/Bluefruit52Lib/src/services
diff options
context:
space:
mode:
Diffstat (limited to 'arduino/libraries/Bluefruit52Lib/src/services')
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEBas.cpp66
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEBas.h60
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.cpp126
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.h73
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEDfu.cpp223
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEDfu.h55
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEDis.cpp101
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEDis.h72
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.cpp394
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.h90
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.cpp516
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.h583
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEMidi.cpp395
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEMidi.h99
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEUart.cpp325
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/BLEUart.h105
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/EddyStone.cpp180
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/src/services/EddyStone.h69
18 files changed, 3532 insertions, 0 deletions
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEBas.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEBas.cpp
new file mode 100755
index 0000000..2cfd172
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEBas.cpp
@@ -0,0 +1,66 @@
+/**************************************************************************/
+/*!
+ @file BLEBas.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+
+BLEBas::BLEBas(void) :
+ BLEService(UUID16_SVC_BATTERY), _battery(UUID16_CHR_BATTERY_LEVEL)
+{
+
+}
+
+err_t BLEBas::begin(void)
+{
+ // Invoke base class begin()
+ VERIFY_STATUS( BLEService::begin() );
+
+ _battery.setProperties(CHR_PROPS_READ | CHR_PROPS_NOTIFY); // could support notify
+ _battery.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
+ _battery.setFixedLen(1);
+ VERIFY_STATUS( _battery.begin() );
+
+ return ERROR_NONE;
+}
+
+bool BLEBas::write(uint8_t level)
+{
+ return _battery.write8(level) > 0;
+}
+
+bool BLEBas::notify(uint8_t level)
+{
+ return _battery.notify8(level);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEBas.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEBas.h
new file mode 100755
index 0000000..d091ce5
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEBas.h
@@ -0,0 +1,60 @@
+/**************************************************************************/
+/*!
+ @file BLEBas.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEBAS_H_
+#define BLEBAS_H_
+
+#include "bluefruit_common.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+class BLEBas : public BLEService
+{
+ protected:
+ BLECharacteristic _battery;
+
+ public:
+ BLEBas(void);
+
+ virtual err_t begin(void);
+
+ bool write (uint8_t level);
+ bool notify(uint8_t level);
+};
+
+
+
+#endif /* BLEBAS_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.cpp
new file mode 100755
index 0000000..21d3120
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.cpp
@@ -0,0 +1,126 @@
+/**************************************************************************/
+/*!
+ @file BLEBeacon.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+
+void BLEBeacon::_init(void)
+{
+ _manufacturer_id = UUID16_COMPANY_ID_APPLE; // default is Apple
+ _uuid128 = NULL;
+
+ _major_be = _minor_be = 0;
+ _rssi_at_1m = -54;
+}
+
+BLEBeacon::BLEBeacon(void)
+{
+ _init();
+}
+
+BLEBeacon::BLEBeacon(uint8_t const uuid128[16])
+{
+ _init();
+ _uuid128 = uuid128;
+}
+
+BLEBeacon::BLEBeacon(uint8_t const uuid128[16], uint16_t major, uint16_t minor, int8_t rssi)
+{
+ _init();
+ _uuid128 = uuid128;
+ _major_be = __swap16(major);
+ _minor_be = __swap16(minor);
+ _rssi_at_1m = rssi;
+}
+
+void BLEBeacon::setManufacturer(uint16_t manfacturer)
+{
+ _manufacturer_id = manfacturer;
+}
+
+void BLEBeacon::setUuid(uint8_t const uuid128[16])
+{
+ _uuid128 = uuid128;
+}
+
+void BLEBeacon::setMajorMinor(uint16_t major, uint16_t minor)
+{
+ _major_be = major;
+ _minor_be = minor;
+}
+
+void BLEBeacon::setRssiAt1m(int8_t rssi)
+{
+ _rssi_at_1m = rssi;
+}
+
+bool BLEBeacon::start(void)
+{
+ return start(Bluefruit.Advertising);
+}
+
+bool BLEBeacon::start(BLEAdvertising& adv)
+{
+ adv.clearData();
+
+ struct ATTR_PACKED
+ {
+ uint16_t manufacturer;
+
+ uint8_t beacon_type;
+ uint8_t beacon_len;
+
+ uint8_t uuid128[16];
+ uint16_t major;
+ uint16_t minor;
+ int8_t rssi_at_1m;
+ } beacon_data =
+ {
+ .manufacturer = _manufacturer_id,
+ .beacon_type = 0x02,
+ .beacon_len = sizeof(beacon_data) - 4, // len of uuid + major + minor + rssi
+ .uuid128 = { 0 },
+ .major = _major_be,
+ .minor = _minor_be,
+ .rssi_at_1m = _rssi_at_1m
+ };
+
+ VERIFY_STATIC(sizeof(beacon_data) == 25);
+
+ memcpy(beacon_data.uuid128, _uuid128, 16);
+
+ adv.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ return adv.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, &beacon_data, sizeof(beacon_data));
+}
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.h
new file mode 100755
index 0000000..d138813
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEBeacon.h
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/*!
+ @file BLEBeacon.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEBEACON_H_
+#define BLEBEACON_H_
+
+#include "bluefruit_common.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+class BLEAdvertising; // forward declare
+
+class BLEBeacon
+{
+ private:
+ uint16_t _manufacturer_id;
+ uint8_t const* _uuid128;
+ uint16_t _major_be; // Big Endian
+ uint16_t _minor_be; // Big Endian
+ int8_t _rssi_at_1m;
+
+ void _init(void);
+
+ public:
+ BLEBeacon(void);
+ BLEBeacon(uint8_t const uuid128[16]);
+ BLEBeacon(uint8_t const uuid128[16], uint16_t major, uint16_t minor, int8_t rssi);
+
+ void setManufacturer(uint16_t manfacturer);
+ void setUuid(uint8_t const uuid128[16]);
+ void setMajorMinor(uint16_t major, uint16_t minor);
+ void setRssiAt1m(int8_t rssi);
+
+ bool start(void);
+ bool start(BLEAdvertising& adv);
+};
+
+
+
+#endif /* BLEBEACON_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEDfu.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEDfu.cpp
new file mode 100755
index 0000000..3ff2516
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEDfu.cpp
@@ -0,0 +1,223 @@
+/**************************************************************************/
+/*!
+ @file BLEDfu.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+
+#define DFU_REV_APPMODE 0x0001
+
+/* DFU Serivce : 00001530-1212-EFDE-1523-785FEABCD123
+ * DFU Control : 00001531-1212-EFDE-1523-785FEABCD123
+ * DFU Packet : 00001532-1212-EFDE-1523-785FEABCD123
+ * DFU Revision: 00001534-1212-EFDE-1523-785FEABCD123
+ */
+
+const uint8_t UUID128_SVC_DFU_OTA[16] =
+{
+ 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
+ 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00
+};
+
+
+const uint8_t UUID128_CHR_DFU_CONTROL[16] =
+{
+ 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
+ 0xDE, 0xEF, 0x12, 0x12, 0x31, 0x15, 0x00, 0x00
+};
+
+const uint8_t UUID128_CHR_DFU_PACKET[16] =
+{
+ 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
+ 0xDE, 0xEF, 0x12, 0x12, 0x32, 0x15, 0x00, 0x00
+};
+
+const uint8_t UUID128_CHR_DFU_REVISON[16] =
+{
+ 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
+ 0xDE, 0xEF, 0x12, 0x12, 0x34, 0x15, 0x00, 0x00
+};
+
+extern "C" void bootloader_util_app_start(uint32_t start_addr);
+
+static uint16_t crc16(const uint8_t* data_p, uint8_t length)
+{
+ uint8_t x;
+ uint16_t crc = 0xFFFF;
+
+ while ( length-- )
+ {
+ x = crc >> 8 ^ *data_p++;
+ x ^= x >> 4;
+ crc = (crc << 8) ^ ((uint16_t) (x << 12)) ^ ((uint16_t) (x << 5)) ^ ((uint16_t) x);
+ }
+ return crc;
+}
+
+static void bledfu_control_wr_authorize_cb(BLECharacteristic& chr, ble_gatts_evt_write_t* request)
+{
+ if ( (request->handle == chr.handles().value_handle) &&
+ (request->op != BLE_GATTS_OP_PREP_WRITE_REQ) &&
+ (request->op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) &&
+ (request->op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL))
+ {
+ uint16_t conn_hdl = Bluefruit.connHandle();
+
+ ble_gatts_rw_authorize_reply_params_t reply = { .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE };
+
+ if ( !chr.notifyEnabled() )
+ {
+ reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
+ sd_ble_gatts_rw_authorize_reply(conn_hdl, &reply);
+ return;
+ }
+
+ reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
+ sd_ble_gatts_rw_authorize_reply(conn_hdl, &reply);
+
+ enum { START_DFU = 1 };
+ if ( request->data[0] == START_DFU )
+ {
+ // Peer data information so that bootloader could re-connect after reboot
+ typedef struct {
+ ble_gap_addr_t addr;
+ ble_gap_irk_t irk;
+ ble_gap_enc_key_t enc_key;
+ uint8_t sys_attr[8];
+ uint16_t crc16;
+ }peer_data_t;
+
+ VERIFY_STATIC(offsetof(peer_data_t, crc16) == 60);
+
+ /* Save Peer data
+ * Peer data address is defined in bootloader linker @0x20007F80
+ * - If bonded : save Security information
+ * - Otherwise : save Address for direct advertising
+ *
+ * TODO may force bonded only for security reason
+ */
+ peer_data_t* peer_data = (peer_data_t*) (0x20007F80UL);
+ varclr(peer_data);
+
+ // Get CCCD
+ uint16_t sysattr_len = sizeof(peer_data->sys_attr);
+ sd_ble_gatts_sys_attr_get(conn_hdl, peer_data->sys_attr, &sysattr_len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
+
+ // Get Bond Data or using Address if not bonded
+ peer_data->addr = Bluefruit.Gap.getPeerAddr(conn_hdl);
+
+ if ( Bluefruit.Gap.paired(conn_hdl) )
+ {
+ bond_keys_t bkeys;
+
+ if ( bond_load_keys( BLE_GAP_ROLE_PERIPH, Bluefruit.Gap._get_peer(conn_hdl)->ediv, &bkeys ) )
+ {
+ peer_data->addr = bkeys.peer_id.id_addr_info;
+ peer_data->irk = bkeys.peer_id.id_info;
+ peer_data->enc_key = bkeys.own_enc;
+ }
+ }
+
+ // Calculate crc
+ peer_data->crc16 = crc16((uint8_t*) peer_data, offsetof(peer_data_t, crc16));
+
+ // Initiate DFU Sequence and reboot into DFU OTA mode
+ Bluefruit.Advertising.restartOnDisconnect(false);
+ Bluefruit.disconnect();
+
+ // Set GPReset to DFU OTA
+ enum { DFU_OTA_MAGIC = 0xB1 };
+
+ sd_power_gpregret_clr(0, 0xFF);
+ VERIFY_STATUS( sd_power_gpregret_set(0, DFU_OTA_MAGIC), );
+ VERIFY_STATUS( sd_softdevice_disable(), );
+
+ // Disable all interrupts
+ #if defined(NRF52832_XXAA)
+ #define MAX_NUMBER_INTERRUPTS 39
+ #elif defined(NRF52840_XXAA)
+ #define MAX_NUMBER_INTERRUPTS 48
+ #endif
+
+ NVIC_ClearPendingIRQ(SD_EVT_IRQn);
+ for(int i=0; i < MAX_NUMBER_INTERRUPTS; i++)
+ {
+ NVIC_DisableIRQ( (IRQn_Type) i );
+ }
+
+ // Clear RTC1 timer to prevent Interrupt happens after changing vector table
+// NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
+// NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
+// NRF_RTC1->TASKS_STOP = 1;
+// NRF_RTC1->TASKS_CLEAR = 1;
+
+ VERIFY_STATUS( sd_softdevice_vector_table_base_set(NRF_UICR->NRFFW[0]), );
+
+ __set_CONTROL(0); // switch to MSP, required if using FreeRTOS
+ bootloader_util_app_start(NRF_UICR->NRFFW[0]);
+ }
+ }
+}
+
+BLEDfu::BLEDfu(void) : BLEService(UUID128_SVC_DFU_OTA), _chr_control(UUID128_CHR_DFU_CONTROL)
+{
+
+}
+
+err_t BLEDfu::begin(void)
+{
+ // Invoke base class begin()
+ VERIFY_STATUS( BLEService::begin() );
+
+ // No need to keep packet & revision characteristics
+ BLECharacteristic chr_packet(UUID128_CHR_DFU_PACKET);
+ chr_packet.setTempMemory();
+ chr_packet.setProperties(CHR_PROPS_WRITE_WO_RESP);
+ chr_packet.setMaxLen(20);
+ VERIFY_STATUS( chr_packet.begin() );
+
+ _chr_control.setProperties(CHR_PROPS_WRITE | CHR_PROPS_NOTIFY);
+ _chr_control.setMaxLen(23);
+ _chr_control.setWriteAuthorizeCallback(bledfu_control_wr_authorize_cb);
+ VERIFY_STATUS( _chr_control.begin() );
+
+ BLECharacteristic chr_revision(UUID128_CHR_DFU_REVISON);
+ chr_revision.setTempMemory();
+ chr_revision.setProperties(CHR_PROPS_READ);
+ chr_revision.setFixedLen(2);
+ VERIFY_STATUS( chr_revision.begin());
+ chr_revision.write16(DFU_REV_APPMODE);
+
+ return ERROR_NONE;
+}
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEDfu.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEDfu.h
new file mode 100755
index 0000000..224a338
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEDfu.h
@@ -0,0 +1,55 @@
+/**************************************************************************/
+/*!
+ @file BLEDfu.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEDFU_H_
+#define BLEDFU_H_
+
+#include "bluefruit_common.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+class BLEDfu : public BLEService
+{
+ protected:
+ BLECharacteristic _chr_control;
+
+ public:
+ BLEDfu(void);
+
+ virtual err_t begin(void);
+};
+
+#endif /* BLEDFU_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEDis.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEDis.cpp
new file mode 100755
index 0000000..c1a08e6
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEDis.cpp
@@ -0,0 +1,101 @@
+/**************************************************************************/
+/*!
+ @file BLEDis.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+#include "utility/utilities.h"
+
+BLEDis::BLEDis(void)
+ : BLEService(UUID16_SVC_DEVICE_INFORMATION)
+{
+#ifdef NRF52840_XXAA
+ _model = "Bluefruit Feather nRF52840";
+#else
+ _model = "Bluefruit Feather nRF52832";
+#endif
+
+ _serial = NULL;
+ _firmware_rev = NULL;
+ _hardware_rev = NULL;
+ _software_rev = ARDUINO_BSP_VERSION;
+ _manufacturer = "Adafruit Industries";
+}
+
+void BLEDis::setModel(const char* model)
+{
+ _model = model;
+}
+
+void BLEDis::setHardwareRev(const char* hw_rev)
+{
+ _hardware_rev = hw_rev;
+}
+
+void BLEDis::setSoftwareRev(const char* sw_rev)
+{
+ _software_rev = sw_rev;
+}
+
+void BLEDis::setManufacturer(const char* manufacturer)
+{
+ _manufacturer = manufacturer;
+}
+
+err_t BLEDis::begin(void)
+{
+ // Invoke base class begin()
+ VERIFY_STATUS( BLEService::begin() );
+
+ _serial = getMcuUniqueID();
+ _firmware_rev = getBootloaderVersion();
+
+ for(uint8_t i=0; i<arrcount(_strarr); i++)
+ {
+ if ( _strarr[i] != NULL )
+ {
+ BLECharacteristic chars(UUID16_CHR_MODEL_NUMBER_STRING+i);
+ chars.setTempMemory();
+
+ chars.setProperties(CHR_PROPS_READ);
+ chars.setFixedLen(strlen(_strarr[i]));
+
+ VERIFY_STATUS( chars.begin() );
+ chars.write(_strarr[i]);
+ }
+ }
+
+ return ERROR_NONE;
+}
+
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEDis.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEDis.h
new file mode 100755
index 0000000..bc5e710
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEDis.h
@@ -0,0 +1,72 @@
+/**************************************************************************/
+/*!
+ @file BLEDis.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEDIS_H_
+#define BLEDIS_H_
+
+#include "bluefruit_common.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+class BLEDis : public BLEService
+{
+ protected:
+ union {
+ struct {
+ const char * _model;
+ const char * _serial;
+ const char * _firmware_rev;
+ const char * _hardware_rev;
+ const char * _software_rev;
+ const char * _manufacturer;
+ };
+
+ const char * _strarr[6];
+ };
+
+ public:
+ BLEDis(void);
+
+ void setModel(const char* model);
+ void setHardwareRev(const char* hw_rev);
+ void setSoftwareRev(const char* sw_rev);
+ void setManufacturer(const char* manufacturer);
+
+ virtual err_t begin(void);
+};
+
+
+#endif /* BLEDIS_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.cpp
new file mode 100755
index 0000000..3657f3a
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.cpp
@@ -0,0 +1,394 @@
+/**************************************************************************/
+/*!
+ @file BLEHidAdafruit.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+
+enum
+{
+ REPORT_ID_KEYBOARD = 1,
+ REPORT_ID_CONSUMER_CONTROL,
+ REPORT_ID_MOUSE,
+ REPORT_ID_GAMEPAD
+};
+
+uint8_t const hid_report_descriptor[] =
+{
+ //------------- Keyboard Report -------------//
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ),
+ HID_USAGE ( HID_USAGE_DESKTOP_KEYBOARD ),
+ HID_COLLECTION ( HID_COLLECTION_APPLICATION ),
+ HID_REPORT_ID ( REPORT_ID_KEYBOARD ),
+ HID_USAGE_PAGE( HID_USAGE_PAGE_KEYBOARD ),
+ // 8 bits Modifier Keys (Shfit, Control, Alt)
+ HID_USAGE_MIN ( 224 ),
+ HID_USAGE_MAX ( 231 ),
+ HID_LOGICAL_MIN ( 0 ),
+ HID_LOGICAL_MAX ( 1 ),
+
+ HID_REPORT_COUNT ( 8 ),
+ HID_REPORT_SIZE ( 1 ),
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),
+
+ // 8 bit reserved
+ HID_REPORT_COUNT ( 1 ),
+ HID_REPORT_SIZE ( 8 ),
+ HID_INPUT ( HID_CONSTANT ),
+
+ // 6-byte Keycodes
+ HID_USAGE_PAGE (HID_USAGE_PAGE_KEYBOARD),
+ HID_USAGE_MIN ( 0 ),
+ HID_USAGE_MAX ( 255 ),
+ HID_LOGICAL_MIN ( 0 ),
+ HID_LOGICAL_MAX ( 255 ),
+
+ HID_REPORT_COUNT ( 6 ),
+ HID_REPORT_SIZE ( 8 ),
+ HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ),
+
+ // LED Indicator Kana | Compose | Scroll Lock | CapsLock | NumLock
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_LED ),
+ /* 5-bit Led report */
+ HID_USAGE_MIN ( 1 ),
+ HID_USAGE_MAX ( 5 ),
+ HID_REPORT_COUNT ( 5 ),
+ HID_REPORT_SIZE ( 1 ),
+ HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),
+ /* led padding */
+ HID_REPORT_COUNT ( 1 ),
+ HID_REPORT_SIZE ( 3 ),
+ HID_OUTPUT ( HID_CONSTANT ),
+ HID_COLLECTION_END,
+
+ //------------- Consumer Control Report -------------//
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ),
+ HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ),
+ HID_COLLECTION ( HID_COLLECTION_APPLICATION ),
+ HID_REPORT_ID( REPORT_ID_CONSUMER_CONTROL ),
+ HID_LOGICAL_MIN ( 0x00 ),
+ HID_LOGICAL_MAX_N( 0x03FF, 2 ),
+ HID_USAGE_MIN ( 0x00 ),
+ HID_USAGE_MAX_N ( 0x03FF, 2 ),
+ HID_REPORT_COUNT ( 1 ),
+ HID_REPORT_SIZE ( 16 ),
+ HID_INPUT ( HID_DATA | HID_ARRAY | HID_ABSOLUTE ),
+ HID_COLLECTION_END,
+
+ //------------- Mouse Report: buttons + dx + dy + scroll + pan -------------//
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ),
+ HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ),
+ HID_COLLECTION ( HID_COLLECTION_APPLICATION ),
+ HID_REPORT_ID( REPORT_ID_MOUSE ),
+ HID_USAGE (HID_USAGE_DESKTOP_POINTER ),
+ HID_COLLECTION ( HID_COLLECTION_PHYSICAL ),
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ),
+ HID_USAGE_MIN ( 1 ),
+ HID_USAGE_MAX ( 5 ),
+ HID_LOGICAL_MIN ( 0 ),
+ HID_LOGICAL_MAX ( 1 ),
+
+ HID_REPORT_COUNT ( 5 ), /* Forward, Backward, Middle, Right, Left */
+ HID_REPORT_SIZE ( 1 ),
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),
+
+ HID_REPORT_COUNT ( 1 ),
+ HID_REPORT_SIZE ( 3 ),
+ HID_INPUT ( HID_CONSTANT ), /* 5 bit padding followed 3 bit buttons */
+
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ),
+ HID_USAGE ( HID_USAGE_DESKTOP_X ),
+ HID_USAGE ( HID_USAGE_DESKTOP_Y ),
+ HID_LOGICAL_MIN ( 0x81 ), /* -127 */
+ HID_LOGICAL_MAX ( 0x7f ), /* 127 */
+
+ HID_REPORT_COUNT ( 2 ), /* X, Y position */
+ HID_REPORT_SIZE ( 8 ),
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), /* relative values */
+
+ HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ), /* mouse scroll */
+ HID_LOGICAL_MIN ( 0x81 ), /* -127 */
+ HID_LOGICAL_MAX ( 0x7f ), /* 127 */
+ HID_REPORT_COUNT( 1 ),
+ HID_REPORT_SIZE ( 8 ), /* 8-bit value */
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), /* relative values */
+
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ),
+ HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), /* Horizontal wheel scroll */
+ HID_LOGICAL_MIN ( 0x81 ), /* -127 */
+ HID_LOGICAL_MAX ( 0x7f ), /* 127 */
+ HID_REPORT_COUNT( 1 ),
+ HID_REPORT_SIZE ( 8 ), /* 8-bit value */
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), /* relative values */
+ HID_COLLECTION_END,
+ HID_COLLECTION_END,
+
+#if 0
+ //------------- Gamepad Report -------------//
+ /* Byte 0: 4 pad | 2 Y-axis | 2 X-axis
+ * Byte 1: Button7-Button0
+ */
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ),
+ HID_USAGE ( HID_USAGE_DESKTOP_GAMEPAD ),
+ HID_COLLECTION ( HID_COLLECTION_APPLICATION ),
+ HID_REPORT_ID ( REPORT_ID_GAMEPAD ),
+ HID_USAGE (HID_USAGE_DESKTOP_POINTER ),
+ HID_COLLECTION ( HID_COLLECTION_PHYSICAL ),
+ // X,Y joystick
+ HID_USAGE ( HID_USAGE_DESKTOP_X ),
+ HID_USAGE ( HID_USAGE_DESKTOP_Y ),
+ HID_LOGICAL_MIN ( 0xFF ), /* -1 */
+ HID_LOGICAL_MAX ( 0x01 ), /* 1 */
+ HID_REPORT_COUNT( 2 ), /* X, Y position */
+ HID_REPORT_SIZE ( 2 ), /* 2-bit value */
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), /* input values */
+ HID_COLLECTION_END,
+
+ /* X,Y padding */
+ HID_REPORT_COUNT ( 4 ),
+ HID_REPORT_SIZE ( 1 ),
+ HID_INPUT ( HID_CONSTANT | HID_VARIABLE | HID_ABSOLUTE),
+
+ // Buttons
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ),
+ HID_USAGE_MIN ( 1 ),
+ HID_USAGE_MAX ( 8 ),
+ HID_LOGICAL_MIN ( 0 ),
+ HID_LOGICAL_MAX ( 1 ),
+ HID_REPORT_COUNT ( 8 ), // Keyboard
+ HID_REPORT_SIZE ( 1 ),
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE),
+ HID_COLLECTION_END
+#endif
+};
+
+BLEHidAdafruit::BLEHidAdafruit(void)
+ : BLEHidGeneric(3, 1, 0)
+{
+ _mse_buttons = 0;
+ _kbd_led_cb = NULL;
+}
+
+err_t BLEHidAdafruit::begin(void)
+{
+ uint16_t input_len [] = { sizeof(hid_keyboard_report_t), sizeof(hid_consumer_control_report_t), sizeof(hid_mouse_report_t) };
+ uint16_t output_len[] = { 1 };
+
+ setReportLen(input_len, output_len, NULL);
+ enableKeyboard(true);
+ enableMouse(true);
+ setReportMap(hid_report_descriptor, sizeof(hid_report_descriptor));
+
+ VERIFY_STATUS( BLEHidGeneric::begin() );
+
+ // Attempt to change the connection interval to 11.25-15 ms when starting HID
+ Bluefruit.setConnInterval(9, 12);
+
+ return ERROR_NONE;
+}
+
+/*------------------------------------------------------------------*/
+/* Keyboard
+ *------------------------------------------------------------------*/
+
+void blehid_ada_keyboard_output_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset)
+{
+ LOG_LV2("HID", "Keyboard LED : 0x%02X", data[0]);
+ VERIFY(len == 1, );
+
+ BLEHidAdafruit& svc = (BLEHidAdafruit&) chr.parentService();
+ if ( svc._kbd_led_cb ) svc._kbd_led_cb(data[0]);
+}
+
+void BLEHidAdafruit::setKeyboardLedCallback(kbd_led_cb_t fp)
+{
+ _kbd_led_cb = fp;
+
+ // Report mode
+ this->setOutputReportCallback(REPORT_ID_KEYBOARD, fp ? blehid_ada_keyboard_output_cb : NULL);
+
+ // Boot mode
+ _chr_boot_keyboard_output->setWriteCallback(fp ? blehid_ada_keyboard_output_cb : NULL);
+}
+
+bool BLEHidAdafruit::keyboardReport(hid_keyboard_report_t* report)
+{
+ if ( isBootMode() )
+ {
+ return bootKeyboardReport(report, sizeof(hid_keyboard_report_t));
+ }else
+ {
+ return inputReport( REPORT_ID_KEYBOARD, report, sizeof(hid_keyboard_report_t));
+ }
+}
+
+bool BLEHidAdafruit::keyboardReport(uint8_t modifier, uint8_t keycode[6])
+{
+ hid_keyboard_report_t report =
+ {
+ .modifier = modifier,
+ };
+ memcpy(report.keycode, keycode, 6);
+
+ return keyboardReport(&report);
+}
+
+bool BLEHidAdafruit::keyboardReport(uint8_t modifier, uint8_t keycode0, uint8_t keycode1, uint8_t keycode2, uint8_t keycode3, uint8_t keycode4, uint8_t keycode5)
+{
+ hid_keyboard_report_t report =
+ {
+ .modifier = modifier,
+ .reserved = 0,
+ .keycode = { keycode0, keycode1, keycode2, keycode3, keycode4, keycode5 }
+ };
+
+ return keyboardReport(&report);
+}
+
+bool BLEHidAdafruit::keyPress(char ch)
+{
+ hid_keyboard_report_t report;
+ varclr(&report);
+
+ report.modifier = ( HID_ASCII_TO_KEYCODE[(uint8_t)ch].shift ) ? KEYBOARD_MODIFIER_LEFTSHIFT : 0;
+ report.keycode[0] = HID_ASCII_TO_KEYCODE[(uint8_t)ch].keycode;
+
+ return keyboardReport(&report);
+}
+
+bool BLEHidAdafruit::keyRelease(void)
+{
+ hid_keyboard_report_t report;
+ varclr(&report);
+
+ return keyboardReport(&report);
+}
+
+bool BLEHidAdafruit::keySequence(const char* str, int interal)
+{
+ // Send each key in sequence
+ char ch;
+ while( (ch = *str++) != 0 )
+ {
+ char lookahead = *str;
+
+ keyPress(ch);
+ delay(interal);
+
+ /* Only need to empty report if the next character is NULL or the same with
+ * the current one, else no need to send */
+ if ( lookahead == ch || lookahead == 0 )
+ {
+ keyRelease();
+ delay(interal);
+ }
+ }
+
+ return true;
+}
+
+/*------------------------------------------------------------------*/
+/* Consumer Media Key
+ *------------------------------------------------------------------*/
+bool BLEHidAdafruit::consumerReport(uint16_t usage_code)
+{
+ return inputReport( REPORT_ID_CONSUMER_CONTROL, &usage_code, sizeof(usage_code));
+}
+
+bool BLEHidAdafruit::consumerKeyPress(uint16_t usage_code)
+{
+ return consumerReport(usage_code);
+}
+
+bool BLEHidAdafruit::consumerKeyRelease(void)
+{
+ uint16_t usage = 0;
+ return consumerReport(usage);
+}
+
+/*------------------------------------------------------------------*/
+/* Mouse
+ *------------------------------------------------------------------*/
+bool BLEHidAdafruit::mouseReport(hid_mouse_report_t* report)
+{
+ if ( isBootMode() )
+ {
+ return bootMouseReport(report, sizeof(hid_mouse_report_t));
+ }else
+ {
+ return inputReport( REPORT_ID_MOUSE, report, sizeof(hid_mouse_report_t));
+ }
+}
+
+bool BLEHidAdafruit::mouseReport(uint8_t buttons, int8_t x, int8_t y, int8_t wheel, int8_t pan)
+{
+ hid_mouse_report_t report =
+ {
+ .buttons = buttons,
+ .x = x,
+ .y = y,
+ .wheel = wheel,
+ .pan = pan
+ };
+
+ _mse_buttons = buttons;
+
+ return mouseReport(&report);
+}
+
+bool BLEHidAdafruit::mouseButtonPress(uint8_t buttons)
+{
+ _mse_buttons = buttons;
+ return mouseReport(buttons, 0, 0, 0, 0);
+}
+
+bool BLEHidAdafruit::mouseButtonRelease(void)
+{
+ return mouseReport(0, 0, 0, 0, 0);
+}
+
+bool BLEHidAdafruit::mouseMove(int8_t x, int8_t y)
+{
+ return mouseReport(_mse_buttons, x, y, 0, 0);
+}
+
+bool BLEHidAdafruit::mouseScroll(int8_t scroll)
+{
+ return mouseReport(_mse_buttons, 0, 0, scroll, 0);
+}
+
+bool BLEHidAdafruit::mousePan(int8_t pan)
+{
+ return mouseReport(_mse_buttons, 0, 0, 0, pan);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.h
new file mode 100755
index 0000000..6563705
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidAdafruit.h
@@ -0,0 +1,90 @@
+/**************************************************************************/
+/*!
+ @file BLEHidAdafruit.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEHIDADAFRUIT_H_
+#define BLEHIDADAFRUIT_H_
+
+#include "bluefruit_common.h"
+
+#include "BLECharacteristic.h"
+#include "BLEHidGeneric.h"
+#include "BLEService.h"
+
+
+class BLEHidAdafruit : public BLEHidGeneric
+{
+ public:
+ /*--------- Callback Signatures ----------*/
+ typedef void (*kbd_led_cb_t) (uint8_t leds_bitmap);
+
+ BLEHidAdafruit(void);
+
+ virtual err_t begin(void);
+
+ // Keyboard
+ bool keyboardReport(hid_keyboard_report_t* report);
+ bool keyboardReport(uint8_t modifier, uint8_t keycode[6]);
+ bool keyboardReport(uint8_t modifier, uint8_t keycode0, uint8_t keycode1=0, uint8_t keycode2=0, uint8_t keycode3=0, uint8_t keycode4=0, uint8_t keycode5=0);
+
+ void setKeyboardLedCallback(kbd_led_cb_t fp);
+
+ bool keyPress(char ch);
+ bool keyRelease(void);
+ bool keySequence(const char* str, int interal=5);
+
+ // Consumer Media Keys
+ bool consumerReport(uint16_t usage_code);
+ bool consumerKeyPress(uint16_t usage_code);
+ bool consumerKeyRelease(void);
+
+ // Mouse
+ bool mouseReport(hid_mouse_report_t* report);
+ bool mouseReport(uint8_t buttons, int8_t x, int8_t y, int8_t wheel=0, int8_t pan=0);
+
+ bool mouseButtonPress(uint8_t buttons);
+ bool mouseButtonRelease(void);
+
+ bool mouseMove(int8_t x, int8_t y);
+ bool mouseScroll(int8_t scroll);
+ bool mousePan(int8_t pan);
+
+ protected:
+ uint8_t _mse_buttons;
+ kbd_led_cb_t _kbd_led_cb;
+
+ friend void blehid_ada_keyboard_output_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset);
+};
+
+#endif /* BLEHIDADAFRUIT_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.cpp
new file mode 100755
index 0000000..a95ddc2
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.cpp
@@ -0,0 +1,516 @@
+/**************************************************************************/
+/*!
+ @file BLEHidGeneric.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+
+enum {
+ REPORT_TYPE_INPUT = 1,
+ REPORT_TYPE_OUTPUT,
+ REPORT_TYPE_FEATURE
+};
+
+BLEHidGeneric::BLEHidGeneric(uint8_t num_input, uint8_t num_output, uint8_t num_feature)
+ : BLEService(UUID16_SVC_HUMAN_INTERFACE_DEVICE), _chr_control(UUID16_CHR_HID_CONTROL_POINT)
+{
+ _has_keyboard = _has_mouse = false;
+ _protocol_mode = HID_PROTOCOL_MODE_REPORT;
+
+ _report_map = NULL;
+ _report_map_len = 0;
+
+ _input_len = _output_len = _feature_len = NULL;
+
+ _num_input = num_input;
+ _num_output = num_output;
+ _num_feature = num_feature;
+
+ // HID Information
+ // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.hid_information.xml
+ // bcd 1.1, country = 0, flag = normal connect
+ _hid_info[0] = 0x01;
+ _hid_info[1] = 0x01;
+ _hid_info[2] = 0x00;
+ _hid_info[3] = bit(1);
+
+ _chr_protocol = NULL;
+ _chr_inputs = _chr_outputs = _chr_features = NULL;
+ _chr_boot_keyboard_input = _chr_boot_keyboard_output = _chr_boot_mouse_input = NULL;
+
+ if ( _num_input )
+ {
+ _chr_inputs = new BLECharacteristic[_num_input];
+ }
+
+ if ( _num_output )
+ {
+ _chr_outputs = new BLECharacteristic[_num_output];
+ }
+
+ if ( _num_feature )
+ {
+ _chr_features = new BLECharacteristic[_num_feature];
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* CONFIG
+ *------------------------------------------------------------------*/
+void BLEHidGeneric::enableKeyboard(bool enable)
+{
+ _has_keyboard = enable;
+}
+
+void BLEHidGeneric::enableMouse(bool enable)
+{
+ _has_mouse = enable;
+}
+
+void BLEHidGeneric::setHidInfo(uint16_t bcd, uint8_t country, uint8_t flags)
+{
+ memcpy(_hid_info, &bcd, 2);
+ _hid_info[2] = country;
+ _hid_info[3] = flags;
+}
+
+void BLEHidGeneric::setReportMap(const uint8_t* report_map, size_t len)
+{
+ _report_map = report_map;
+ _report_map_len = len;
+}
+
+void BLEHidGeneric::setReportLen(uint16_t input_len[], uint16_t output_len[], uint16_t feature_len[])
+{
+ _input_len = input_len;
+ _output_len = output_len;
+ _feature_len = feature_len;
+}
+
+void BLEHidGeneric::setOutputReportCallback(uint8_t reportID, BLECharacteristic::write_cb_t fp)
+{
+ // index is ID-1
+ uint8_t const idx = ( reportID ? (reportID-1) : 0 );
+
+ // report mode
+ if ( idx < _num_output ) _chr_outputs[idx].setWriteCallback(fp);
+}
+
+/*------------------------------------------------------------------*/
+/* Callbacks
+ *------------------------------------------------------------------*/
+void blehid_generic_protocol_mode_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset)
+{
+ BLEHidGeneric& svc = (BLEHidGeneric&) chr.parentService();
+ svc._protocol_mode = *data;
+
+ LOG_LV2("HID", "Protocol Mode : %d (0 Boot, 1 Report)", *data);
+}
+
+/*------------------------------------------------------------------*/
+/* Begin
+ *------------------------------------------------------------------*/
+err_t BLEHidGeneric::begin(void)
+{
+ VERIFY ( (_report_map != NULL) && _report_map_len, NRF_ERROR_INVALID_PARAM);
+
+ // Invoke base class begin()
+ VERIFY_STATUS( BLEService::begin() );
+
+ // Protocol Mode
+ if ( _has_keyboard || _has_mouse )
+ {
+ _chr_protocol = new BLECharacteristic(UUID16_CHR_PROTOCOL_MODE);
+ VERIFY(_chr_protocol, NRF_ERROR_NO_MEM);
+
+ _chr_protocol->setProperties(CHR_PROPS_READ | CHR_PROPS_WRITE_WO_RESP);
+ _chr_protocol->setFixedLen(1);
+ _chr_protocol->setWriteCallback(blehid_generic_protocol_mode_cb);
+ VERIFY_STATUS( _chr_protocol->begin() );
+ _chr_protocol->write8(_protocol_mode);
+ }
+
+ // Input reports
+ for(uint8_t i=0; i<_num_input; i++)
+ {
+ _chr_inputs[i].setUuid(UUID16_CHR_REPORT);
+ _chr_inputs[i].setProperties(CHR_PROPS_READ | CHR_PROPS_NOTIFY);
+ _chr_inputs[i].setPermission(SECMODE_ENC_NO_MITM, SECMODE_NO_ACCESS);
+ _chr_inputs[i].setReportRefDescriptor(i+1, REPORT_TYPE_INPUT);
+
+ // Input report len is configured, else variable len up to 255
+ if ( _input_len ) _chr_inputs[i].setFixedLen( _input_len[i] );
+
+ VERIFY_STATUS( _chr_inputs[i].begin() );
+ }
+
+ // Output reports
+ for(uint8_t i=0; i<_num_output; i++)
+ {
+ _chr_outputs[i].setUuid(UUID16_CHR_REPORT);
+ _chr_outputs[i].setProperties(CHR_PROPS_READ | CHR_PROPS_WRITE | CHR_PROPS_WRITE_WO_RESP);
+ _chr_outputs[i].setPermission(SECMODE_ENC_NO_MITM, SECMODE_ENC_NO_MITM);
+ _chr_outputs[i].setReportRefDescriptor(i+1, REPORT_TYPE_OUTPUT);
+
+ // Input report len is configured, else variable len up to 255
+ if ( _output_len ) _chr_outputs[i].setFixedLen( _output_len[i] );
+
+ VERIFY_STATUS( _chr_outputs[i].begin() );
+
+ _chr_outputs[i].write8(0);
+ }
+
+ // Report Map (HID Report Descriptor)
+ BLECharacteristic report_map(UUID16_CHR_REPORT_MAP);
+ report_map.setTempMemory();
+ report_map.setProperties(CHR_PROPS_READ);
+ report_map.setPermission(SECMODE_ENC_NO_MITM, SECMODE_NO_ACCESS);
+ report_map.setFixedLen(_report_map_len);
+ VERIFY_STATUS( report_map.begin() );
+ report_map.write(_report_map, _report_map_len);
+
+ // Boot Keyboard Input & Output Report
+ if ( _has_keyboard )
+ {
+ _chr_boot_keyboard_input = new BLECharacteristic(UUID16_CHR_BOOT_KEYBOARD_INPUT_REPORT);
+ _chr_boot_keyboard_input->setProperties(CHR_PROPS_READ | CHR_PROPS_NOTIFY);
+ _chr_boot_keyboard_input->setFixedLen(8); // boot keyboard is 8 bytes
+ _chr_boot_keyboard_input->setPermission(SECMODE_ENC_NO_MITM, SECMODE_NO_ACCESS);
+ VERIFY_STATUS(_chr_boot_keyboard_input->begin());
+
+ _chr_boot_keyboard_output = new BLECharacteristic(UUID16_CHR_BOOT_KEYBOARD_OUTPUT_REPORT);
+ _chr_boot_keyboard_output->setProperties(CHR_PROPS_READ | CHR_PROPS_WRITE | CHR_PROPS_WRITE_WO_RESP);
+ _chr_boot_keyboard_output->setFixedLen(1); // boot keyboard is 1 byte
+ _chr_boot_keyboard_output->setPermission(SECMODE_ENC_NO_MITM, SECMODE_ENC_NO_MITM);
+ VERIFY_STATUS(_chr_boot_keyboard_output->begin());
+ _chr_boot_keyboard_output->write8(0);
+ }
+
+ // Boot Mouse Input Report
+ if ( _has_mouse )
+ {
+ _chr_boot_mouse_input = new BLECharacteristic(UUID16_CHR_BOOT_MOUSE_INPUT_REPORT);
+ _chr_boot_mouse_input->setProperties(CHR_PROPS_READ | CHR_PROPS_NOTIFY);
+ _chr_boot_mouse_input->setFixedLen(sizeof(hid_mouse_report_t));
+ _chr_boot_mouse_input->setPermission(SECMODE_ENC_NO_MITM, SECMODE_NO_ACCESS);
+ VERIFY_STATUS(_chr_boot_mouse_input->begin());
+ }
+
+ // HID Info
+ BLECharacteristic hid_info(UUID16_CHR_HID_INFORMATION);
+ hid_info.setTempMemory();
+ hid_info.setProperties(CHR_PROPS_READ);
+ hid_info.setPermission(SECMODE_ENC_NO_MITM, SECMODE_NO_ACCESS);
+ hid_info.setFixedLen(sizeof(_hid_info));
+ VERIFY_STATUS( hid_info.begin() );
+ hid_info.write(_hid_info, sizeof(_hid_info));
+
+ // HID Control Point
+ _chr_control.setProperties(CHR_PROPS_WRITE_WO_RESP);
+ _chr_control.setPermission(SECMODE_NO_ACCESS, SECMODE_ENC_NO_MITM);
+ _chr_control.setFixedLen(1);
+ VERIFY_STATUS( _chr_control.begin() );
+ _chr_control.write8(0);
+
+ return ERROR_NONE;
+}
+
+/*------------------------------------------------------------------*/
+/* Input Report
+ *------------------------------------------------------------------*/
+bool BLEHidGeneric::inputReport(uint8_t reportID, void const* data, int len)
+{
+ // index is ID-1
+ uint8_t const idx = ( reportID ? (reportID-1) : 0 );
+
+ return _chr_inputs[idx].notify( (uint8_t const*) data, len);
+}
+
+bool BLEHidGeneric::bootKeyboardReport(void const* data, int len)
+{
+ return _chr_boot_keyboard_input->notify(data, len);
+}
+
+bool BLEHidGeneric::bootMouseReport(void const* data, int len)
+{
+ return _chr_boot_mouse_input->notify(data, len);
+}
+
+/*------------------------------------------------------------------*/
+/* Ascii to Keycode
+ *------------------------------------------------------------------*/
+const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128] =
+{
+ {0, 0 }, // 0x00 Null
+ {0, 0 }, // 0x01
+ {0, 0 }, // 0x02
+ {0, 0 }, // 0x03
+ {0, 0 }, // 0x04
+ {0, 0 }, // 0x05
+ {0, 0 }, // 0x06
+ {0, 0 }, // 0x07
+ {0, HID_KEY_BACKSPACE }, // 0x08 Backspace
+ {0, HID_KEY_TAB }, // 0x09 Horizontal Tab
+ {0, HID_KEY_RETURN }, // 0x0A Line Feed
+ {0, 0 }, // 0x0B
+ {0, 0 }, // 0x0C
+ {0, HID_KEY_RETURN }, // 0x0D Carriage return
+ {0, 0 }, // 0x0E
+ {0, 0 }, // 0x0F
+ {0, 0 }, // 0x10
+ {0, 0 }, // 0x11
+ {0, 0 }, // 0x12
+ {0, 0 }, // 0x13
+ {0, 0 }, // 0x14
+ {0, 0 }, // 0x15
+ {0, 0 }, // 0x16
+ {0, 0 }, // 0x17
+ {0, 0 }, // 0x18
+ {0, 0 }, // 0x19
+ {0, 0 }, // 0x1A
+ {0, HID_KEY_ESCAPE }, // 0x1B Escape
+ {0, 0 }, // 0x1C
+ {0, 0 }, // 0x1D
+ {0, 0 }, // 0x1E
+ {0, 0 }, // 0x1F
+
+ {0, HID_KEY_SPACE }, // 0x20
+ {1, HID_KEY_1 }, // 0x21 !
+ {1, HID_KEY_APOSTROPHE }, // 0x22 "
+ {1, HID_KEY_3 }, // 0x23 #
+ {1, HID_KEY_4 }, // 0x24 $
+ {1, HID_KEY_5 }, // 0x25 %
+ {1, HID_KEY_7 }, // 0x26 &
+ {0, HID_KEY_APOSTROPHE }, // 0x27 '
+ {1, HID_KEY_9 }, // 0x28 (
+ {1, HID_KEY_0 }, // 0x29 )
+ {1, HID_KEY_8 }, // 0x2A *
+ {1, HID_KEY_EQUAL }, // 0x2B +
+ {0, HID_KEY_COMMA }, // 0x2C ,
+ {0, HID_KEY_MINUS }, // 0x2D -
+ {0, HID_KEY_PERIOD }, // 0x2E .
+ {0, HID_KEY_SLASH }, // 0x2F /
+ {0, HID_KEY_0 }, // 0x30 0
+ {0, HID_KEY_1 }, // 0x31 1
+ {0, HID_KEY_2 }, // 0x32 2
+ {0, HID_KEY_3 }, // 0x33 3
+ {0, HID_KEY_4 }, // 0x34 4
+ {0, HID_KEY_5 }, // 0x35 5
+ {0, HID_KEY_6 }, // 0x36 6
+ {0, HID_KEY_7 }, // 0x37 7
+ {0, HID_KEY_8 }, // 0x38 8
+ {0, HID_KEY_9 }, // 0x39 9
+ {1, HID_KEY_SEMICOLON }, // 0x3A :
+ {0, HID_KEY_SEMICOLON }, // 0x3B ;
+ {1, HID_KEY_COMMA }, // 0x3C <
+ {0, HID_KEY_EQUAL }, // 0x3D =
+ {1, HID_KEY_PERIOD }, // 0x3E >
+ {1, HID_KEY_SLASH }, // 0x3F ?
+
+ {1, HID_KEY_2 }, // 0x40 @
+ {1, HID_KEY_A }, // 0x41 A
+ {1, HID_KEY_B }, // 0x42 B
+ {1, HID_KEY_C }, // 0x43 C
+ {1, HID_KEY_D }, // 0x44 D
+ {1, HID_KEY_E }, // 0x45 E
+ {1, HID_KEY_F }, // 0x46 F
+ {1, HID_KEY_G }, // 0x47 G
+ {1, HID_KEY_H }, // 0x48 H
+ {1, HID_KEY_I }, // 0x49 I
+ {1, HID_KEY_J }, // 0x4A J
+ {1, HID_KEY_K }, // 0x4B K
+ {1, HID_KEY_L }, // 0x4C L
+ {1, HID_KEY_M }, // 0x4D M
+ {1, HID_KEY_N }, // 0x4E N
+ {1, HID_KEY_O }, // 0x4F O
+ {1, HID_KEY_P }, // 0x50 P
+ {1, HID_KEY_Q }, // 0x51 Q
+ {1, HID_KEY_R }, // 0x52 R
+ {1, HID_KEY_S }, // 0x53 S
+ {1, HID_KEY_T }, // 0x55 T
+ {1, HID_KEY_U }, // 0x55 U
+ {1, HID_KEY_V }, // 0x56 V
+ {1, HID_KEY_W }, // 0x57 W
+ {1, HID_KEY_X }, // 0x58 X
+ {1, HID_KEY_Y }, // 0x59 Y
+ {1, HID_KEY_Z }, // 0x5A Z
+ {0, HID_KEY_BRACKET_LEFT }, // 0x5B [
+ {0, HID_KEY_BACKSLASH }, // 0x5C '\'
+ {0, HID_KEY_BRACKET_RIGHT }, // 0x5D ]
+ {1, HID_KEY_6 }, // 0x5E ^
+ {1, HID_KEY_MINUS }, // 0x5F _
+
+ {0, HID_KEY_GRAVE }, // 0x60 `
+ {0, HID_KEY_A }, // 0x61 a
+ {0, HID_KEY_B }, // 0x62 b
+ {0, HID_KEY_C }, // 0x63 c
+ {0, HID_KEY_D }, // 0x66 d
+ {0, HID_KEY_E }, // 0x65 e
+ {0, HID_KEY_F }, // 0x66 f
+ {0, HID_KEY_G }, // 0x67 g
+ {0, HID_KEY_H }, // 0x68 h
+ {0, HID_KEY_I }, // 0x69 i
+ {0, HID_KEY_J }, // 0x6A j
+ {0, HID_KEY_K }, // 0x6B k
+ {0, HID_KEY_L }, // 0x6C l
+ {0, HID_KEY_M }, // 0x6D m
+ {0, HID_KEY_N }, // 0x6E n
+ {0, HID_KEY_O }, // 0x6F o
+ {0, HID_KEY_P }, // 0x70 p
+ {0, HID_KEY_Q }, // 0x71 q
+ {0, HID_KEY_R }, // 0x72 r
+ {0, HID_KEY_S }, // 0x73 s
+ {0, HID_KEY_T }, // 0x75 t
+ {0, HID_KEY_U }, // 0x75 u
+ {0, HID_KEY_V }, // 0x76 v
+ {0, HID_KEY_W }, // 0x77 w
+ {0, HID_KEY_X }, // 0x78 x
+ {0, HID_KEY_Y }, // 0x79 y
+ {0, HID_KEY_Z }, // 0x7A z
+ {1, HID_KEY_BRACKET_LEFT }, // 0x7B {
+ {1, HID_KEY_BACKSLASH }, // 0x7C |
+ {1, HID_KEY_BRACKET_RIGHT }, // 0x7D }
+ {1, HID_KEY_GRAVE }, // 0x7E ~
+ {0, HID_KEY_DELETE } // 0x7F Delete
+};
+
+/*------------------------------------------------------------------*/
+/* Keycode to Ascii
+ *------------------------------------------------------------------*/
+const hid_keycode_to_ascii_t HID_KEYCODE_TO_ASCII[128] =
+{
+ {0 , 0 }, // 0x00
+ {0 , 0 }, // 0x01
+ {0 , 0 }, // 0x02
+ {0 , 0 }, // 0x03
+ {'a' , 'A' }, // 0x04
+ {'b' , 'B' }, // 0x05
+ {'c' , 'C' }, // 0x06
+ {'d' , 'D' }, // 0x07
+ {'e' , 'E' }, // 0x08
+ {'f' , 'F' }, // 0x09
+ {'g' , 'G' }, // 0x0a
+ {'h' , 'H' }, // 0x0b
+ {'i' , 'I' }, // 0x0c
+ {'j' , 'J' }, // 0x0d
+ {'k' , 'K' }, // 0x0e
+ {'l' , 'L' }, // 0x0f
+ {'m' , 'M' }, // 0x10
+ {'n' , 'N' }, // 0x11
+ {'o' , 'O' }, // 0x12
+ {'p' , 'P' }, // 0x13
+ {'q' , 'Q' }, // 0x14
+ {'r' , 'R' }, // 0x15
+ {'s' , 'S' }, // 0x16
+ {'t' , 'T' }, // 0x17
+ {'u' , 'U' }, // 0x18
+ {'v' , 'V' }, // 0x19
+ {'w' , 'W' }, // 0x1a
+ {'x' , 'X' }, // 0x1b
+ {'y' , 'Y' }, // 0x1c
+ {'z' , 'Z' }, // 0x1d
+ {'1' , '!' }, // 0x1e
+ {'2' , '@' }, // 0x1f
+ {'3' , '#' }, // 0x20
+ {'4' , '$' }, // 0x21
+ {'5' , '%' }, // 0x22
+ {'6' , '^' }, // 0x23
+ {'7' , '&' }, // 0x24
+ {'8' , '*' }, // 0x25
+ {'9' , '(' }, // 0x26
+ {'0' , ')' }, // 0x27
+ {'\r' , '\r' }, // 0x28
+ {'\x1b', '\x1b' }, // 0x29
+ {'\b' , '\b' }, // 0x2a
+ {'\t' , '\t' }, // 0x2b
+ {' ' , ' ' }, // 0x2c
+ {'-' , '_' }, // 0x2d
+ {'=' , '+' }, // 0x2e
+ {'[' , '{' }, // 0x2f
+ {']' , '}' }, // 0x30
+ {'\\' , '|' }, // 0x31
+ {'#' , '~' }, // 0x32
+ {';' , ':' }, // 0x33
+ {'\'' , '\"' }, // 0x34
+ {0 , 0 }, // 0x35
+ {',' , '<' }, // 0x36
+ {'.' , '>' }, // 0x37
+ {'/' , '?' }, // 0x38
+
+ {0 , 0 }, // 0x39
+ {0 , 0 }, // 0x3a
+ {0 , 0 }, // 0x3b
+ {0 , 0 }, // 0x3c
+ {0 , 0 }, // 0x3d
+ {0 , 0 }, // 0x3e
+ {0 , 0 }, // 0x3f
+ {0 , 0 }, // 0x40
+ {0 , 0 }, // 0x41
+ {0 , 0 }, // 0x42
+ {0 , 0 }, // 0x43
+ {0 , 0 }, // 0x44
+ {0 , 0 }, // 0x45
+ {0 , 0 }, // 0x46
+ {0 , 0 }, // 0x47
+ {0 , 0 }, // 0x48
+ {0 , 0 }, // 0x49
+ {0 , 0 }, // 0x4a
+ {0 , 0 }, // 0x4b
+ {0 , 0 }, // 0x4c
+ {0 , 0 }, // 0x4d
+ {0 , 0 }, // 0x4e
+ {0 , 0 }, // 0x4f
+ {0 , 0 }, // 0x50
+ {0 , 0 }, // 0x51
+ {0 , 0 }, // 0x52
+ {0 , 0 }, // 0x53
+
+ {'/' , '/' }, // 0x54
+ {'*' , '*' }, // 0x55
+ {'-' , '-' }, // 0x56
+ {'+' , '+' }, // 0x57
+ {'\r' , '\r' }, // 0x58
+ {'1' , 0 }, // 0x59 /* numpad1 & end */ \
+ {'2' , 0 }, // 0x5a
+ {'3' , 0 }, // 0x5b
+ {'4' , 0 }, // 0x5c
+ {'5' , '5' }, // 0x5d
+ {'6' , 0 }, // 0x5e
+ {'7' , 0 }, // 0x5f
+ {'8' , 0 }, // 0x60
+ {'9' , 0 }, // 0x61
+ {'0' , 0 }, // 0x62
+ {'0' , 0 }, // 0x63
+ {'=' , '=' }, // 0x67
+};
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.h
new file mode 100755
index 0000000..449668a
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEHidGeneric.h
@@ -0,0 +1,583 @@
+/**************************************************************************/
+/*!
+ @file BLEHidGeneric.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEHIDGENERIC_H_
+#define BLEHIDGENERIC_H_
+
+#include "bluefruit_common.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+enum
+{
+ HID_PROTOCOL_MODE_BOOT = 0,
+ HID_PROTOCOL_MODE_REPORT = 1
+};
+
+typedef struct{
+ uint8_t shift;
+ uint8_t keycode;
+}hid_ascii_to_keycode_entry_t;
+extern const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128];
+
+typedef struct{
+ uint8_t ascii;
+ uint8_t shifted;
+}hid_keycode_to_ascii_t;
+extern hid_keycode_to_ascii_t const HID_KEYCODE_TO_ASCII[128];
+
+/// Standard HID Boot Protocol Mouse Report.
+typedef ATTR_PACKED_STRUCT(struct)
+{
+ uint8_t buttons; /**< buttons mask for currently pressed buttons in the mouse. */
+ int8_t x; /**< Current delta x movement of the mouse. */
+ int8_t y; /**< Current delta y movement on the mouse. */
+ int8_t wheel; /**< Current delta vertical wheel movement on the mouse. */
+ int8_t pan; /**< Current delta horizontal wheel movement on the mouse. */
+} hid_mouse_report_t;
+
+/// Standard HID Boot Protocol Keyboard Report.
+typedef ATTR_PACKED_STRUCT(struct)
+{
+ uint8_t modifier; /**< Keyboard modifier byte, indicating pressed modifier keys (a combination of HID_KEYBOARD_MODIFER_* masks). */
+ uint8_t reserved; /**< Reserved for OEM use, always set to 0. */
+ uint8_t keycode[6]; /**< Key codes of the currently pressed keys. */
+} hid_keyboard_report_t;
+
+/// HID Consumer Control Report
+typedef ATTR_PACKED_STRUCT(struct)
+{
+ uint16_t usage_value; ///< Usage value of the pressed control
+} hid_consumer_control_report_t;
+
+/// Gamepad report
+typedef ATTR_PACKED_STRUCT(struct)
+{
+ ATTR_PACKED_STRUCT(struct){
+ uint8_t x : 2;
+ uint8_t y : 2;
+ uint8_t : 4;
+ };
+
+ uint8_t buttons;
+}hid_gamepad_report_t;
+
+
+class BLEHidGeneric : public BLEService
+{
+ public:
+ BLEHidGeneric(uint8_t num_input, uint8_t num_output = 0, uint8_t num_feature = 0);
+
+ void enableKeyboard(bool enable);
+ void enableMouse(bool enable);
+
+ void setHidInfo(uint16_t bcd, uint8_t country, uint8_t flags);
+
+ void setReportLen(uint16_t input_len[], uint16_t output_len[] = NULL, uint16_t feature_len[] = NULL);
+ void setReportMap(const uint8_t* report_map, size_t len);
+
+ void setOutputReportCallback(uint8_t reportID, BLECharacteristic::write_cb_t fp);
+
+ virtual err_t begin(void);
+
+ bool isBootMode(void) { return _protocol_mode == HID_PROTOCOL_MODE_BOOT; }
+
+ // Report
+ bool inputReport(uint8_t reportID, void const* data, int len);
+ bool bootKeyboardReport(void const* data, int len);
+ bool bootMouseReport(void const* data, int len);
+
+ protected:
+ uint8_t _num_input;
+ uint8_t _num_output;
+ uint8_t _num_feature;
+
+ bool _has_keyboard;
+ bool _has_mouse;
+ bool _protocol_mode;
+
+ uint8_t _hid_info[4];
+ const uint8_t* _report_map;
+ size_t _report_map_len;
+
+ uint16_t* _input_len;
+ uint16_t* _output_len;
+ uint16_t* _feature_len;
+
+ BLECharacteristic* _chr_protocol;
+
+ BLECharacteristic* _chr_inputs;
+ BLECharacteristic* _chr_outputs;
+ BLECharacteristic* _chr_features;
+
+ BLECharacteristic* _chr_boot_keyboard_input;
+ BLECharacteristic* _chr_boot_keyboard_output;
+ BLECharacteristic* _chr_boot_mouse_input;
+
+ BLECharacteristic _chr_control;
+
+ friend void blehid_generic_protocol_mode_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset);
+};
+
+//--------------------------------------------------------------------+
+// MOUSE
+//--------------------------------------------------------------------+
+
+/// Standard Mouse Buttons Bitmap
+typedef enum {
+ MOUSE_BUTTON_LEFT = bit(0), ///< Left button
+ MOUSE_BUTTON_RIGHT = bit(1), ///< Right button
+ MOUSE_BUTTON_MIDDLE = bit(2), ///< Middle button,
+ MOUSE_BUTTON_BACKWARD = bit(3), ///< Backward button,
+ MOUSE_BUTTON_FORWARD = bit(4), ///< Forward button,
+}hid_mouse_button_bm_t;
+
+//--------------------------------------------------------------------+
+// Keyboard
+//--------------------------------------------------------------------+
+
+///// Keyboard modifier codes bitmap
+typedef enum {
+ KEYBOARD_MODIFIER_LEFTCTRL = bit(0), ///< Left Control
+ KEYBOARD_MODIFIER_LEFTSHIFT = bit(1), ///< Left Shift
+ KEYBOARD_MODIFIER_LEFTALT = bit(2), ///< Left Alt
+ KEYBOARD_MODIFIER_LEFTGUI = bit(3), ///< Left Window
+ KEYBOARD_MODIFIER_RIGHTCTRL = bit(4), ///< Right Control
+ KEYBOARD_MODIFIER_RIGHTSHIFT = bit(5), ///< Right Shift
+ KEYBOARD_MODIFIER_RIGHTALT = bit(6), ///< Right Alt
+ KEYBOARD_MODIFIER_RIGHTGUI = bit(7) ///< Right Window
+}hid_keyboard_modifier_bm_t;
+
+typedef enum {
+ KEYBOARD_LED_NUMLOCK = bit(0), ///< Num Lock LED
+ KEYBOARD_LED_CAPSLOCK = bit(1), ///< Caps Lock LED
+ KEYBOARD_LED_SCROLLLOCK = bit(2), ///< Scroll Lock LED
+ KEYBOARD_LED_COMPOSE = bit(3), ///< Composition Mode
+ KEYBOARD_LED_KANA = bit(4) ///< Kana mode
+}hid_keyboard_led_bm_t;
+
+//--------------------------------------------------------------------+
+// HID KEYCODE
+//--------------------------------------------------------------------+
+#define HID_KEY_NONE 0x00
+#define HID_KEY_A 0x04
+#define HID_KEY_B 0x05
+#define HID_KEY_C 0x06
+#define HID_KEY_D 0x07
+#define HID_KEY_E 0x08
+#define HID_KEY_F 0x09
+#define HID_KEY_G 0x0A
+#define HID_KEY_H 0x0B
+#define HID_KEY_I 0x0C
+#define HID_KEY_J 0x0D
+#define HID_KEY_K 0x0E
+#define HID_KEY_L 0x0F
+#define HID_KEY_M 0x10
+#define HID_KEY_N 0x11
+#define HID_KEY_O 0x12
+#define HID_KEY_P 0x13
+#define HID_KEY_Q 0x14
+#define HID_KEY_R 0x15
+#define HID_KEY_S 0x16
+#define HID_KEY_T 0x17
+#define HID_KEY_U 0x18
+#define HID_KEY_V 0x19
+#define HID_KEY_W 0x1A
+#define HID_KEY_X 0x1B
+#define HID_KEY_Y 0x1C
+#define HID_KEY_Z 0x1D
+#define HID_KEY_1 0x1E
+#define HID_KEY_2 0x1F
+#define HID_KEY_3 0x20
+#define HID_KEY_4 0x21
+#define HID_KEY_5 0x22
+#define HID_KEY_6 0x23
+#define HID_KEY_7 0x24
+#define HID_KEY_8 0x25
+#define HID_KEY_9 0x26
+#define HID_KEY_0 0x27
+#define HID_KEY_RETURN 0x28
+#define HID_KEY_ESCAPE 0x29
+#define HID_KEY_BACKSPACE 0x2A
+#define HID_KEY_TAB 0x2B
+#define HID_KEY_SPACE 0x2C
+#define HID_KEY_MINUS 0x2D
+#define HID_KEY_EQUAL 0x2E
+#define HID_KEY_BRACKET_LEFT 0x2F
+#define HID_KEY_BRACKET_RIGHT 0x30
+#define HID_KEY_BACKSLASH 0x31
+#define HID_KEY_EUROPE_1 0x32
+#define HID_KEY_SEMICOLON 0x33
+#define HID_KEY_APOSTROPHE 0x34
+#define HID_KEY_GRAVE 0x35
+#define HID_KEY_COMMA 0x36
+#define HID_KEY_PERIOD 0x37
+#define HID_KEY_SLASH 0x38
+#define HID_KEY_CAPS_LOCK 0x39
+#define HID_KEY_F1 0x3A
+#define HID_KEY_F2 0x3B
+#define HID_KEY_F3 0x3C
+#define HID_KEY_F4 0x3D
+#define HID_KEY_F5 0x3E
+#define HID_KEY_F6 0x3F
+#define HID_KEY_F7 0x40
+#define HID_KEY_F8 0x41
+#define HID_KEY_F9 0x42
+#define HID_KEY_F10 0x43
+#define HID_KEY_F11 0x44
+#define HID_KEY_F12 0x45
+#define HID_KEY_PRINT_SCREEN 0x46
+#define HID_KEY_SCROLL_LOCK 0x47
+#define HID_KEY_PAUSE 0x48
+#define HID_KEY_INSERT 0x49
+#define HID_KEY_HOME 0x4A
+#define HID_KEY_PAGE_UP 0x4B
+#define HID_KEY_DELETE 0x4C
+#define HID_KEY_END 0x4D
+#define HID_KEY_PAGE_DOWN 0x4E
+#define HID_KEY_ARROW_RIGHT 0x4F
+#define HID_KEY_ARROW_LEFT 0x50
+#define HID_KEY_ARROW_DOWN 0x51
+#define HID_KEY_ARROW_UP 0x52
+#define HID_KEY_NUM_LOCK 0x53
+#define HID_KEY_KEYPAD_DIVIDE 0x54
+#define HID_KEY_KEYPAD_MULTIPLY 0x55
+#define HID_KEY_KEYPAD_SUBTRACT 0x56
+#define HID_KEY_KEYPAD_ADD 0x57
+#define HID_KEY_KEYPAD_ENTER 0x58
+#define HID_KEY_KEYPAD_1 0x59
+#define HID_KEY_KEYPAD_2 0x5A
+#define HID_KEY_KEYPAD_3 0x5B
+#define HID_KEY_KEYPAD_4 0x5C
+#define HID_KEY_KEYPAD_5 0x5D
+#define HID_KEY_KEYPAD_6 0x5E
+#define HID_KEY_KEYPAD_7 0x5F
+#define HID_KEY_KEYPAD_8 0x60
+#define HID_KEY_KEYPAD_9 0x61
+#define HID_KEY_KEYPAD_0 0x62
+#define HID_KEY_KEYPAD_DECIMAL 0x63
+#define HID_KEY_EUROPE_2 0x64
+#define HID_KEY_APPLICATION 0x65
+#define HID_KEY_POWER 0x66
+#define HID_KEY_KEYPAD_EQUAL 0x67
+#define HID_KEY_F13 0x68
+#define HID_KEY_F14 0x69
+#define HID_KEY_F15 0x6A
+#define HID_KEY_CONTROL_LEFT 0xE0
+#define HID_KEY_SHIFT_LEFT 0xE1
+#define HID_KEY_ALT_LEFT 0xE2
+#define HID_KEY_GUI_LEFT 0xE3
+#define HID_KEY_CONTROL_RIGHT 0xE4
+#define HID_KEY_SHIFT_RIGHT 0xE5
+#define HID_KEY_ALT_RIGHT 0xE6
+#define HID_KEY_GUI_RIGHT 0xE7
+
+//--------------------------------------------------------------------+
+// REPORT DESCRIPTOR
+//--------------------------------------------------------------------+
+//------------- ITEM & TAG -------------//
+#define HID_REPORT_DATA_0(data)
+#define HID_REPORT_DATA_1(data) , (data)
+#define HID_REPORT_DATA_2(data) , U16_BYTES_LE(data)
+#define HID_REPORT_DATA_3(data) , U32_BYTES_LE(data)
+
+#define HID_REPORT_ITEM(data, tag, type, size) \
+ (((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data)
+
+#define RI_TYPE_MAIN 0
+#define RI_TYPE_GLOBAL 1
+#define RI_TYPE_LOCAL 2
+
+//------------- MAIN ITEMS 6.2.2.4 -------------//
+#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1)
+#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1)
+#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1)
+#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1)
+#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0)
+
+//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------//
+#define HID_DATA (0<<0)
+#define HID_CONSTANT (1<<0)
+
+#define HID_ARRAY (0<<1)
+#define HID_VARIABLE (1<<1)
+
+#define HID_ABSOLUTE (0<<2)
+#define HID_RELATIVE (1<<2)
+
+#define HID_WRAP_NO (0<<3)
+#define HID_WRAP (1<<3)
+
+#define HID_LINEAR (0<<4)
+#define HID_NONLINEAR (1<<4)
+
+#define HID_PREFERRED_STATE (0<<5)
+#define HID_PREFERRED_NO (1<<5)
+
+#define HID_NO_NULL_POSITION (0<<6)
+#define HID_NULL_STATE (1<<6)
+
+#define HID_NON_VOLATILE (0<<7)
+#define HID_VOLATILE (1<<7)
+
+#define HID_BITFIELD (0<<8)
+#define HID_BUFFERED_BYTES (1<<8)
+
+//------------- COLLECTION ITEM 6.2.2.6 -------------//
+enum {
+ HID_COLLECTION_PHYSICAL = 0,
+ HID_COLLECTION_APPLICATION,
+ HID_COLLECTION_LOGICAL,
+ HID_COLLECTION_REPORT,
+ HID_COLLECTION_NAMED_ARRAY,
+ HID_COLLECTION_USAGE_SWITCH,
+ HID_COLLECTION_USAGE_MODIFIER
+};
+
+//------------- GLOBAL ITEMS 6.2.2.7 -------------//
+#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1)
+#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n)
+
+#define HID_LOGICAL_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, 1)
+#define HID_LOGICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_GLOBAL, n)
+
+#define HID_LOGICAL_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, 1)
+#define HID_LOGICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_GLOBAL, n)
+
+#define HID_PHYSICAL_MIN(x) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, 1)
+#define HID_PHYSICAL_MIN_N(x, n) HID_REPORT_ITEM(x, 3, RI_TYPE_GLOBAL, n)
+
+#define HID_PHYSICAL_MAX(x) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, 1)
+#define HID_PHYSICAL_MAX_N(x, n) HID_REPORT_ITEM(x, 4, RI_TYPE_GLOBAL, n)
+
+#define HID_UNIT_EXPONENT(x) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, 1)
+#define HID_UNIT_EXPONENT_N(x, n) HID_REPORT_ITEM(x, 5, RI_TYPE_GLOBAL, n)
+
+#define HID_UNIT(x) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, 1)
+#define HID_UNIT_N(x, n) HID_REPORT_ITEM(x, 6, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_SIZE(x) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_SIZE_N(x, n) HID_REPORT_ITEM(x, 7, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_ID(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_ID_N(x) HID_REPORT_ITEM(x, 8, RI_TYPE_GLOBAL, n)
+
+#define HID_REPORT_COUNT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, 1)
+#define HID_REPORT_COUNT_N(x, n) HID_REPORT_ITEM(x, 9, RI_TYPE_GLOBAL, n)
+
+#define HID_PUSH HID_REPORT_ITEM(x, 10, RI_TYPE_GLOBAL, 0)
+#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0)
+
+//------------- LOCAL ITEMS 6.2.2.8 -------------//
+#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n)
+
+#define HID_USAGE_MIN(x) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_MIN_N(x, n) HID_REPORT_ITEM(x, 1, RI_TYPE_LOCAL, n)
+
+#define HID_USAGE_MAX(x) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, 1)
+#define HID_USAGE_MAX_N(x, n) HID_REPORT_ITEM(x, 2, RI_TYPE_LOCAL, n)
+
+//--------------------------------------------------------------------+
+// Usage Table
+//--------------------------------------------------------------------+
+
+/// HID Usage Table - Table 1: Usage Page Summary
+enum {
+ HID_USAGE_PAGE_DESKTOP = 0x01,
+ HID_USAGE_PAGE_SIMULATE = 0x02,
+ HID_USAGE_PAGE_VIRTUAL_REALITY = 0x03,
+ HID_USAGE_PAGE_SPORT = 0x04,
+ HID_USAGE_PAGE_GAME = 0x05,
+ HID_USAGE_PAGE_GENERIC_DEVICE = 0x06,
+ HID_USAGE_PAGE_KEYBOARD = 0x07,
+ HID_USAGE_PAGE_LED = 0x08,
+ HID_USAGE_PAGE_BUTTON = 0x09,
+ HID_USAGE_PAGE_ORDINAL = 0x0a,
+ HID_USAGE_PAGE_TELEPHONY = 0x0b,
+ HID_USAGE_PAGE_CONSUMER = 0x0c,
+ HID_USAGE_PAGE_DIGITIZER = 0x0d,
+ HID_USAGE_PAGE_PID = 0x0f,
+ HID_USAGE_PAGE_UNICODE = 0x10,
+ HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14,
+ HID_USAGE_PAGE_MEDICAL = 0x40,
+ HID_USAGE_PAGE_MONITOR = 0x80, //0x80 - 0x83
+ HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87
+ HID_USAGE_PAGE_BARCODE_SCANNER = 0x8c,
+ HID_USAGE_PAGE_SCALE = 0x8d,
+ HID_USAGE_PAGE_MSR = 0x8e,
+ HID_USAGE_PAGE_CAMERA = 0x90,
+ HID_USAGE_PAGE_ARCADE = 0x91,
+ HID_USAGE_PAGE_VENDOR = 0xFFFF // 0xFF00 - 0xFFFF
+};
+
+/// HID Usage Table - Table 6: Generic Desktop Page
+enum
+{
+ HID_USAGE_DESKTOP_POINTER = 0x01,
+ HID_USAGE_DESKTOP_MOUSE = 0x02,
+ HID_USAGE_DESKTOP_JOYSTICK = 0x04,
+ HID_USAGE_DESKTOP_GAMEPAD = 0x05,
+ HID_USAGE_DESKTOP_KEYBOARD = 0x06,
+ HID_USAGE_DESKTOP_KEYPAD = 0x07,
+ HID_USAGE_DESKTOP_MULTI_AXIS_CONTROLLER = 0x08,
+ HID_USAGE_DESKTOP_TABLET_PC_SYSTEM = 0x09,
+ HID_USAGE_DESKTOP_X = 0x30,
+ HID_USAGE_DESKTOP_Y = 0x31,
+ HID_USAGE_DESKTOP_Z = 0x32,
+ HID_USAGE_DESKTOP_RX = 0x33,
+ HID_USAGE_DESKTOP_RY = 0x34,
+ HID_USAGE_DESKTOP_RZ = 0x35,
+ HID_USAGE_DESKTOP_SLIDER = 0x36,
+ HID_USAGE_DESKTOP_DIAL = 0x37,
+ HID_USAGE_DESKTOP_WHEEL = 0x38,
+ HID_USAGE_DESKTOP_HAT_SWITCH = 0x39,
+ HID_USAGE_DESKTOP_COUNTED_BUFFER = 0x3a,
+ HID_USAGE_DESKTOP_BYTE_COUNT = 0x3b,
+ HID_USAGE_DESKTOP_MOTION_WAKEUP = 0x3c,
+ HID_USAGE_DESKTOP_START = 0x3d,
+ HID_USAGE_DESKTOP_SELECT = 0x3e,
+ HID_USAGE_DESKTOP_VX = 0x40,
+ HID_USAGE_DESKTOP_VY = 0x41,
+ HID_USAGE_DESKTOP_VZ = 0x42,
+ HID_USAGE_DESKTOP_VBRX = 0x43,
+ HID_USAGE_DESKTOP_VBRY = 0x44,
+ HID_USAGE_DESKTOP_VBRZ = 0x45,
+ HID_USAGE_DESKTOP_VNO = 0x46,
+ HID_USAGE_DESKTOP_FEATURE_NOTIFICATION = 0x47,
+ HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER = 0x48,
+ HID_USAGE_DESKTOP_SYSTEM_CONTROL = 0x80,
+ HID_USAGE_DESKTOP_SYSTEM_POWER_DOWN = 0x81,
+ HID_USAGE_DESKTOP_SYSTEM_SLEEP = 0x82,
+ HID_USAGE_DESKTOP_SYSTEM_WAKE_UP = 0x83,
+ HID_USAGE_DESKTOP_SYSTEM_CONTEXT_MENU = 0x84,
+ HID_USAGE_DESKTOP_SYSTEM_MAIN_MENU = 0x85,
+ HID_USAGE_DESKTOP_SYSTEM_APP_MENU = 0x86,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_HELP = 0x87,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_EXIT = 0x88,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_SELECT = 0x89,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_RIGHT = 0x8A,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_LEFT = 0x8B,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_UP = 0x8C,
+ HID_USAGE_DESKTOP_SYSTEM_MENU_DOWN = 0x8D,
+ HID_USAGE_DESKTOP_SYSTEM_COLD_RESTART = 0x8E,
+ HID_USAGE_DESKTOP_SYSTEM_WARM_RESTART = 0x8F,
+ HID_USAGE_DESKTOP_DPAD_UP = 0x90,
+ HID_USAGE_DESKTOP_DPAD_DOWN = 0x91,
+ HID_USAGE_DESKTOP_DPAD_RIGHT = 0x92,
+ HID_USAGE_DESKTOP_DPAD_LEFT = 0x93,
+ HID_USAGE_DESKTOP_SYSTEM_DOCK = 0xA0,
+ HID_USAGE_DESKTOP_SYSTEM_UNDOCK = 0xA1,
+ HID_USAGE_DESKTOP_SYSTEM_SETUP = 0xA2,
+ HID_USAGE_DESKTOP_SYSTEM_BREAK = 0xA3,
+ HID_USAGE_DESKTOP_SYSTEM_DEBUGGER_BREAK = 0xA4,
+ HID_USAGE_DESKTOP_APPLICATION_BREAK = 0xA5,
+ HID_USAGE_DESKTOP_APPLICATION_DEBUGGER_BREAK = 0xA6,
+ HID_USAGE_DESKTOP_SYSTEM_SPEAKER_MUTE = 0xA7,
+ HID_USAGE_DESKTOP_SYSTEM_HIBERNATE = 0xA8,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INVERT = 0xB0,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_INTERNAL = 0xB1,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_EXTERNAL = 0xB2,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_BOTH = 0xB3,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_DUAL = 0xB4,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_TOGGLE_INT_EXT = 0xB5,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_SWAP_PRIMARY_SECONDARY = 0xB6,
+ HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7
+};
+
+/// HID Usage Table: Consumer Page (0x0C)
+/// Only contains controls that supported by Windows (whole list is too long)
+enum
+{
+ // Generic Control
+ HID_USAGE_CONSUMER_CONTROL = 0x0001,
+
+ // Power Control
+ HID_USAGE_CONSUMER_POWER = 0x0030,
+ HID_USAGE_CONSUMER_RESET = 0x0031,
+ HID_USAGE_CONSUMER_SLEEP = 0x0032,
+
+ // Screen Brightness
+ HID_USAGE_CONSUMER_BRIGHTNESS_INCREMENT = 0x006F,
+ HID_USAGE_CONSUMER_BRIGHTNESS_DECREMENT = 0x0070,
+
+ // These HID usages operate only on mobile systems (battery powered) and
+ // require Windows 8 (build 8302 or greater).
+ HID_USAGE_CONSUMER_WIRELESS_RADIO_CONTROLS = 0x000C,
+ HID_USAGE_CONSUMER_WIRELESS_RADIO_BUTTONS = 0x00C6,
+ HID_USAGE_CONSUMER_WIRELESS_RADIO_LED = 0x00C7,
+ HID_USAGE_CONSUMER_WIRELESS_RADIO_SLIDER_SWITCH = 0x00C8,
+
+ // Media Control
+ HID_USAGE_CONSUMER_PLAY_PAUSE = 0x00CD,
+ HID_USAGE_CONSUMER_SCAN_NEXT = 0x00B5,
+ HID_USAGE_CONSUMER_SCAN_PREVIOUS = 0x00B6,
+ HID_USAGE_CONSUMER_STOP = 0x00B7,
+ HID_USAGE_CONSUMER_EJECT = 0x00B8,
+
+ HID_USAGE_CONSUMER_VOLUME = 0x00E0,
+ HID_USAGE_CONSUMER_MUTE = 0x00E2,
+ HID_USAGE_CONSUMER_BASS = 0x00E3,
+ HID_USAGE_CONSUMER_TREBLE = 0x00E4,
+ HID_USAGE_CONSUMER_BASS_BOOST = 0x00E5,
+ HID_USAGE_CONSUMER_VOLUME_INCREMENT = 0x00E9,
+ HID_USAGE_CONSUMER_VOLUME_DECREMENT = 0x00EA,
+ HID_USAGE_CONSUMER_BASS_INCREMENT = 0x0152,
+ HID_USAGE_CONSUMER_BASS_DECREMENT = 0x0153,
+ HID_USAGE_CONSUMER_TREBLE_INCREMENT = 0x0154,
+ HID_USAGE_CONSUMER_TREBLE_DECREMENT = 0x0155,
+
+ // Application Launcher
+ HID_USAGE_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION = 0x0183,
+ HID_USAGE_CONSUMER_AL_EMAIL_READER = 0x018A,
+ HID_USAGE_CONSUMER_AL_CALCULATOR = 0x0192,
+ HID_USAGE_CONSUMER_AL_LOCAL_BROWSER = 0x0194,
+
+ // Browser/Explorer Specific
+ HID_USAGE_CONSUMER_AC_SEARCH = 0x0221,
+ HID_USAGE_CONSUMER_AC_HOME = 0x0223,
+ HID_USAGE_CONSUMER_AC_BACK = 0x0224,
+ HID_USAGE_CONSUMER_AC_FORWARD = 0x0225,
+ HID_USAGE_CONSUMER_AC_STOP = 0x0226,
+ HID_USAGE_CONSUMER_AC_REFRESH = 0x0227,
+ HID_USAGE_CONSUMER_AC_BOOKMARKS = 0x022A,
+
+ // Mouse Horizontal scroll
+ HID_USAGE_CONSUMER_AC_PAN = 0x0238,
+};
+
+
+#endif /* BLEHIDGENERIC_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEMidi.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEMidi.cpp
new file mode 100755
index 0000000..cc16f6d
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEMidi.cpp
@@ -0,0 +1,395 @@
+/**************************************************************************/
+/*!
+ @file BLEMidi.cpp
+ @author hathach (tinyusb.org) & toddtreece
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+
+// GCC 5x new feature to detect optional include
+#ifdef __has_include
+#if __has_include("MIDI.h")
+ #include <MIDI.h>
+ #define MIDI_LIB_INCLUDED
+#endif
+#endif
+
+
+/* MIDI Service: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700
+ * MIDI I/O : 7772E5DB-3868-4112-A1A9-F2669D106BF3
+ */
+
+const uint8_t BLEMIDI_UUID_SERVICE[] =
+{
+ 0x00, 0xC7, 0xC4, 0x4E, 0xE3, 0x6C, 0x51, 0xA7,
+ 0x33, 0x4B, 0xE8, 0xED, 0x5A, 0x0E, 0xB8, 0x03
+};
+
+const uint8_t BLEMIDI_UUID_CHR_IO[] =
+{
+ 0xF3, 0x6B, 0x10, 0x9D, 0x66, 0xF2, 0xA9, 0xA1,
+ 0x12, 0x41, 0x68, 0x38, 0xDB, 0xE5, 0x72, 0x77
+};
+
+/*------------------------------------------------------------------*/
+/* MIDI Data Type
+ *------------------------------------------------------------------*/
+typedef union ATTR_PACKED
+{
+ struct {
+ uint8_t timestamp_hi : 6;
+ uint8_t : 1;
+ uint8_t start_bit : 1;
+ };
+
+ uint8_t byte;
+} midi_header_t;
+
+VERIFY_STATIC ( sizeof(midi_header_t) == 1 );
+
+typedef union ATTR_PACKED
+{
+ struct {
+ uint8_t timestamp_low : 7;
+ uint8_t start_bit : 1;
+ };
+
+ uint8_t byte;
+} midi_timestamp_t;
+
+VERIFY_STATIC ( sizeof(midi_timestamp_t) == 1 );
+
+typedef struct ATTR_PACKED
+{
+ midi_header_t header;
+ midi_timestamp_t timestamp;
+ uint8_t data[BLE_MIDI_TX_BUFFER_SIZE];
+} midi_event_packet_t;
+
+VERIFY_STATIC ( sizeof(midi_event_packet_t) == (BLE_MIDI_TX_BUFFER_SIZE + 2) );
+
+typedef struct ATTR_PACKED
+{
+ midi_header_t header;
+ uint8_t data[BLE_MIDI_TX_BUFFER_SIZE];
+} midi_split_packet_t;
+
+VERIFY_STATIC ( sizeof(midi_split_packet_t) == (BLE_MIDI_TX_BUFFER_SIZE + 1) );
+
+void blemidi_write_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset);
+
+/*------------------------------------------------------------------*/
+/* IMPLEMENTATION
+ *------------------------------------------------------------------*/
+BLEMidi::BLEMidi(uint16_t fifo_depth)
+ : BLEService(BLEMIDI_UUID_SERVICE), _io(BLEMIDI_UUID_CHR_IO), _rxd_fifo(1, fifo_depth)
+{
+ _write_cb = NULL;
+ _midilib_obj = NULL;
+}
+
+bool BLEMidi::notifyEnabled(void)
+{
+ return Bluefruit.connPaired() && _io.notifyEnabled();
+}
+
+void BLEMidi::setWriteCallback(midi_write_cb_t fp)
+{
+ _write_cb = fp;
+}
+
+void BLEMidi::autoMIDIread(void* midi_obj)
+{
+ _midilib_obj = midi_obj;
+}
+void BLEMidi::begin(int baudrate)
+{
+ (void) baudrate;
+ begin();
+}
+
+err_t BLEMidi::begin(void)
+{
+ _rxd_fifo.begin();
+
+ // Invoke base class begin()
+ VERIFY_STATUS( BLEService::begin() );
+
+ // IO characteristic
+ _io.setProperties(CHR_PROPS_READ | CHR_PROPS_WRITE | CHR_PROPS_WRITE_WO_RESP | CHR_PROPS_NOTIFY);
+ _io.setPermission(SECMODE_ENC_NO_MITM, SECMODE_ENC_NO_MITM);
+ _io.setWriteCallback(blemidi_write_cb);
+
+ VERIFY_STATUS( _io.begin() );
+
+ // Attempt to change the connection interval to 11.25-15 ms when starting HID
+ Bluefruit.setConnInterval(9, 12);
+
+ return ERROR_NONE;
+}
+
+/*------------------------------------------------------------------*/
+/* Callbacks
+ *------------------------------------------------------------------*/
+void blemidi_write_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset)
+{
+ (void) offset;
+ if ( len < 3 ) return;
+
+ BLEMidi& midi_svc = (BLEMidi&) chr.parentService();
+ midi_svc._write_handler(data, len);
+}
+
+void BLEMidi::_write_handler(uint8_t* data, uint16_t len)
+{
+ // drop the BLE MIDI header byte
+ data++;
+ len--;
+
+ while (len)
+ {
+
+ // timestamp low byte followed by a MIDI status,
+ // so we drop the timestamp low byte
+ if ( isStatusByte(data[0]) && isStatusByte(data[1]) )
+ {
+ data++;
+ len--;
+ }
+ // timestamp low byte on it's own (running status),
+ // so we drop the timestamp low byte
+ else if ( isStatusByte(data[0]) && ! isStatusByte(data[1]) )
+ {
+ data++;
+ len--;
+ }
+
+ // write the status or MIDI data to the FIFO
+ _rxd_fifo.write(data++, 1);
+ len--;
+ }
+
+ // Call write callback if configured
+ if ( _write_cb ) _write_cb();
+
+#ifdef MIDI_LIB_INCLUDED
+ // read while possible if configured
+ if ( _midilib_obj )
+ {
+ while( ((midi::MidiInterface<BLEMidi>*)_midilib_obj)->read() ) { }
+ }
+#endif
+
+}
+
+/*------------------------------------------------------------------*/
+/* Stream API
+ *------------------------------------------------------------------*/
+int BLEMidi::read ( void )
+{
+ uint8_t ch;
+ return _rxd_fifo.read(&ch) ? (int) ch : EOF;
+}
+
+
+size_t BLEMidi::write ( uint8_t b )
+{
+ // MIDI Library will write event byte by byte.
+ // We need to buffer the data until we have a full event,
+ // or until we reach the TX buffer limit.
+ static uint8_t count = 0;
+ static uint8_t buf[BLE_MIDI_TX_BUFFER_SIZE] = { 0 };
+
+ // the current byte is a sysex end status message,
+ // and we still have an existing buffer. send the
+ // existing buffer and clear it so we can send
+ // the sysex end status message with the appropriate
+ // BLE header and timestamp bytes.
+ if(b == 0xF7 && count > 0)
+ {
+ // send and clear the last of the existing buffer.
+ // it should contain the final bytes in the sysex payload.
+ if (isStatusByte(buf[0]))
+ send(buf, count);
+ else
+ sendSplit(buf, count);
+
+ // reset buffer
+ buf[0] = 0;
+ count = 0;
+ }
+
+ // add the current byte to the buffer
+ buf[count++] = b;
+
+ // send matching 1, 2, or 3 byte messages
+ // and clear the buffer
+ if ( (oneByteMessage(buf[0]) && count == 1) ||
+ (twoByteMessage(buf[0]) && count == 2) ||
+ (threeByteMessage(buf[0]) && count == 3) )
+ {
+ send(buf, count);
+ // reset buffer
+ buf[0] = 0;
+ count = 0;
+ }
+
+ // do we have a full buffer at this point?
+ if(count == BLE_MIDI_TX_BUFFER_SIZE)
+ {
+ // send a full or split message depending
+ // on the type of the first byte in the buffer
+ if (isStatusByte(buf[0]))
+ send(buf, count);
+ else
+ sendSplit(buf, count);
+
+ // reset buffer
+ buf[0] = 0;
+ count = 0;
+ }
+
+ return 1;
+}
+
+int BLEMidi::available ( void )
+{
+ return _rxd_fifo.count();
+}
+
+int BLEMidi::peek ( void )
+{
+ uint8_t ch;
+ return _rxd_fifo.peek(&ch) ? (int) ch : EOF;
+}
+
+void BLEMidi::flush ( void )
+{
+ _rxd_fifo.clear();
+}
+
+/*------------------------------------------------------------------*/
+/* Message Type Helpers
+ *------------------------------------------------------------------*/
+bool BLEMidi::isStatusByte( uint8_t b )
+{
+ // if the bit 7 is set, then it's a MIDI status message
+ if (bitRead(b, 7))
+ return true;
+ else
+ return false;
+}
+
+bool BLEMidi::oneByteMessage( uint8_t status )
+{
+ // system messages
+ if (status >= 0xF4 && status <= 0xFF) return true;
+
+ // system common
+ if (status == 0xF1) return true;
+
+ // sysex end
+ if (status == 0xF7) return true;
+
+ return false;
+}
+
+bool BLEMidi::twoByteMessage( uint8_t status )
+{
+ // program change, aftertouch
+ if (status >= 0xC0 && status <= 0xDF) return true;
+
+ // song select
+ if (status == 0xF3) return true;
+
+ return false;
+}
+
+bool BLEMidi::threeByteMessage( uint8_t status )
+{
+ // note off, note on, aftertouch, control change
+ if (status >= 0x80 && status <= 0xBF) return true;
+
+ // pitch wheel change
+ if (status >= 0xE0 && status <= 0xEF) return true;
+
+ // song position pointer
+ if (status == 0xF2) return true;
+
+ return false;
+}
+
+/*------------------------------------------------------------------*/
+/* Send Event (notify)
+ *------------------------------------------------------------------*/
+bool BLEMidi::send(uint8_t data[], uint8_t len)
+{
+ uint32_t tstamp = millis();
+
+ midi_event_packet_t event =
+ {
+ .header = {{
+ .timestamp_hi = (uint8_t) ((tstamp & 0x1F80UL) >> 7),
+ .start_bit = 1
+ }},
+
+ .timestamp = {{
+ .timestamp_low = (uint8_t) (tstamp & 0x7FUL),
+ .start_bit = 1
+ }}
+ };
+
+ memcpy(event.data, data, len);
+
+ // send data length + 1 byte for header + 1 byte for timestamp
+ return _io.notify(&event, len + 2);
+}
+
+bool BLEMidi::sendSplit(uint8_t data[], uint8_t len)
+{
+ uint32_t tstamp = millis();
+
+ midi_split_packet_t event =
+ {
+ .header = {{
+ .timestamp_hi = (uint8_t) ((tstamp & 0x1F80UL) >> 7),
+ .start_bit = 1
+ }}
+ };
+
+ memcpy(event.data, data, len);
+
+ // send data length + 1 byte for header
+ // don't include the second timestamp byte
+ return _io.notify(&event, len + 1);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEMidi.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEMidi.h
new file mode 100755
index 0000000..dbcb872
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEMidi.h
@@ -0,0 +1,99 @@
+/**************************************************************************/
+/*!
+ @file BLEMidi.h
+ @author hathach (tinyusb.org) & toddtreece
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com) All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEMIDI_H_
+#define BLEMIDI_H_
+
+#include "bluefruit_common.h"
+#include "utility/adafruit_fifo.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+#define MIDI_CREATE_BLE_INSTANCE(midiService) MIDI_CREATE_INSTANCE(BLEMidi, midiService, MIDI)
+
+#define BLE_MIDI_DEFAULT_FIFO_DEPTH 128
+#define BLE_MIDI_TX_BUFFER_SIZE 3
+
+extern const uint8_t BLEMIDI_UUID_SERVICE[];
+extern const uint8_t BLEMIDI_UUID_CHR_IO[];
+
+class BLEMidi: public BLEService, public Stream
+{
+ public:
+ typedef void (*midi_write_cb_t) (void);
+
+ BLEMidi(uint16_t fifo_depth = BLE_MIDI_DEFAULT_FIFO_DEPTH);
+
+ virtual err_t begin(void);
+ void begin(int baudrate); // MidiInterface
+ bool notifyEnabled(void);
+
+ bool send(uint8_t data[], uint8_t len);
+ bool sendSplit(uint8_t data[], uint8_t len);
+
+ // message type helpers
+ bool isStatusByte(uint8_t b);
+ bool oneByteMessage(uint8_t status);
+ bool twoByteMessage(uint8_t status);
+ bool threeByteMessage(uint8_t status);
+
+ void setWriteCallback(midi_write_cb_t fp);
+ void autoMIDIread(void* midi_obj);
+
+ // Stream API for MIDI Interface
+ virtual int read ( void );
+ virtual size_t write ( uint8_t b );
+ virtual int available ( void );
+ virtual int peek ( void );
+ virtual void flush ( void );
+
+ using Print::write; // pull in write(str) and write(buf, size) from Print
+
+ private:
+ BLECharacteristic _io;
+
+ Adafruit_FIFO _rxd_fifo;
+ midi_write_cb_t _write_cb;
+
+ void* _midilib_obj;
+
+ void _write_handler(uint8_t* data, uint16_t len);
+
+ friend void blemidi_write_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset);
+};
+
+
+
+#endif /* BLEMIDI_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEUart.cpp b/arduino/libraries/Bluefruit52Lib/src/services/BLEUart.cpp
new file mode 100755
index 0000000..050ecc8
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEUart.cpp
@@ -0,0 +1,325 @@
+/**************************************************************************/
+/*!
+ @file BLEUart.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+#include "utility/TimeoutTimer.h"
+
+/* UART Serivce: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
+ * UART RXD : 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
+ * UART TXD : 6E400003-B5A3-F393-E0A9-E50E24DCCA9E
+ */
+
+const uint8_t BLEUART_UUID_SERVICE[] =
+{
+ 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0,
+ 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E
+};
+
+const uint8_t BLEUART_UUID_CHR_RXD[] =
+{
+ 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0,
+ 0x93, 0xF3, 0xA3, 0xB5, 0x02, 0x00, 0x40, 0x6E
+};
+
+const uint8_t BLEUART_UUID_CHR_TXD[] =
+{
+ 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0,
+ 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E
+};
+
+/**
+ * Constructor
+ */
+BLEUart::BLEUart(uint16_t fifo_depth)
+ : BLEService(BLEUART_UUID_SERVICE), _txd(BLEUART_UUID_CHR_TXD), _rxd(BLEUART_UUID_CHR_RXD)
+{
+ _rx_fifo = NULL;
+ _rx_cb = NULL;
+ _rx_fifo_depth = fifo_depth;
+
+ _tx_fifo = NULL;
+ _tx_buffered = 0;
+ _buffered_th = NULL;
+}
+
+/**
+ * Destructor
+ */
+BLEUart::~BLEUart()
+{
+ if ( _tx_fifo ) delete _tx_fifo;
+}
+
+/**
+ * Callback when received new data
+ * @param chr
+ * @param data
+ * @param len
+ * @param offset
+ */
+void bleuart_rxd_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset)
+{
+ (void) offset;
+
+ BLEUart& svc = (BLEUart&) chr.parentService();
+ svc._rx_fifo->write(data, len);
+
+#if CFG_DEBUG >= 2
+ LOG_LV2("BLEUART", "RX: ");
+ PRINT_BUFFER(data, len);
+#endif
+
+ // invoke user callback
+ if ( svc._rx_cb ) svc._rx_cb();
+}
+
+/**
+ * Timer callback periodically to send TX packet (if enabled).
+ * @param timer
+ */
+void bleuart_txd_buffered_hdlr(TimerHandle_t timer)
+{
+ BLEUart* svc = (BLEUart*) pvTimerGetTimerID(timer);
+
+ // skip if null (unlikely)
+ if ( !svc->_tx_fifo ) return;
+
+ // flush tx data
+ (void) svc->flush_tx_buffered();
+}
+
+void bleuart_txd_cccd_cb(BLECharacteristic& chr, uint16_t value)
+{
+ BLEUart& svc = (BLEUart&) chr.parentService();
+
+ if ( svc._buffered_th == NULL) return;
+
+ // Enable TXD timer if configured
+ if (value & BLE_GATT_HVX_NOTIFICATION)
+ {
+ xTimerStart(svc._buffered_th, 0); // if started --> timer got reset
+ }else
+ {
+ xTimerStop(svc._buffered_th, 0);
+ }
+}
+
+void BLEUart::setRxCallback( rx_callback_t fp)
+{
+ _rx_cb = fp;
+}
+
+/**
+ * Enable packet buffered for TXD
+ * Note: packet is sent right away if it reach MTU bytes
+ * @param enable true or false
+ */
+void BLEUart::bufferTXD(uint8_t enable)
+{
+ _tx_buffered = enable;
+
+ if ( enable )
+ {
+ // enable cccd callback to start timer when enabled
+ _txd.setCccdWriteCallback(bleuart_txd_cccd_cb);
+
+ // Create FIFO for TX TODO Larger MTU Size
+ if ( _tx_fifo == NULL )
+ {
+ _tx_fifo = new Adafruit_FIFO(1);
+ _tx_fifo->begin( Bluefruit.Gap.getMaxMtuByConnCfg(CONN_CFG_PERIPHERAL) );
+ }
+ }else
+ {
+ _txd.setCccdWriteCallback(NULL);
+
+ if ( _tx_fifo ) delete _tx_fifo;
+ }
+}
+
+err_t BLEUart::begin(void)
+{
+ _rx_fifo = new Adafruit_FIFO(1);
+ _rx_fifo->begin(_rx_fifo_depth);
+
+ // Invoke base class begin()
+ VERIFY_STATUS( BLEService::begin() );
+
+ uint16_t max_mtu = Bluefruit.Gap.getMaxMtuByConnCfg(CONN_CFG_PERIPHERAL);
+
+ // Add TXD Characteristic
+ _txd.setProperties(CHR_PROPS_NOTIFY);
+ // TODO enable encryption when bonding is enabled
+ _txd.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
+ _txd.setMaxLen( max_mtu );
+ _txd.setUserDescriptor("TXD");
+ VERIFY_STATUS( _txd.begin() );
+
+ // Add RXD Characteristic
+ _rxd.setProperties(CHR_PROPS_WRITE | CHR_PROPS_WRITE_WO_RESP);
+ _rxd.setWriteCallback(bleuart_rxd_cb);
+
+ // TODO enable encryption when bonding is enabled
+ _rxd.setPermission(SECMODE_NO_ACCESS, SECMODE_OPEN);
+ _rxd.setMaxLen( max_mtu );
+ _rxd.setUserDescriptor("RXD");
+ VERIFY_STATUS(_rxd.begin());
+
+ return ERROR_NONE;
+}
+
+bool BLEUart::notifyEnabled(void)
+{
+ return _txd.notifyEnabled();
+}
+
+void BLEUart::_disconnect_cb(void)
+{
+ if (_buffered_th)
+ {
+ xTimerDelete(_buffered_th, 0);
+ _buffered_th = NULL;
+
+ if (_tx_fifo) _tx_fifo->clear();
+ }
+}
+
+void BLEUart::_connect_cb (void)
+{
+ if ( _tx_buffered )
+ {
+ // create TXD timer TODO take connInterval into account
+ // ((5*ms2tick(Bluefruit.connInterval())) / 4) / 2
+ _buffered_th = xTimerCreate(NULL, ms2tick(10), true, this, bleuart_txd_buffered_hdlr);
+
+ // Start the timer
+ xTimerStart(_buffered_th, 0);
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* STREAM API
+ *------------------------------------------------------------------*/
+int BLEUart::read (void)
+{
+ uint8_t ch;
+ return read(&ch, 1) ? (int) ch : EOF;
+}
+
+int BLEUart::read (uint8_t * buf, size_t size)
+{
+ return _rx_fifo->read(buf, size);
+}
+
+size_t BLEUart::write (uint8_t b)
+{
+ return write(&b, 1);
+}
+
+size_t BLEUart::write (const uint8_t *content, size_t len)
+{
+ // notify right away if txd buffered is not enabled
+ if ( !(_tx_buffered && _tx_fifo) )
+ {
+ return _txd.notify(content, len) ? len : 0;
+ }else
+ {
+ // skip if not enabled
+ if ( !notifyEnabled() ) return 0;
+
+ uint16_t written = _tx_fifo->write(content, len);
+
+ // TODO multiple prph connections
+ // Not up to GATT MTU, notify will be sent later by TXD timer handler
+ if ( _tx_fifo->count() < (Bluefruit.Gap.getMTU( Bluefruit.connHandle() ) - 3) )
+ {
+ return len;
+ }
+ else
+ {
+ // TX fifo has enough data, send notify right away
+ VERIFY( flush_tx_buffered(), 0);
+
+ // still more data left, send them all
+ if ( written < len )
+ {
+ VERIFY( _txd.notify(content+written, len-written), written);
+ }
+
+ return len;
+ }
+ }
+}
+
+int BLEUart::available (void)
+{
+ return _rx_fifo->count();
+}
+
+int BLEUart::peek (void)
+{
+ uint8_t ch;
+ return _rx_fifo->peek(&ch) ? (int) ch : EOF;
+}
+
+void BLEUart::flush (void)
+{
+ _rx_fifo->clear();
+}
+
+bool BLEUart::flush_tx_buffered(void)
+{
+ uint16_t max_hvx = Bluefruit.Gap.getMTU( Bluefruit.connHandle() ) - 3;
+ uint8_t* ff_data = (uint8_t*) rtos_malloc( max_hvx );
+
+ if (!ff_data) return false;
+
+ uint16_t len = _tx_fifo->read(ff_data, max_hvx);
+ bool result = true;
+
+ if ( len )
+ {
+ result = _txd.notify(ff_data, len);
+ }
+
+ rtos_free(ff_data);
+
+ return result;
+}
+
+
+
+
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/BLEUart.h b/arduino/libraries/Bluefruit52Lib/src/services/BLEUart.h
new file mode 100755
index 0000000..d8c589d
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/BLEUart.h
@@ -0,0 +1,105 @@
+/**************************************************************************/
+/*!
+ @file BLEUart.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef BLEUART_H_
+#define BLEUART_H_
+
+#include "bluefruit_common.h"
+#include "utility/adafruit_fifo.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+#define BLE_UART_DEFAULT_FIFO_DEPTH 256
+
+extern const uint8_t BLEUART_UUID_SERVICE[];
+extern const uint8_t BLEUART_UUID_CHR_RXD[];
+extern const uint8_t BLEUART_UUID_CHR_TXD[];
+
+class BLEUart : public BLEService, public Stream
+{
+ public:
+ typedef void (*rx_callback_t) (void);
+
+ BLEUart(uint16_t fifo_depth = BLE_UART_DEFAULT_FIFO_DEPTH);
+ virtual ~BLEUart();
+
+ virtual err_t begin(void);
+
+ bool notifyEnabled (void);
+ void setRxCallback (rx_callback_t fp);
+ void bufferTXD (uint8_t enable);
+
+ // Stream API
+ virtual int read ( void );
+ virtual int read ( uint8_t * buf, size_t size );
+ int read ( char * buf, size_t size ) { return read( (uint8_t*) buf, size); }
+ virtual size_t write ( uint8_t b );
+ virtual size_t write ( const uint8_t *content, size_t len );
+ virtual int available ( void );
+ virtual int peek ( void );
+ virtual void flush ( void );
+
+ // pull in write(str) and write(buf, size) from Print
+ using Print::write;
+
+ protected:
+ BLECharacteristic _txd;
+ BLECharacteristic _rxd;
+
+ // RXD
+ Adafruit_FIFO* _rx_fifo;
+ uint16_t _rx_fifo_depth;
+ rx_callback_t _rx_cb;
+
+ // TXD
+ Adafruit_FIFO* _tx_fifo;
+ uint8_t _tx_buffered;
+ TimerHandle_t _buffered_th;
+
+ bool flush_tx_buffered(void);
+
+ // from BLEService
+ virtual void _disconnect_cb(void);
+ virtual void _connect_cb(void);
+
+ friend void bleuart_rxd_cb(BLECharacteristic& chr, uint8_t* data, uint16_t len, uint16_t offset);
+ friend void bleuart_txd_cccd_cb(BLECharacteristic& chr, uint16_t value);
+ friend void bleuart_txd_buffered_hdlr(TimerHandle_t timer);
+};
+
+
+
+#endif /* BLEUART_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/EddyStone.cpp b/arduino/libraries/Bluefruit52Lib/src/services/EddyStone.cpp
new file mode 100755
index 0000000..22b45b3
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/EddyStone.cpp
@@ -0,0 +1,180 @@
+/**************************************************************************/
+/*!
+ @file EddyStone.cpp
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "bluefruit.h"
+
+/*------------------------------------------------------------------*/
+/* EddyStone URL
+ *------------------------------------------------------------------*/
+char const * const prefix_scheme[] =
+{
+ [0] = "http://www." ,
+ [1] = "https://www." ,
+ [2] = "http://" ,
+ [3] = "https://"
+};
+enum { PREFIX_COUNT = sizeof(prefix_scheme)/sizeof(char*) };
+
+char const * const url_expansion[] =
+{
+ [0 ] = ".com/" ,
+ [1 ] = ".org/" ,
+ [2 ] = ".edu/" ,
+ [3 ] = ".net/" ,
+ [4 ] = ".info/" ,
+ [5 ] = ".biz/" ,
+ [6 ] = ".gov/" ,
+
+ [7 ] = ".com" ,
+ [8 ] = ".org" ,
+ [9 ] = ".edu" ,
+ [10] = ".net" ,
+ [11] = ".info" ,
+ [12] = ".biz" ,
+ [13] = ".gov" ,
+};
+
+enum { EXPANNSION_COUNT = sizeof(url_expansion)/sizeof(char*) };
+
+EddyStoneUrl::EddyStoneUrl(void)
+{
+ _rssi = 0;
+ _url = NULL;
+}
+
+EddyStoneUrl::EddyStoneUrl(int8_t rssiAt0m, const char* url)
+{
+ _rssi = rssiAt0m;
+ _url = url;
+}
+
+bool EddyStoneUrl::setUrl(const char* url)
+{
+ _url = url;
+}
+
+void EddyStoneUrl::setRssi(int8_t rssiAt0m)
+{
+ _rssi = rssiAt0m;
+}
+
+char const* findExpansion(char const* p_url, uint8_t * p_idx)
+{
+ for(uint8_t i=0; i<EXPANNSION_COUNT; i++)
+ {
+ char const * substr = strstr(p_url, url_expansion[i]);
+
+ if ( substr )
+ {
+ *p_idx = i;
+ return substr;
+ }
+ }
+
+ return NULL;
+}
+
+bool EddyStoneUrl::start(void)
+{
+ enum { URL_MAXLEN = 17 };
+ struct ATTR_PACKED {
+ uint16_t eddy_uuid;
+
+ uint8_t frame_type;
+ int8_t rssi;
+ uint8_t url_scheme;
+ uint8_t urlencode[URL_MAXLEN];
+ }eddy =
+ {
+ .eddy_uuid = UUID16_SVC_EDDYSTONE,
+ .frame_type = EDDYSTONE_TYPE_URL,
+ .rssi = _rssi,
+ .url_scheme = 0xff
+ };
+
+ const char* url = _url;
+
+ // Detect url scheme
+ for(uint8_t i=0; i<PREFIX_COUNT; i++)
+ {
+ uint8_t prelen = strlen(prefix_scheme[i]);
+ if ( !memcmp(url, prefix_scheme[i], prelen) )
+ {
+ eddy.url_scheme = i;
+ url += prelen;
+
+ break;
+ }
+ }
+ VERIFY( eddy.url_scheme < PREFIX_COUNT );
+
+ // Encode url data
+ uint8_t len = 0;
+
+ while(*url)
+ {
+ uint8_t ex_code;
+ char const * expansion = findExpansion(url, &ex_code);
+
+ // copy url up to the found expansion, if expansion is found, one more
+ // byte must be reserved for it
+ uint8_t cp_num = (expansion) ? (expansion-url) : strlen(url);
+ if ( cp_num > URL_MAXLEN-(len + (expansion ? 1:0)) )
+ {
+ LOG_LV1("EDDYS", "url is too long");
+ return false;
+ }
+
+ memcpy(eddy.urlencode+len, url, cp_num);
+ url += cp_num;
+ len += cp_num;
+
+ // copy expansion code if found
+ if (expansion)
+ {
+ eddy.urlencode[len++] = ex_code;
+ url += strlen(url_expansion[ex_code]);
+ }
+ }
+
+ // Add UUID16 list with EddyStone
+ VERIFY ( Bluefruit.Advertising.addUuid(UUID16_SVC_EDDYSTONE) );
+
+ // Add Eddystone Service Data
+ VERIFY ( Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_SERVICE_DATA, &eddy, len + 5) );
+
+ return true;
+}
diff --git a/arduino/libraries/Bluefruit52Lib/src/services/EddyStone.h b/arduino/libraries/Bluefruit52Lib/src/services/EddyStone.h
new file mode 100755
index 0000000..4dc4585
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/src/services/EddyStone.h
@@ -0,0 +1,69 @@
+/**************************************************************************/
+/*!
+ @file EddyStone.h
+ @author hathach (tinyusb.org)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2018, Adafruit Industries (adafruit.com)
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef EDDYSTONE_H_
+#define EDDYSTONE_H_
+
+#include "bluefruit_common.h"
+
+#include "BLECharacteristic.h"
+#include "BLEService.h"
+
+enum
+{
+ EDDYSTONE_TYPE_UID = 0x00,
+ EDDYSTONE_TYPE_URL = 0x10,
+ EDDYSTONE_TYPE_TLM = 0x20,
+ EDDYSTONE_TYPE_EID = 0x30,
+};
+
+class EddyStoneUrl
+{
+ private:
+ int8_t _rssi;
+ const char* _url;
+
+ public:
+ EddyStoneUrl(void);
+ EddyStoneUrl(int8_t rssiAt0m, const char* url = NULL);
+
+ bool setUrl(const char* url);
+ void setRssi(int8_t rssiAt0m);
+
+ bool start(void);
+};
+
+
+#endif /* EDDYSTONE_H_ */