/********************************************************************* * @fn oadManagerCharDiscovery * * @brief OAD Characteristics service discovery. * * @return none */ static void oadManagerCharDiscovery(void) { attReadByTypeReq_t req; req.startHandle = oadSvcStartHdl; req.endHandle = oadSvcEndHdl; req.type.len = ATT_UUID_SIZE; if ( oadManagerDiscIdx == 0 ) { uint8 oadCharUUID[ATT_UUID_SIZE] = { TI_BASE_UUID_128( OAD_IMG_IDENTIFY_UUID ) }; (void)osal_memcpy(req.type.uuid, oadCharUUID, ATT_UUID_SIZE); } else { uint8 oadCharUUID[ATT_UUID_SIZE] = { TI_BASE_UUID_128( OAD_IMG_BLOCK_UUID ) }; (void)osal_memcpy(req.type.uuid, oadCharUUID, ATT_UUID_SIZE); } if (GATT_DiscCharsByUUID(oadManagerConnHandle, &req, oadManagerTaskId) != SUCCESS) { (void)osal_set_event(oadManagerTaskId, CHAR_DISCOVERY_EVT); } }
// Discover Chars by UUID void BLECtrlDiscoverCharsByUUID16(uint16 connHandle, uint8 task_id, uint8* uuid) { attReadByTypeReq_t req; req.startHandle = 0x0001; req.endHandle = 0xFFFF; req.type.len = 16; VOID osal_memcpy(req.type.uuid, uuid, 16); GATT_DiscCharsByUUID(connHandle, &req, task_id); // TODO verify uuid_len == 2 }
// Discover Chars void BLECtrlDiscoverChars(uint16 connHandle, uint8 task_id) { attReadByTypeReq_t req; req.startHandle = blectrlServStartHdl; req.endHandle = blectrlServEndHdl; req.type.len = blectrlCharUUIDLen; VOID osal_memcpy( req.type.uuid, blectrlCharUUID, blectrlCharUUIDLen ); GATT_DiscCharsByUUID(connHandle, &req, task_id); // TODO verify uuid_len == 2 }
static void hidappProcessGATTMsg( gattMsgEvent_t *pPkt ) { // Build the message first switch ( pPkt->method ) { case ATT_HANDLE_VALUE_NOTI: // First try to send out pending HID report if ( reportRetries > 0 ) { hidappSendInReport( &lastInReport ); reportRetries = 0; osal_stop_timerEx( hidappTaskId, HIDAPP_EVT_REPORT_RETRY ); } // Send incoming HID report if ( hidappSendInReport( &(pPkt->msg.handleValueNoti) ) == FALSE ) { // Save report for retries later osal_memcpy( &lastInReport, &(pPkt->msg.handleValueNoti), sizeof( attHandleValueNoti_t ) ); reportRetries = 1; osal_start_timerEx( hidappTaskId, HIDAPP_EVT_REPORT_RETRY, HIDAPP_INPUT_RETRY_TIMEOUT ); } break; case ATT_FIND_BY_TYPE_VALUE_RSP: // Response from GATT_DiscPrimaryServiceByUUID // Service found, store handles if ( pPkt->msg.findByTypeValueRsp.numInfo > 0 ) { serviceStartHandle = pPkt->msg.findByTypeValueRsp.handlesInfo[0].handle; serviceEndHandle = pPkt->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle; } // If procedure complete else if ( pPkt->hdr.status == bleProcedureComplete ) { if ( serviceStartHandle != 0 ) { if ( serviceToDiscover == GATT_SERVICE_UUID ) { // Begin the search for characteristic handle of the service readReq.startHandle = serviceStartHandle; readReq.endHandle = serviceEndHandle; readReqType.len = 2; readReqType.uuid[0] = LO_UINT16(SERVICE_CHANGED_UUID); readReqType.uuid[1] = HI_UINT16(SERVICE_CHANGED_UUID); readReq.type = readReqType; GATT_DiscCharsByUUID(connHandle, &readReq, hidappTaskId ); } else if ( serviceToDiscover == HID_SERVICE_UUID ) { // Discover all characteristics GATT_DiscAllChars( connHandle, serviceStartHandle, serviceEndHandle, hidappTaskId ); } } } break; case ATT_READ_BY_TYPE_RSP: // Response from Discover all Characteristics. // Success indicates packet with characteristic discoveries. if ( pPkt->hdr.status == SUCCESS ) { attReadByTypeRsp_t rsp = pPkt->msg.readByTypeRsp; uint8 idx = 0; if ( serviceToDiscover == GATT_SERVICE_UUID ) { // We have discovered the GATT Service Characteristic handle uint8 low = LO_UINT16(pPkt->msg.readByTypeRsp.dataList[3]); uint8 high = HI_UINT16(pPkt->msg.readByTypeRsp.dataList[4]); serviceChangeHandle = BUILD_UINT16(low, high); // Break to skip next part, it doesn't apply here break; } // Search characteristics for those with notification permissions. while( idx < ((rsp.numPairs * rsp.len ) - 1)) { // Check permissions of characteristic for notification permission if ( (rsp.dataList[idx+2] & GATT_PROP_NOTIFY ) ) { uint16* pHandle = (mouseCharHandle == GATT_INVALID_HANDLE) ? &mouseCharHandle : &keyCharHandle ; if ( pHandle == &keyCharHandle && consumerCtrlCharHandle == GATT_INVALID_HANDLE ) { pHandle = ( keyCharHandle == GATT_INVALID_HANDLE ) ? &keyCharHandle : &consumerCtrlCharHandle; } if ( *pHandle == GATT_INVALID_HANDLE ) { *pHandle = BUILD_UINT16( rsp.dataList[idx+3], rsp.dataList[idx+4] ); } } idx += rsp.len; } } // This indicates that there is no more characteristic data // to be discovered within the given handle range. else if ( pPkt->hdr.status == bleProcedureComplete ) { if ( serviceToDiscover == GATT_SERVICE_UUID ) { // Begin Service Discovery of HID Service serviceToDiscover = HID_SERVICE_UUID; hidappDiscoverService( connHandle, HID_SERVICE_UUID ); // Break to skip next part, it doesn't apply yet. break; } if ( enableCCCDs == TRUE ) { mouseCCCHandle = mouseCharHandle + 1; // Begin configuring the characteristics for notifications hidappEnableNotification( connHandle, mouseCCCHandle ); } else { serviceDiscComplete = TRUE; } } break; case ATT_WRITE_RSP: if ( pPkt->hdr.status == SUCCESS && !serviceDiscComplete ) { uint16 handle = ( keyCCCHandle == GATT_INVALID_HANDLE ) ? ( keyCCCHandle = keyCharHandle + 1 ) : ( consumerCtrlCCCHandle = consumerCtrlCharHandle + 1 ); hidappEnableNotification( connHandle, handle ); if ( consumerCtrlCCCHandle != GATT_INVALID_HANDLE) { serviceDiscComplete = TRUE; } } break; // Service Change indication case ATT_HANDLE_VALUE_IND: // Note: this logic assumes that the only indications that will be sent // will come from that GATT Service Changed Characteristic if ( pPkt->hdr.status == SUCCESS ) { serviceChange = CHANGE_OCCURED; // Acknowledge receipt of indication ATT_HandleValueCfm( pPkt->connHandle ); // Handles in server have changed while devices are connected if ( ( gapBondMgrState == PAIRED_BONDED_STATE ) && ( serviceChangeHandle == pPkt->msg.handleValueInd.handle ) ) { // Begin Service Discovery of HID Service serviceToDiscover = HID_SERVICE_UUID; hidappDiscoverService( connHandle, HID_SERVICE_UUID ); serviceChange = NO_CHANGE; } } break; default: // Unknown event break; } }