this is using the mbed os version 5-13-1

Dependencies:   mbed-http

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BleManager.cpp Source File

BleManager.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include <events/mbed_events.h>
00018 #include <mbed.h>
00019 #include "debug.h"
00020 #include "common_config.h"
00021 #include "ble/BLE.h"
00022 #include "ble/services/UARTService.h"
00023 #include "SecurityManager.h"
00024 #include "BleManager.h"
00025 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
00026 #include "LittleFileSystem.h"
00027 #include "HeapBlockDevice.h"
00028 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
00029 #define FILE_CODE       "btle"
00030 
00031 
00032 //static const uint8_t DEVICE_NAME[] = "SM_device";
00033 //static const uint16_t uuid16_list[] = {LEDService::LED_SERVICE_UUID};
00034 extern UARTService *uart;
00035 
00036 /** This example demonstrates all the basic setup required
00037  *  for pairing and setting up link security both as a central and peripheral
00038  *
00039  *  The example is implemented as two classes, one for the peripheral and one
00040  *  for central inheriting from a common base. They are run in sequence and
00041  *  require a peer device to connect to. During the peripheral device demonstration
00042  *  a peer device is required to connect. In the central device demonstration
00043  *  this peer device will be scanned for and connected to - therefore it should
00044  *  be advertising with the same address as when it connected.
00045  *
00046  *  During the test output is written on the serial connection to monitor its
00047  *  progress.
00048  */
00049 
00050 //static const uint8_t DEVICE_NAME[] = "SM_device";
00051 
00052 /* for demonstration purposes we will store the peer device address
00053  * of the device that connects to us in the first demonstration
00054  * so we can use its address to reconnect to it later */
00055 //static BLEProtocol::AddressBytes_t peer_address;
00056 
00057 /** Base class for both peripheral and central. The same class that provides
00058  *  the logic for the application also implements the SecurityManagerEventHandler
00059  *  which is the interface used by the Security Manager to communicate events
00060  *  back to the applications. You can provide overrides for a selection of events
00061  *  your application is interested in.
00062  */
00063 SMDevice::SMDevice(BLE &ble, events::EventQueue &event_queue, 
00064                    BLEProtocol::AddressBytes_t &peer_address, 
00065                    MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool, 
00066                    Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue, 
00067                    MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool, 
00068                    Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue, 
00069                    ble_config_t *ble_config) :
00070         _ble(ble),
00071         _event_queue(event_queue),
00072         _peer_address(peer_address),
00073         _aT2BleDatamPool (aT2BleDatamPool),
00074         _aT2BleDataQueue (aT2BleDataQueue),
00075         _ble2ATDatamPool (ble2ATDatamPool),
00076         _ble2ATDataQueue (ble2ATDataQueue),
00077         ble_config(ble_config),
00078         _handle(0),
00079         _is_connecting(false), 
00080         _led1(LED1, 0)
00081 { 
00082     isConnected = false;
00083 }
00084 
00085 SMDevice::~SMDevice()
00086 {
00087     if (_ble.hasInitialized()) {
00088         _ble.shutdown();
00089     }
00090 }
00091 
00092 /** Start BLE interface initialisation */
00093 void SMDevice::run()
00094 {
00095     dbg_printf(LOG, "\r\n [BTLE MAN]  Thread Id = %X\r\n", (uint32_t)ThisThread::get_id());
00096 
00097     ble_error_t error;
00098 
00099     /* to show we're running we'll blink every 10secs */
00100     //_event_queue.call_every(10000, this, &SMDevice::blink);
00101 
00102     /* to show we're advertising we'll print status every minute */
00103     //_event_queue.call_every(60000, this, &SMDevice::reportGapState);
00104 
00105     /* process queues every BLE_PROCESS_QUEUES_INTERVAL_MS */
00106     _event_queue.call_every(BLE_PROCESS_QUEUES_INTERVAL_MS, this, &SMDevice::processQueues);
00107 
00108 
00109 
00110     if (_ble.hasInitialized()) {
00111         dbg_printf(LOG, "Ble instance already initialised.\r\n");
00112         return;
00113     }
00114 
00115     /* this will inform us off all events so we can schedule their handling
00116      * using our event queue */
00117     _ble.onEventsToProcess(
00118         makeFunctionPointer(this, &SMDevice::schedule_ble_events)
00119     );
00120 
00121     /* handle timeouts, for example when connection attempts fail */
00122     _ble.gap().onTimeout(
00123         makeFunctionPointer(this, &SMDevice::on_timeout)
00124     );
00125 
00126     error = _ble.init(this, &SMDevice::on_init_complete);
00127 
00128     if (error) {
00129         dbg_printf(LOG, "Error returned by BLE::init.\r\n");
00130         return;
00131     }
00132 
00133     /* this will not return until shutdown */
00134     //_event_queue.dispatch_forever();
00135 }
00136 
00137 
00138 void SMDevice::shutDown()
00139 {
00140     if (_ble.hasInitialized()) {
00141         _ble.shutdown();
00142         dbg_printf(LOG, "Shutting down BLE Instance...\r\n");
00143         _event_queue.break_dispatch();
00144     }
00145 }
00146 
00147 
00148 /* event handler functions */
00149 
00150 /** Respond to a pairing request. This will be called by the stack
00151  * when a pairing request arrives and expects the application to
00152  * call acceptPairingRequest or cancelPairingRequest */
00153 void SMDevice::pairingRequest(
00154     ble::connection_handle_t connectionHandle
00155 ) {
00156     dbg_printf(LOG, "Pairing requested - authorising\r\n");
00157     _ble.securityManager().acceptPairingRequest(connectionHandle);
00158 }
00159 
00160 /** Inform the application of a successful pairing. Terminate the demonstration. */
00161 void SMDevice::pairingResult(
00162     ble::connection_handle_t connectionHandle,
00163     SecurityManager::SecurityCompletionStatus_t result
00164 ) {
00165     if (result == SecurityManager::SEC_STATUS_SUCCESS) {
00166         dbg_printf(LOG, "Pairing successful\r\n");
00167     } else {
00168         dbg_printf(LOG, "Pairing failed\r\n");
00169     }
00170 }
00171 
00172 /** Inform the application of change in encryption status. This will be
00173  * communicated through the serial port */
00174 void SMDevice::linkEncryptionResult(
00175     ble::connection_handle_t connectionHandle,
00176     ble::link_encryption_t result
00177 ) {
00178     if (result == ble::link_encryption_t::ENCRYPTED) {
00179         dbg_printf(LOG, "Link ENCRYPTED\r\n");
00180     } else if (result == ble::link_encryption_t::ENCRYPTED_WITH_MITM) {
00181         dbg_printf(LOG, "Link ENCRYPTED_WITH_MITM\r\n");
00182     } else if (result == ble::link_encryption_t::NOT_ENCRYPTED) {
00183         dbg_printf(LOG, "Link NOT_ENCRYPTED\r\n");
00184     }
00185 
00186 #ifdef DEMO_BLE_SECURITY
00187     /* disconnect in 2 s */
00188     _event_queue.call_in(
00189         2000, &_ble.gap(),
00190         &Gap::disconnect, _handle, Gap::REMOTE_USER_TERMINATED_CONNECTION
00191     );
00192 #endif
00193 }
00194 
00195 /** Override to start chosen activity when initialisation completes */
00196 //void SMDevice::start() = 0;
00197 
00198 /** This is called when BLE interface is initialised and starts the demonstration */
00199 void SMDevice::on_init_complete(BLE::InitializationCompleteCallbackContext *event)
00200 {
00201     ble_error_t error;
00202 
00203     if (event->error) {
00204         dbg_printf(LOG, "Error during the initialisation\r\n");
00205         return;
00206     }
00207 
00208     /* This path will be used to store bonding information but will fallback
00209      * to storing in memory if file access fails (for example due to lack of a filesystem) */
00210     const char* db_path = "/fs/bt_sec_db";
00211     /* If the security manager is required this needs to be called before any
00212      * calls to the Security manager happen. */
00213     error = _ble.securityManager().init(
00214         true,
00215         false,
00216         SecurityManager::IO_CAPS_DISPLAY_ONLY, // SecurityManager::IO_CAPS_NONE
00217         ble_config->pairingKey,
00218         false,
00219         db_path
00220     );
00221 
00222     if (error) {
00223         dbg_printf(LOG, "Error during init %d\r\n", error);
00224         return;
00225     }
00226 
00227     error = _ble.securityManager().preserveBondingStateOnReset(true);
00228 
00229     if (error) {
00230         dbg_printf(LOG, "Error during preserveBondingStateOnReset %d\r\n", error);
00231     }
00232 
00233 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
00234     /* Enable privacy so we can find the keys */
00235     error = _ble.gap().enablePrivacy(true);
00236 
00237     if (error) {
00238         dbg_printf(LOG, "Error enabling privacy\r\n");
00239     }
00240 
00241     Gap::PeripheralPrivacyConfiguration_t configuration_p = {
00242         /* use_non_resolvable_random_address */ false,
00243         Gap::PeripheralPrivacyConfiguration_t::REJECT_NON_RESOLVED_ADDRESS
00244     };
00245     _ble.gap().setPeripheralPrivacyConfiguration(&configuration_p);
00246 
00247     Gap::CentralPrivacyConfiguration_t configuration_c = {
00248         /* use_non_resolvable_random_address */ false,
00249         Gap::CentralPrivacyConfiguration_t::RESOLVE_AND_FORWARD
00250     };
00251     _ble.gap().setCentralPrivacyConfiguration(&configuration_c);
00252 
00253     /* this demo switches between being master and slave */
00254     _ble.securityManager().setHintFutureRoleReversal(true);
00255 #endif
00256 
00257     /* Tell the security manager to use methods in this class to inform us
00258      * of any events. Class needs to implement SecurityManagerEventHandler. */
00259     _ble.securityManager().setSecurityManagerEventHandler(this);
00260 
00261     /* print device address */
00262     Gap::AddressType_t addr_type;
00263     Gap::Address_t addr;
00264     _ble.gap().getAddress(&addr_type, addr);
00265     dbg_printf(LOG, "Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
00266            addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
00267 
00268     /* when scanning we want to connect to a peer device so we need to
00269      * attach callbacks that are used by Gap to notify us of events */
00270     _ble.gap().onConnection(this, &SMDevice::on_connect);
00271     _ble.gap().onDisconnection(this, &SMDevice::on_disconnect);
00272     _ble.gattServer().onDataWritten(this, &SMDevice::onDataWrittenCallback);
00273     //_ble.securityManager().onPasskeyDisplay(this, &SMDevice::passkeyDisplayCallback);
00274     //_ble.securityManager().onSecuritySetupCompleted(this, &SMDevice::securitySetupCompletedCallback);
00275 
00276     /* start test in 500 ms */
00277     _event_queue.call_in(500, this, &SMDevice::start);
00278 }
00279 
00280 /** This is called by Gap to notify the application we connected */
00281 //void SMDevice::on_connect(const Gap::ConnectionCallbackParams_t *connection_event);
00282 
00283 /** This is called by Gap to notify the application we disconnected,
00284  *  in our case it ends the demonstration. */
00285 void SMDevice::on_disconnect(const Gap::DisconnectionCallbackParams_t *event)
00286 {
00287     dbg_printf(LOG, "Disconnected\r\n");
00288 #ifndef DEMO_BLE_SECURITY
00289     dbg_printf(LOG, "Restarting advertising...\r\n");
00290     _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
00291 #endif
00292     isConnected = false;
00293     _event_queue.call(this, &SMDevice::setNextCommand, BLE_CMD_DISCONNECT);
00294 }
00295 
00296 /** End demonstration unexpectedly. Called if timeout is reached during advertising,
00297  * scanning or connection initiation */
00298 void SMDevice::on_timeout(const Gap::TimeoutSource_t source)
00299 {
00300     dbg_printf(LOG, "Unexpected timeout - aborting\r\n");
00301     _event_queue.break_dispatch();
00302 }
00303 
00304 /** Schedule processing of events from the BLE in the event queue. */
00305 void SMDevice::schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
00306 {
00307     _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
00308 };
00309 
00310 /** Echo received data back                                       */
00311 void SMDevice::EchoBleUartReceived()
00312 {
00313     uart->writeString(buffer);
00314     uart->writeString("\n");    //flushes uart output buffer and sends data
00315 }
00316 
00317 
00318 /** Send data aynchronously using BLE                                       */
00319 void SMDevice::sendBLEUartData(const uint8_t * buf, int len)
00320 {
00321     //gapState.connected
00322     if(isConnected){    
00323         uart->write(buf, len);
00324         //uart->writeString("\n");    //flushes uart output buffer and sends data
00325     }
00326     else
00327     {
00328         dbg_printf(LOG, "BLE not connected\r\n");
00329     }
00330 }
00331 
00332 
00333 /**
00334  * This callback allows the UARTService to receive updates.
00335  *
00336  * @param[in] params
00337  *     Information about the characterisitc being updated.
00338  */
00339 void SMDevice::onDataWrittenCallback(const GattWriteCallbackParams *params) {
00340     if ((uart != NULL) && (params->handle == uart->getTXCharacteristicHandle())) {
00341         uint16_t bytesRead = params->len;
00342 
00343         dbg_printf(LOG, "received %u bytes\n\r ", bytesRead);
00344 
00345         if(bytesRead >= 255){
00346             dbg_printf(LOG, "Overflow command %u n\r ", bytesRead);
00347             bytesRead = 255;
00348         }
00349 
00350         unsigned index = 0;
00351         for (; index < bytesRead; index++) {
00352             buffer[index] = params->data[index];
00353         }
00354 
00355         buffer[index++] = 0;
00356         at_data_resp = new ble_at_msg_t;
00357         at_data_resp->dataLen = params->len;
00358         // first set buffer to zeroes
00359         //memset(at_data_resp->buffer, 0x00, sizeof(at_data_resp->buffer));
00360         memcpy(at_data_resp->buffer, params->data, params->len);
00361         at_data_resp->buffer[params->len] = NULL;
00362         at_data_resp->at_resp = AT_BLE_RESPONSE;
00363         dbg_printf(LOG, "Data : %s : len = %d",(char *)at_data_resp->buffer, at_data_resp->dataLen);
00364         dbg_printf(LOG, "\r\n");
00365         dbg_printf(LOG, "Data : %s : len = %d",buffer, params->len);
00366         dbg_printf(LOG, "\r\n");
00367         /* directly queue received data */
00368         _event_queue.call(this, &SMDevice::sendATresponseBytes, AT_BLE_RESPONSE);
00369         /* start echo in 50 ms */
00370         _event_queue.call_in(50, this, &SMDevice::EchoBleUartReceived);
00371         //_event_queue.call(EchoBleUartReceived);
00372 
00373     }
00374 }
00375 
00376 
00377 
00378  
00379 /** Blink LED to show we're running */
00380 void SMDevice::blink(void)
00381 {
00382     _led1 = !_led1;
00383 }
00384 
00385 
00386 void SMDevice::reportGapState()
00387 {
00388      //Gap::GapState_t gapState = _ble.gap().getState();
00389      char connStr[20] = " Not Connected ";
00390      char advStr[20] = " Not Advertising ";
00391      //char devName[20] = "";
00392      //if(gapState.advertising){
00393      if(_ble.gap().isAdvertisingActive(ble::LEGACY_ADVERTISING_HANDLE)){
00394          strncpy(advStr, " Advertising ", 20);
00395      }
00396      if(isConnected){
00397          strncpy(connStr, " Connected ", 20);
00398      }
00399      dbg_printf(LOG, "\n Advertising Status = %s\n Connection Status = %s\n", advStr, connStr);
00400      
00401 }
00402 
00403 
00404 /** A peripheral device will advertise, accept the connection and request
00405  * a change in link security. */
00406 SMDevicePeripheral::SMDevicePeripheral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address, 
00407                                        MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool, 
00408                                        Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue, 
00409                                        MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool, 
00410                                        Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue, 
00411                                        ble_config_t *ble_config)
00412         : SMDevice(ble, event_queue, peer_address, 
00413                    aT2BleDatamPool, aT2BleDataQueue, 
00414                    ble2ATDatamPool, ble2ATDataQueue, 
00415                    ble_config) { }
00416 
00417 void SMDevicePeripheral::start()
00418 {
00419     /* Set up and start advertising */
00420 
00421     ble_error_t error;
00422     GapAdvertisingData advertising_data;
00423 
00424     /* add advertising flags */
00425     advertising_data.addFlags(GapAdvertisingData::LE_GENERAL_DISCOVERABLE
00426                               | GapAdvertisingData::BREDR_NOT_SUPPORTED);
00427 
00428     /* add device name */
00429     advertising_data.addData(
00430         GapAdvertisingData::COMPLETE_LOCAL_NAME,
00431         (const uint8_t *)ble_config->deviceName,
00432         strlen(ble_config->deviceName)
00433         );
00434     /* Setup primary service */
00435     uart = new UARTService(_ble);
00436 
00437 
00438     /* add device name */
00439     error = advertising_data.addData(
00440         GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS ,
00441         (const uint8_t *)UARTServiceUUID_reversed,
00442         sizeof(sizeof(UARTServiceUUID_reversed))
00443         );
00444     /* setup advertising */
00445     //error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00446     //ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
00447     //error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00448     /* set up the services that can be discovered */
00449     //error = _ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
00450     
00451 
00452     //error = _ble.gap().setAdvertisingPayload(advertising_data);
00453 
00454     if (error) {
00455         dbg_printf(LOG, "Error during Gap::setAdvertisingPayload\r\n");
00456         return;
00457     }
00458 
00459     /* advertise to everyone */
00460     _ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00461     /* how many milliseconds between advertisements, lower interval
00462      * increases the chances of being seen at the cost of more power */
00463     //_ble.gap().setAdvertisingInterval(20);
00464     //_ble.gap().setAdvertisingTimeout(0);
00465     _ble.gap().setAdvertisingInterval(ble_config->advInterval); /* setting in ble_config */
00466     _ble.gap().setAdvertisingTimeout(ble_config->advTimeout);   /* setting in ble_config */
00467 
00468     error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
00469 
00470     if (error) {
00471         dbg_printf(LOG, "Error during Gap::startAdvertising.\r\n");
00472         return;
00473     }
00474 
00475     dbg_printf(LOG, "Please connect to device\r\n");
00476 
00477     /** This tells the stack to generate a pairingRequest event
00478      * which will require this application to respond before pairing
00479      * can proceed. Setting it to false will automatically accept
00480      * pairing. */
00481     _ble.securityManager().setPairingRequestAuthorisation(true);
00482 }
00483 
00484 /** This is called by Gap to notify the application we connected,
00485  *  in our case it immediately requests a change in link security */
00486 void SMDevicePeripheral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
00487 {
00488     ble_error_t error;
00489 
00490     /* remember the device that connects to us now so we can connect to it
00491      * during the next demonstration */
00492     memcpy(_peer_address, connection_event->peerAddr, sizeof(_peer_address));
00493 
00494     dbg_printf(LOG, "Connected to: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
00495             _peer_address[5], _peer_address[4], _peer_address[3],
00496             _peer_address[2], _peer_address[1], _peer_address[0]);
00497 
00498     /* store the handle for future Security Manager requests */
00499     _handle = connection_event->handle;
00500 
00501     /* Request a change in link security. This will be done
00502      * indirectly by asking the master of the connection to
00503      * change it. Depending on circumstances different actions
00504      * may be taken by the master which will trigger events
00505      * which the applications should deal with. */
00506     error = _ble.securityManager().setLinkSecurity(
00507         _handle,
00508         SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM
00509     );
00510 
00511     if (error) {
00512         dbg_printf(LOG, "Error during SM::setLinkSecurity %d\r\n", error);
00513         return;
00514     }
00515     dbg_printf(LOG, "SM::setLinkSecurity setup\r\n");
00516     isConnected = true;
00517     _event_queue.call(this, &SMDevicePeripheral::setNextCommand, BLE_CMD_CONNECT);
00518 }
00519 
00520 void SMDevicePeripheral::stopAdvertising()
00521 {
00522     if (_ble.hasInitialized()) {
00523         ble_error_t error;
00524         error = _ble.gap().stopAdvertising(ble::LEGACY_ADVERTISING_HANDLE);;
00525         if(error){
00526             dbg_printf(LOG, " Error stopping advertising...\r\n");
00527             return;
00528         }
00529         dbg_printf(LOG, "Stopping advertising...\r\n");
00530         //_event_queue.break_dispatch();
00531     }
00532 }
00533 void SMDevicePeripheral::startAdvertising()
00534 {
00535     if (_ble.hasInitialized()) {
00536         ble_error_t error;
00537         error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
00538         if(error){
00539             dbg_printf(LOG, " Error Restarting advertising...\r\n");
00540             return;
00541         }
00542         dbg_printf(LOG, "Restarting advertising...\r\n");
00543         //_event_queue.break_dispatch();
00544     }
00545 }
00546 
00547 
00548 void SMDevicePeripheral::sendConnectionResponses()
00549 {
00550     // send ACL Connected +UUBTACLC
00551     at_data_resp = new ble_at_msg_t;
00552     char * respStr = (char *)at_data_resp->buffer;
00553     sprintf(respStr, "\r\n+UUBTACLC:%d,%d,%02X%02X%02X%02X%02X%02X\r\n", 
00554             DEFAULT_BTLE_CHANNEL, GATT_TYPE,_peer_address[5] ,_peer_address[4],
00555             _peer_address[3],_peer_address[2],_peer_address[1],_peer_address[0]);
00556     at_data_resp->dataLen = strlen(respStr); // get bytes total
00557     sendATresponseBytes(AT_BLE_EVENT);
00558     
00559     // send +UUDPC
00560     at_data_resp = new ble_at_msg_t;
00561     respStr = (char *)at_data_resp->buffer;
00562     sprintf(respStr, "\r\n+UUDPC:%d,%d,%d,%02X%02X%02X%02X%02X%02X,%d\r\n", 
00563             BTLE_PEER_HANDLE, BLE_CONNECTION, BLE_UUID_PROFILE,_peer_address[5] ,
00564             _peer_address[4], _peer_address[3],_peer_address[2],_peer_address[1],
00565             _peer_address[0], BLE_FRAME_SIZE);
00566     at_data_resp->dataLen = strlen(respStr); // get bytes total
00567     sendATresponseBytes(AT_BLE_EVENT);
00568     
00569     // send connect event
00570     at_data_resp = new ble_at_msg_t;
00571     at_data_resp->dataLen = 10; // 10 bytes total
00572     int idx = 0;
00573     // connect type BLE = 0x01
00574     at_data_resp->buffer[idx++] = 0x01;
00575     // Serial Port Service BLE profile = 0x0E (14)
00576     at_data_resp->buffer[idx++] = 0x0E;
00577     // copy peer device address
00578     memcpy(&at_data_resp->buffer[idx], _peer_address, sizeof(_peer_address));
00579     idx+=sizeof(_peer_address);
00580     // frame size 0x0166
00581     at_data_resp->buffer[idx++] = 0x01;
00582     at_data_resp->buffer[idx++] = 0x66;
00583     sendATresponseBytes(BLE_CONNECT_EVENT);
00584 }
00585 
00586 
00587 void SMDevicePeripheral::sendDisconnectionResponses()
00588 {
00589     // send ACL disconnected +UUBTACLD
00590     at_data_resp = new ble_at_msg_t;
00591     char * respStr = (char *)at_data_resp->buffer;
00592     sprintf(respStr, "\r\n+UUBTACLD:%d\r\n", DEFAULT_BTLE_CHANNEL);
00593     at_data_resp->dataLen = strlen(respStr); // get bytes total
00594     sendATresponseBytes(AT_BLE_EVENT);
00595     
00596     // send +UUDPD
00597     at_data_resp = new ble_at_msg_t;
00598     respStr = (char *)at_data_resp->buffer;
00599     sprintf(respStr, "\r\n+UUDPD:%d\r\n", BTLE_PEER_HANDLE);
00600     at_data_resp->dataLen = strlen(respStr); // get bytes total
00601     sendATresponseBytes(AT_BLE_EVENT);
00602     
00603     // send connect event
00604     at_data_resp = new ble_at_msg_t;
00605     sendATresponseBytes(BLE_DISCONNECT_EVENT);
00606 }
00607 
00608 
00609 
00610 void SMDevicePeripheral::processQueues()
00611 {
00612     dequeueATdataResponse();
00613     switch(bleCmd)
00614     {
00615     case BLE_CMD_NONE:
00616         break;
00617     case BLE_CMD_CONFIG:
00618         _aT2BleDatamPool->free(data_msg);
00619         bleCmd = BLE_CMD_NONE;
00620         break;
00621     case BLE_CMD_CONNECT:
00622         sendConnectionResponses();
00623         bleCmd = BLE_CMD_NONE;
00624         break;
00625     case BLE_CMD_DISCONNECT:
00626     {
00627         sendDisconnectionResponses();
00628         bleCmd = BLE_CMD_NONE;
00629         break;
00630     }
00631     case BLE_CMD_MAC_ADDR:
00632     {
00633         // send BLE MAC_ADDR
00634         _aT2BleDatamPool->free(data_msg);
00635         at_data_resp = new ble_at_msg_t;
00636         char * respStr = (char *)at_data_resp->buffer;
00637         /* print device address */
00638         Gap::AddressType_t addr_type;
00639         Gap::Address_t addr;
00640         _ble.gap().getAddress(&addr_type, addr);
00641         //dbg_printf(LOG, "Device address: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
00642         //       addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
00643         sprintf(respStr, "\r\n%s%d,%02X%02X%02X%02X%02X%02XOK\r\n", LOCAL_ADDRESS_RESP
00644                                                                 , BLE_IF_ID
00645                                                                 , addr[5]
00646                                                                 , addr[4]
00647                                                                 , addr[3]
00648                                                                 , addr[2]
00649                                                                 , addr[1]
00650                                                                 , addr[0]
00651                                                                 );
00652         at_data_resp->dataLen = strlen(respStr); // get bytes total
00653         sendATresponseBytes(AT_BLE_MAC_RESP);
00654         bleCmd = BLE_CMD_NONE;
00655         break;
00656     }
00657     case BLE_CMD_DEVICE_NAME:
00658     {
00659         // send BLE_CMD_DEVICE_NAME
00660         _aT2BleDatamPool->free(data_msg);
00661         at_data_resp = new ble_at_msg_t;
00662         char * respStr = (char *)at_data_resp->buffer;
00663         sprintf(respStr, "\r\n%s%sOK\r\n", BLE_DEVICE_NAME_RESP, ble_config->deviceName);
00664         at_data_resp->dataLen = strlen(respStr); // get bytes total
00665         sendATresponseBytes(AT_BLE_NAME_RESP);
00666         bleCmd = BLE_CMD_NONE;
00667         break;
00668     }
00669     case BLE_CMD_SEND_RX_DATA_2AT:
00670         sendATresponseBytes(AT_BLE_RESPONSE);
00671         bleCmd = BLE_CMD_NONE;
00672         break;
00673     case BLE_CMD_SEND_AT_DATA_2BLE:
00674         sendBLEUartData(data_msg->buffer, data_msg->dataLen);
00675         _aT2BleDatamPool->free(data_msg);
00676         bleCmd = BLE_CMD_NONE;
00677         break;
00678     default:
00679         _aT2BleDatamPool->free(data_msg);
00680         bleCmd = BLE_CMD_NONE;
00681         break;
00682     }
00683     
00684 }
00685 
00686 
00687 bool SMDevicePeripheral::queueBleDataResponse(ble_at_msg_t at_resp)
00688 {
00689     ble_at_msg_t *atData = _ble2ATDatamPool->alloc();
00690     if(atData == NULL) return false; // queue full;
00691     atData->at_resp        = at_resp.at_resp;
00692     atData->dataLen        = at_resp.dataLen;
00693     memcpy(atData->buffer, at_resp.buffer, at_resp.dataLen);
00694     _ble2ATDataQueue->put(atData);
00695     dbg_printf(LOG, "[BLE-MAN] queued data size = %d : at_resp = %d\n", at_resp.dataLen, at_resp.at_resp);
00696     return true;
00697 }
00698 
00699 
00700 bool SMDevicePeripheral::dequeueATdataResponse(){
00701     if(bleCmd != BLE_CMD_NONE) return false; // busy
00702     osEvent evt = _aT2BleDataQueue->get(0);
00703     if(evt.status == osEventMessage){
00704         data_msg = (at_ble_msg_t*)evt.value.p;
00705         setNextCommand(data_msg->ble_cmd);
00706         //_wiFi2ATDatamPool->free(data_msg);
00707     }
00708     return true;
00709 }
00710 
00711 void  SMDevicePeripheral::sendATresponseBytes(at_cmd_resp_t at_cmd)
00712 {
00713     //at_data_resp = new ble_at_msg_t;
00714     // package and send on BLE data queue    
00715     // set string length 
00716     //at_data_resp->dataLen = len;
00717     // copy data
00718     //memcpy(at_data_resp->buffer, buf, len);
00719     // copy response type
00720     at_data_resp->at_resp = at_cmd;
00721     bool queueResult = true;
00722     int wait_count = 0;
00723     queueResult = queueBleDataResponse(*at_data_resp);
00724     delete at_data_resp;
00725     at_data_resp = NULL;
00726     dbg_printf(LOG, "[BLE-MAN] sendATresponseBytes completed successfully\r\n");
00727 }                                            
00728 
00729 bool SMDevicePeripheral::setNextCommand(ble_cmd_t cmd)
00730 {
00731     dbg_printf(LOG, "\n [BLE-MAN] About to set next BLE manager command to %d\n", cmd);
00732     if(bleCmd == BLE_CMD_NONE){
00733         bleCmd = cmd;
00734         return true; // success
00735     }
00736     dbg_printf(LOG, "\n [BLE-MAN] Busy : current state = %d \n", bleCmd);
00737     return false; // BleManager busy
00738 }
00739 
00740 /** A central device will scan, connect to a peer and request pairing. */
00741 
00742 SMDeviceCentral::SMDeviceCentral(BLE &ble, events::EventQueue &event_queue, BLEProtocol::AddressBytes_t &peer_address, 
00743                                  MemoryPool<at_ble_msg_t, PQDSZ_BLE> *aT2BleDatamPool, 
00744                                  Queue<at_ble_msg_t, PQDSZ_BLE> *aT2BleDataQueue, 
00745                                  MemoryPool<ble_at_msg_t, PQDSZ_BLE> *ble2ATDatamPool, 
00746                                  Queue<ble_at_msg_t, PQDSZ_BLE> *ble2ATDataQueue, 
00747                                  ble_config_t *ble_config)
00748     : SMDevice(ble, event_queue, peer_address, 
00749                aT2BleDatamPool, aT2BleDataQueue, 
00750                ble2ATDatamPool, ble2ATDataQueue, 
00751                ble_config) { };
00752 
00753 void SMDeviceCentral::start()
00754 {
00755     /* start scanning and attach a callback that will handle advertisements
00756      * and scan requests responses */
00757     ble_error_t error = _ble.gap().startScan(this, &SMDeviceCentral::on_scan);
00758 
00759     dbg_printf(LOG, "Please advertise\r\n");
00760 
00761     dbg_printf(LOG, "Scanning for: %02x:%02x:%02x:%02x:%02x:%02x\r\n",
00762            _peer_address[5], _peer_address[4], _peer_address[3],
00763            _peer_address[2], _peer_address[1], _peer_address[0]);
00764 
00765     if (error) {
00766         dbg_printf(LOG, "Error during Gap::startScan %d\r\n", error);
00767         return;
00768     }
00769 }
00770 
00771 /** Look at scan payload to find a peer device and connect to it */
00772 void SMDeviceCentral::on_scan(const Gap::AdvertisementCallbackParams_t *params)
00773 {
00774     /* don't bother with analysing scan result if we're already connecting */
00775     if (_is_connecting) {
00776         return;
00777     }
00778 
00779     /* connect to the same device that connected to us */
00780     if (memcmp(params->peerAddr, _peer_address, sizeof(_peer_address)) == 0) {
00781 
00782         ble_error_t error = _ble.gap().connect(
00783             params->peerAddr, params->peerAddrType,
00784             NULL, NULL
00785         );
00786 
00787         if (error) {
00788             dbg_printf(LOG, "Error during Gap::connect %d\r\n", error);
00789             return;
00790         }
00791 
00792         dbg_printf(LOG, "Connecting... ");
00793 
00794         /* we may have already scan events waiting
00795          * to be processed so we need to remember
00796          * that we are already connecting and ignore them */
00797         _is_connecting = true;
00798 
00799         return;
00800     }
00801 }
00802 
00803 /** This is called by Gap to notify the application we connected,
00804  *  in our case it immediately request pairing */
00805 void SMDeviceCentral::on_connect(const Gap::ConnectionCallbackParams_t *connection_event)
00806 {
00807     ble_error_t error;
00808 
00809     /* store the handle for future Security Manager requests */
00810     _handle = connection_event->handle;
00811 
00812     /* in this example the local device is the master so we request pairing */
00813     error = _ble.securityManager().requestPairing(_handle);
00814 
00815     dbg_printf(LOG, "Connected\r\n");
00816 
00817     if (error) {
00818         dbg_printf(LOG, "Error during SM::requestPairing %d\r\n", error);
00819         return;
00820     }
00821 
00822     /* upon pairing success the application will disconnect */
00823 }
00824 
00825 
00826 
00827 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
00828 bool create_filesystem()
00829 {
00830     static LittleFileSystem fs("fs");
00831 
00832     /* replace this with any physical block device your board supports (like an SD card) */
00833     static HeapBlockDevice bd(4096, 256);
00834 
00835     int err = bd.init();
00836 
00837     if (err) {
00838         return false;
00839     }
00840 
00841     err = bd.erase(0, bd.size());
00842 
00843     if (err) {
00844         return false;
00845     }
00846 
00847     err = fs.mount(&bd);
00848 
00849     if (err) {
00850         /* Reformat if we can't mount the filesystem */
00851         dbg_printf(LOG, "No filesystem found, formatting...\r\n");
00852 
00853         err = fs.reformat(&bd);
00854 
00855         if (err) {
00856             return false;
00857         }
00858     }
00859 
00860     return true;
00861 }
00862 #endif //MBED_CONF_APP_FILESYSTEM_SUPPORT
00863 #ifdef BLE_SECURITY_MAIN
00864 int main()
00865 {
00866     BLE& ble = BLE::Instance();
00867     events::EventQueue queue;
00868 
00869 #if MBED_CONF_APP_FILESYSTEM_SUPPORT
00870     /* if filesystem creation fails or there is no filesystem the security manager
00871      * will fallback to storing the security database in memory */
00872     if (!create_filesystem()) {
00873         dbg_printf(LOG, "Filesystem creation failed, will use memory storage\r\n");
00874     }
00875 #endif
00876 
00877     while(1) {
00878         {
00879             dbg_printf(LOG, "\r\n PERIPHERAL \r\n\r\n");
00880             SMDevicePeripheral peripheral(ble, queue, peer_address);
00881             peripheral.run();
00882         }
00883 
00884         {
00885             dbg_printf(LOG, "\r\n CENTRAL \r\n\r\n");
00886             SMDeviceCentral central(ble, queue, peer_address);
00887             central.run();
00888         }
00889     }
00890 
00891     return 0;
00892 }
00893 #endif