Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
Diff: TransferService.cpp
- Revision:
- 0:4eaf82806f06
- Child:
- 1:d623a5792ce5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/TransferService.cpp Mon Aug 18 16:03:22 2014 +0000
@@ -0,0 +1,172 @@
+#include "TransferService.h"
+#include "Logger.h"
+#include "Configuration.h"
+
+namespace Transfer {
+// Transfer base UUID: ADC710C2-xxxx-4BF5-8244-3CEAAA0F87F5
+#define transfer_UUID(x) {0xAD, 0xC7, 0x10, 0xC2, (((x) & 0xFF00) >> 8), ((x) & 0xFF), 0x4B, 0xF5, 0x82, 0x44, 0x3C, 0xEA, 0xAA, 0x0F, 0x87, 0xF5}
+
+// UUID byte arrays
+static const uint8_t transferServiceUUID[] = transfer_UUID(0xACDC);
+static const uint8_t transferFileInfoUUID[] = transfer_UUID(0xACDF);
+static const uint8_t transferFileBlockUUID[16] = transfer_UUID(0xACE0);
+
+// Storage for the value of the characteristics
+struct fileInfo_t {
+ uint16_t length;
+ uint16_t crc16;
+};
+static struct fileInfo_t fileInfo;
+struct fileBlock_t {
+ uint16_t blockNumber;
+ uint8_t data[16];
+};
+static struct fileBlock_t fileBlock;
+
+// Other things needed for operation
+static BLEDevice* ble;
+static Timer downloadTimer;
+
+static uint16_t expectingBlock = 0;
+
+static bool acceptFile = true; // additional condition whether to accept a file upload or not, currently always accept
+static bool downloadInProgress = false; // indicates if we are downloading a file from the phone
+
+static GattCharacteristic transferFileInfo(transferFileInfoUUID,
+ (uint8_t *)&fileInfo,
+ sizeof(fileInfo),
+ sizeof(fileInfo),
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
+
+static GattCharacteristic transferFileBlock(transferFileBlockUUID,
+ (uint8_t *)&fileBlock,
+ sizeof(fileBlock_t),
+ sizeof(fileBlock_t),
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE |
+ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
+
+static GattCharacteristic *allChars[] = {&transferFileInfo, &transferFileBlock};
+static GattService transferService(transferServiceUUID, allChars, sizeof(allChars) / sizeof(GattCharacteristic *));
+
+void init(BLEDevice &bleDevice)
+{
+ downloadInProgress = false;
+ ble = &bleDevice;
+ ble->addService(transferService);
+ DEBUG("Added transfer service\r\n");
+}
+
+void reset()
+{
+ // reset internal state on new connection
+ downloadInProgress = false;
+}
+
+const uint8_t *getServiceUUIDp()
+{
+ return transferServiceUUID;
+}
+
+void requestBlock(uint16_t); // prototype declaration
+void sendFileInfo();
+void refuseFile();
+void sendFileDownloadedSuccessfully();
+
+void handleDataWritten(uint16_t handle)
+{
+ if (!ble) {
+ return;
+ }
+
+ if (handle == transferFileInfo.getHandle()) {
+ uint16_t len = sizeof(fileInfo);
+ ble->readCharacteristicValue(handle, (uint8_t *) &fileInfo, &len);
+
+ if ((fileInfo.length == 0) && (fileInfo.crc16 == 0)) {
+ // signal to cancel pending upload
+ downloadInProgress = false;
+ downloadTimer.reset();
+ expectingBlock = 0;
+ DEBUG("Download RESET\r\n");
+ return;
+ }
+
+ DEBUG("Offered file len=%d, crc=0x%04x, acceptFile=%d, downloadInProgress=%d\r\n", fileInfo.length, fileInfo.crc16, acceptFile, downloadInProgress);
+
+ // Now we must decide whether to accept it or not
+ if (acceptFile && !downloadInProgress) {
+ downloadTimer.reset();
+ downloadTimer.start();
+ downloadInProgress = true;
+ requestBlock(0);
+ } else {
+ refuseFile();
+ }
+ } else if (handle == transferFileBlock.getHandle()) {
+ uint16_t len = sizeof(fileBlock);
+ ble->readCharacteristicValue(handle, (uint8_t *) &fileBlock, &len);
+
+ // DEBUG("received blk %u (total %u): ", fileBlock.blockNumber, fileInfo.length / Config::blockSize);
+ // uint8_t byte;
+ // for (int i = 2; i < len; i++) {
+ // byte = *(((uint8_t*) &fileBlock) + i);
+ // DEBUG("%02x ", byte);
+ // }
+ // DEBUG("\r\n");
+
+ if (fileBlock.blockNumber != expectingBlock) {
+ DEBUG("Expected blk %d, not %d!\r\n", expectingBlock, fileBlock.blockNumber);
+ requestBlock(expectingBlock);
+ return;
+ } else {
+ // DEBUG("."); // one dot = one successfully received packet
+ }
+
+ if (fileBlock.blockNumber > (fileInfo.length / Config::blockSize)) {
+ DEBUG("Error: block %d is out of range\r\n", fileBlock.blockNumber);
+ return;
+ }
+
+ // "processing" step disabled
+ //uint16_t offset = fileBlock.blockNumber * Config::blockSize;
+ //memcpy(downloadLocation, fileBlock[0].data, Config::blockSize);
+
+ // request next block if needed
+ uint16_t nextBlock = fileBlock.blockNumber + 1;
+ if (nextBlock <= fileInfo.length / Config::blockSize) {
+ requestBlock(nextBlock);
+ } else {
+ sendFileDownloadedSuccessfully();
+ }
+ } else {
+ DEBUG("Got data on unexpected characteristic handle %u!\r\n", handle);
+ }
+}
+
+void requestBlock(uint16_t blockNumber)
+{
+ // Requesting a block by sending notification is disabled for speed
+ //ble->updateCharacteristicValue(transferFileBlocks[0].getHandle(), (uint8_t*) &blockNumber, sizeof(blockNumber), false);
+ //DEBUG("BlockReq %d --> PHONE\r\n", blockNumber);
+ expectingBlock = blockNumber;
+}
+
+void sendFileInfo(uint32_t value)
+{
+ // refusal is indicated by sending a fileInfo with all zeros
+ ble->updateCharacteristicValue(transferFileInfo.getHandle(), (uint8_t *) &value, sizeof(value), false);
+}
+
+void refuseFile()
+{
+ sendFileInfo(0);
+}
+
+void sendFileDownloadedSuccessfully()
+{
+ sendFileInfo(1);
+ downloadInProgress = false;
+ downloadTimer.stop();
+ DEBUG("File transfer took %0.1f sec\r\n", downloadTimer.read());
+}
+} // namespace transfer