/** * The nRF transport has its own 3-byte representation of a UUID. If the user- * specified UUID is 128-bits wide, then the UUID base needs to be added to the * soft-device and converted to a 3-byte handle before being used further. This * function is responsible for this translation of user-specified UUIDs into * nRF's representation. * * @param[in] uuid * user-specified UUID * @return nRF * 3-byte UUID (containing a type and 16-bit UUID) representation * to be used with SVC calls. */ ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid) { ble_uuid_t nordicUUID; nordicUUID.uuid = uuid.getShortUUID(); nordicUUID.type = BLE_UUID_TYPE_UNKNOWN; /* to be set below */ if (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) { nordicUUID.type = BLE_UUID_TYPE_BLE; } else { if (!lookupConvertedUUIDTable(uuid.getBaseUUID(), &nordicUUID.type)) { nordicUUID.type = custom_add_uuid_base(uuid.getBaseUUID()); addToConvertedUUIDTable(uuid.getBaseUUID(), nordicUUID.type); } } return nordicUUID; }
void BlueNRGGattClient::primaryServicesCB(Gap::Handle_t connectionHandle, uint8_t event_data_length, uint8_t attribute_data_length, uint8_t *attribute_data_list) { GattAttribute::Handle_t startHandle, endHandle; UUID uuid; uint8_t i, offset, numAttr; /* avoid compiler warnings about unused variables */ (void)connectionHandle; numAttr = (event_data_length - 1) / attribute_data_length; offset = 0; for (i=0; i<numAttr; i++) { startHandle = attribute_data_list[offset]; endHandle = attribute_data_list[offset+2]; // UUID Type if (attribute_data_length == 6) { PRINTF("UUID_TYPE_16\n\r"); uuid = attribute_data_list[offset+5]<<8|attribute_data_list[offset+4]; PRINTF("S UUID-%X attrs[%u %u]\r\n", uuid.getShortUUID(), startHandle, endHandle); } else { PRINTF("UUID_TYPE_128\n\r"); uuid.setupLong(attribute_data_list+offset+4); PRINTF("S UUID-"); #ifdef DEBUG const uint8_t *longUUIDBytes = uuid.getBaseUUID(); for (unsigned j = 0; j < UUID::LENGTH_OF_LONG_UUID; j++) { PRINTF("%02x", longUUIDBytes[j]); } #endif PRINTF(" attrs[%u %u]\r\n", startHandle, endHandle); } PRINTF("Setup serviceIndex = %d\n\r", _numServices); discoveredService[_numServices].setup(uuid, startHandle, endHandle); if(serviceDiscoveryCallback) { if(_matchingServiceUUID == BLE_UUID_UNKNOWN || _matchingServiceUUID == discoveredService[_numServices].getUUID()) { serviceDiscoveryCallback(&discoveredService[_numServices]); } } _numServices++; offset += attribute_data_length; } PRINTF("!!!Service Discovery complete (numAttr=%u)!!!\n\r", numAttr); }
/** * Print the value of a UUID. */ static void print_uuid(const UUID &uuid) { const uint8_t *uuid_value = uuid.getBaseUUID(); // UUIDs are in little endian, print them in big endian for (size_t i = 0; i < uuid.getLen(); ++i) { printf("%02X", uuid_value[(uuid.getLen() - 1) - i]); } }
ble_error_t BlueNRGGattClient::launchServiceDiscovery(Gap::Handle_t connectionHandle, ServiceDiscovery::ServiceCallback_t sc, ServiceDiscovery::CharacteristicCallback_t cc, const UUID &matchingServiceUUID, const UUID &matchingCharacteristicUUIDIn) { PRINTF("launchServiceDiscovery\n\r"); tBleStatus ret; uint8_t uuid_type = UUID_TYPE_16; uint8_t short_uuid[2]; uint8_t *uuid = NULL; unsigned j; _connectionHandle = connectionHandle; serviceDiscoveryCallback = sc; characteristicDiscoveryCallback = cc; _matchingServiceUUID = matchingServiceUUID; _matchingCharacteristicUUIDIn = matchingCharacteristicUUIDIn; //reset services _numServices = 0; _numChars = 0; _servIndex = 0; for(j = 0; j < BLE_TOTAL_DISCOVERED_SERVICES; j++) { discoveredService[j].setup(BLE_UUID_UNKNOWN, GattAttribute::INVALID_HANDLE, GattAttribute::INVALID_HANDLE); } if(matchingServiceUUID == BLE_UUID_UNKNOWN) { // Wildcard: search for all services ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle); } else { uint8_t type = matchingServiceUUID.shortOrLong(); //PRINTF("AddService(): Type:%d\n\r", type); if(type == UUID::UUID_TYPE_SHORT) { STORE_LE_16(short_uuid, matchingServiceUUID.getShortUUID()); PRINTF("launchServiceDiscovery short_uuid=0x"); for(j = 0; j < 2; j++) { PRINTF("%02X", short_uuid[j]); } PRINTF("\n\r"); uuid_type = UUID_TYPE_16; uuid = short_uuid; } else if(type==UUID::UUID_TYPE_LONG) { uuid_type = UUID_TYPE_128; uuid = (unsigned char*)matchingServiceUUID.getBaseUUID(); /* PRINTF("launchServiceDiscovery base_uuid=0x"); for(j = 0; j < 16; j++) { PRINTF("%02X", uuid[j]); } PRINTF("\n\r"); */ } // search for specific service by UUID ret = aci_gatt_disc_prim_service_by_uuid((uint16_t)connectionHandle, uuid_type, uuid); //ret = aci_gatt_disc_all_prim_services((uint16_t)connectionHandle); } if(ret == BLE_STATUS_SUCCESS) { _currentState = GATT_SERVICE_DISCOVERY; } PRINTF("launchServiceDiscovery ret=%d\n\r", ret); return BLE_ERROR_NONE; }
void BlueNRGGattClient::serviceCharByUUIDCB(Gap::Handle_t connectionHandle, uint8_t event_data_length, uint16_t attr_handle, uint8_t *attr_value) { // Charac Properties(1), Charac Value Handle(2), Charac UUID(2/16) GattAttribute::Handle_t declHandle, valueHandle; UUID uuid; PRINTF("serviceCharByUUIDCB\n\r"); // UUID Type if (event_data_length == 7) { PRINTF("Char UUID_TYPE_16\n\r"); uuid = attr_value[4]<<8|attr_value[3]; PRINTF("C UUID-%X\r\n", uuid.getShortUUID()); } else { PRINTF("Char UUID_TYPE_128\n\r"); uuid.setupLong(attr_value+3); PRINTF("C UUID-"); #ifdef DEBUG const uint8_t *longUUIDBytes = uuid.getBaseUUID(); for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) { PRINTF("%02X", longUUIDBytes[i]); } PRINTF("\r\n"); #endif } // Properties DiscoveredCharacteristic::Properties_t p; p._broadcast = (props_mask[0] & attr_value[0]); p._read = (props_mask[1] & attr_value[0])>>1; p._writeWoResp = (props_mask[2] & attr_value[0])>>2; p._write = (props_mask[3] & attr_value[0])>>3; p._notify = (props_mask[4] & attr_value[0])>>4; p._indicate = (props_mask[5] & attr_value[0])>>5; p._authSignedWrite = (props_mask[6] & attr_value[0])>>6; PRINTF("p._broadcast=%d\n\r", p._broadcast); PRINTF("p._read=%d\n\r", p._read); PRINTF("p._writeWoResp=%d\n\r", p._writeWoResp); PRINTF("p._write=%d\n\r", p._write); PRINTF("p._notify=%d\n\r", p._notify); PRINTF("p._indicate=%d\n\r", p._indicate); PRINTF("p._authSignedWrite=%d\n\r", p._authSignedWrite); /* uint8_t props = attr_value[0]; PRINTF("CHAR PROPS: %d\n\r", props); */ // Handles declHandle = attr_handle; valueHandle = attr_value[1]; discoveredChar[_numChars].setup(this, connectionHandle, uuid, p, declHandle, valueHandle); if(characteristicDiscoveryCallback) { characteristicDiscoveryCallback(&discoveredChar[_numChars]); } _numChars++; }
void app_start(int, char *[]) { buffer = (uint8_t*)malloc(24); memset(buffer, 0, 24); console.attach(serialHandler); printf("{{end}}\r\n"); // setup buttons // button1.mode(PullUp); // Delay for initial pullup to take effect wait(.01); // button1.fall(button1ISR); // button2.mode(PullUp); // Delay for initial pullup to take effect wait(.01); // button2.fall(button2ISR); /*************************************************************************/ /*************************************************************************/ /* bluetooth le */ ble.init(); // security ble.securityManager().onSecuritySetupInitiated(securityInitiated); ble.securityManager().onSecuritySetupCompleted(securityCompleted); ble.securityManager().onLinkSecured(linkSecured); ble.securityManager().onSecurityContextStored(contextStored); ble.securityManager().onPasskeyDisplay(passkeyDisplay); // connection status handlers ble.gap().onConnection(whenConnected); ble.gap().onDisconnection(whenDisconnected); // set preferred connection parameters to lowest latency Gap::ConnectionParams_t fast; ble.gap().getPreferredConnectionParams(&fast); fast.minConnectionInterval = 16; // 20 ms fast.maxConnectionInterval = 32; // 40 ms fast.slaveLatency = 0; ble.gap().setPreferredConnectionParams(&fast); /* construct advertising beacon */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED|GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME) - 1); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, uuid.getBaseUUID(), uuid.getLen()); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(200); // Apple uses device name instead of beacon name ble.gap().setDeviceName((const uint8_t*) DEVICE_NAME); // ble setup complete - start advertising ble.gap().startAdvertising(); /*************************************************************************/ /*************************************************************************/ bts = new BlockTransferService(); btc = new BlockTransferClient(); watch = new Timer(); bts->init(uuid, SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK); #if 0 writeBlock.push_back(&writeBlockFragment2); writeBlock.push_back(&writeBlockFragment3); writeBlock.push_back(&writeBlockFragment4); #endif // set callback functions bts->setWriteAuthorizationCallback(blockServerWriteHandler, &receiveBlock); bts->setReadAuthorizationCallback(blockServerReadHandler); printf("BlockTransfer: %s %s %d\r\n", __DATE__, __TIME__, MAX_INDEX_SET_SIZE); }