this is using the mbed os version 5-13-1
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Wed Jul 13 2022 05:40:26 by
1.7.2