CH58X/CH59X/CH32V20X主机枚举所有服务,MTU交互(多连接版)
前言:
现在提供的主机代码是直接通过从机的UUID去和指定的从机进行连接,获取对应特征值的handle值。只要能获取对应特征值的handle即可通信。
现在提供一种方式去获取对应的handle值进行通信。有时候在多连接的场景下需要对handle进行管理。
代码如下:
static void centralConnIistStartDiscovery_0(void) {centralConnList[CONNECT0_ITEM].svcStartHdl = centralConnList[CONNECT0_ITEM].svcEndHdl = centralConnList[CONNECT0_ITEM].charHdl =0; // centralSvcStartHdl = centralSvcEndHdl = centralCharHdl = 0; // centralDiscState = BLE_DISC_STATE_SVC; centralConnList[CONNECT0_ITEM].discState = BLE_DISC_STATE_SVC; uint8_t ret = 0; ret = GATT_DiscAllPrimaryServices(centralConnList[CONNECT0_ITEM].connHandle, centralTaskId); printf("GATT_DiscAllPrimaryServices ret = %x\n", ret); if(ret ==0) { tmos_stop_task(centralConnList[CONNECT0_ITEM].taskID, START_SVC_DISCOVERY_EVT); } } static void centralGATTDiscoveryEvent(uint8_t connItem, gattMsgEvent_t *pMsg) { attReadByTypeReq_t req; if(centralConnList[connItem].discState == BLE_DISC_STATE_SVC) { // Service found, store handles if(pMsg->method == ATT_READ_BY_GRP_TYPE_RSP &&//ATT_FIND_BY_TYPE_VALUE_RSP && pMsg->msg.findByTypeValueRsp.numInfo > 0) { #if 0 for(uint16_t i = 0; i < pMsg->msg.readByGrpTypeRsp.numGrps; i++) { // uuid printf("uuid = %x", BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +4], \ pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +5])); //Primary Service UUID Length printf("%02d bit x",pMsg->msg.readByGrpTypeRsp.len - 4); // printf("att len = %d\n", pMsg->msg.readByGrpTypeRsp.len); printf("start handle:%04x",BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i],\ pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +1])); // Attribute End Group Handle printf("end handle:%04x\r\n",BUILD_UINT16( pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +2], \ pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i +3])); } #endif } if((pMsg->method == ATT_READ_BY_GRP_TYPE_RSP && pMsg->hdr.status == bleProcedureComplete) || (pMsg->method == ATT_ERROR_RSP)) { // Discover characteristic centralConnList[connItem].discState = BLE_DISC_STATE_CHAR; uint8_t ret = GATT_DiscAllChars(centralConnList[connItem].connHandle,0x01,0xFFFF,centralTaskId); PRINT("GATT_DiscAllChars:%02x\r\n",ret); } } else if(centralConnList[connItem].discState == BLE_DISC_STATE_CHAR) { // Characteristic found, store handle if(pMsg->method == ATT_READ_BY_TYPE_RSP && pMsg->msg.readByTypeRsp.numPairs > 0) { for(unsigned char i = 0; i < pMsg->msg.readByTypeRsp.numPairs ; i++) { //characteristic properties uint8_t char_properties = pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 2]; uint16_t char_value_handle = BUILD_UINT16(pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i+3], \ pMsg->msg.readByTypeRsp.pDataList[pMsg->msg.readByTypeRsp.len * i + 4]); //characteristic uuid length uint8_t char_uuid_length = pMsg->msg.readByGrpTypeRsp.len - 5; //uuid uint8_t *char_uuid = &(pMsg->msg.readByGrpTypeRsp.pDataList[pMsg->msg.readByGrpTypeRsp.len * i + 5]); PRINT("______________________________\n"); PRINT("char_uuid :"); for(uint8_t i = 0; i < char_uuid_length; i++ ){ printf("%02x ", char_uuid[i]); }printf("\n"); // PRINT("char_properties :%02x,%s\r\n",char_properties,(char_properties&(GATT_PROP_WRITE|GATT_PROP_WRITE_NO_RSP))?"wite handle":""); PRINT("char_value_handle:%04x\r\n",char_value_handle); PRINT("char_uuid :%02d bit\r\n",char_uuid_length); if(char_properties&(GATT_PROP_WRITE|GATT_PROP_WRITE_NO_RSP)) { centralConnList[connItem].charHdl = char_value_handle; PRINT("Write handle:%04x\r\n",char_value_handle); tmos_start_task(centralConnList[connItem].taskID, START_READ_OR_WRITE_EVT, 1600); } if(char_properties&GATT_PROP_NOTIFY) { centralConnList[connItem].cccHdl = char_value_handle+1; //通过GATT_DiscAllChars或者handle,noti/indi的handle值需要+1 PRINT("Notify handle:%04x\r\n",char_value_handle); tmos_start_task(centralConnList[connItem].taskID, START_WRITE_CCCD_EVT, 1600); } if(char_properties&GATT_PROP_INDICATE) { centralConnList[connItem].cccHdl = char_value_handle+1; //通过GATT_DiscAllChars或者handle,noti/indi的handle值需要+1 PRINT("Indicate handle:%04x\r\n",char_value_handle); tmos_start_task(centralConnList[connItem].taskID, START_WRITE_CCCD_EVT, 800); } } } } }
使用GATT_DiscAllChars函数或者蓝牙分析仪抓包获取到的noti/indi的handle值需要+1才可以使能成功,write/read没有这方面的限制。
使用GATT_ReadUsingCharUUID获取到的handle值直接使能填写使能就可以。
这里更新MTU耗时较长可能会导致发现服务失败,程序中需要做些处理对GATT_DiscAllPrimaryServices的返回值进行判断如果返回值为0再停止这个任务。
当遇到write和write with no rsp的时候需要进行区分。相关实现代码如下:
if(events & START_READ_OR_WRITE_EVT) { if(centralProcedureInProgress == FALSE) { if(centralDoWrite) { // Do a write attWriteReq_t req; req.cmd = FALSE; req.sig = FALSE; req.handle = centralCharHdl; req.len = 1; // req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_REQ, req.len, NULL, 0); //req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_CMD, req.len, NULL, 0); if(write_choose &0x08) { PRINT("write_choose %02x\r\n",write_choose); req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_REQ, req.len, NULL, 0); if(req.pValue != NULL) { *req.pValue = centralCharVal; if(GATT_WriteCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS) //if(GATT_WriteNoRsp(centralConnHandle, &req) == SUCCESS) { //centralProcedureInProgress = TRUE; // centralDoWrite = !centralDoWrite; tmos_start_task(centralTaskId, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY); } else { GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ); } } } if(write_choose &0x04) { PRINT("write_choose %02x\r\n",write_choose); req.pValue = GATT_bm_alloc(centralConnHandle, ATT_WRITE_CMD, req.len, NULL, 0); if(req.pValue != NULL) { *req.pValue = centralCharVal; //if(GATT_WriteCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS) if(GATT_WriteNoRsp(centralConnHandle, &req) == SUCCESS) { //centralProcedureInProgress = TRUE; // centralDoWrite = !centralDoWrite; tmos_start_task(centralTaskId, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY); } else { GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_CMD); } } } } // else // { // // Do a read // attReadReq_t req; // // req.handle = centralCharHdl; // if(GATT_ReadCharValue(centralConnHandle, &req, centralTaskId) == SUCCESS) // { // centralProcedureInProgress = TRUE; // centralDoWrite = !centralDoWrite; // } // } } // tmos_start_task(centralTaskId, START_READ_OR_WRITE_EVT, DEFAULT_READ_OR_WRITE_DELAY); return (events ^ START_READ_OR_WRITE_EVT); }
仅是个人学习分享如有错漏请指正。
浙公网安备 33010602011771号