/***************************************************************************** * FUNCTION * BTAppVerifyApplicationDataElement * DESCRIPTION * * PARAMETERS * raw_data [IN] * raw_data_length [IN] * deepth [IN] * RETURNS * *****************************************************************************/ BOOL BTAppVerifyApplicationDataElement(U8 *raw_data, U16 raw_data_length, U8 deepth) { U16 current_len = 0; U16 attribute_len = 0; U16 element_size = 0; U16 element_header_size = 1; BOOL result = TRUE; U8 *data = 0; U8 i = 0; U8 size_descriptor; U8 attribute_type; if (deepth > BT_APP_MAX_DEEPTH_SIZE) { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_DATA_ELEMENT_TOO_LARGE_NOT_CHECK); return TRUE; } for (current_len = 0; current_len < raw_data_length; current_len += attribute_len) { if (current_len > raw_data_length) { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_INVALID_PARAMETERS); result = FALSE; break; } data = (U8*) & (raw_data[current_len]); size_descriptor = SDP_GetElemSize(data[0]); attribute_type = SDP_GetElemType(data[0]); switch (attribute_type) { case DETD_NIL: case DETD_BOOL: if (size_descriptor != DESD_1BYTE) { result = FALSE; } else { element_size = BTAppSdpGetValidSize(size_descriptor); } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_X1_THE_ELEMENT_SIZE_x02X, element_size); element_header_size = 1; break; case DETD_UINT: case DETD_SINT: if (size_descriptor > DESD_16BYTES) { result = FALSE; } else { element_size = BTAppSdpGetValidSize(size_descriptor); } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_X2_THE_ELEMENT_SIZE_x02X, element_size); element_header_size = 1; break; case DETD_UUID: if ((size_descriptor != DESD_2BYTES) && (size_descriptor != DESD_4BYTES) && (size_descriptor != DESD_16BYTES)) { result = FALSE; } else { element_size = BTAppSdpGetValidSize(size_descriptor); } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_X3_THE_ELEMENT_SIZE_x02X, element_size); element_header_size = 1; break; case DETD_SEQ: case DETD_ALT: case DETD_TEXT: /* Text string. Valid Size 5,6,7 */ case DETD_URL: /* Uniform Resource Locator. Valid size 5,6,7 */ element_header_size = SDP_GetElemSize(data[0]); kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_TYPEx02X_SIZE_INDEXx02X, attribute_type, element_header_size); if (element_header_size < DESD_ADD_8BITS) { result = FALSE; } else { /* If size descriptor=5,6,7 then its additional size_bytes=1(5-4),2(6-4),4 (7-4+1) followed (Type descriptor:5-bits size descriptor:3-bits) */ /* element_header_size -= 4; */ if (element_header_size == DESD_ADD_8BITS) { element_header_size = 1; } else if (element_header_size == DESD_ADD_16BITS) { element_header_size = 2; } else if (element_header_size == DESD_ADD_32BITS) { element_header_size = 4; } else { kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_INVALID_SIZE_DESCRIPTOR_VALUEx02X, element_header_size); result = FALSE; return result; } element_size = 0; for (i = 0; i < element_header_size; i++) { element_size = (element_size << 8) | (data[1 + i]); } /* Currently, element_header_size is number of bytes to store actual data length, +1: 5-bits Type descriptor + 3-bits Size descriptor */ element_header_size += 1; if ((element_header_size + element_size) > (raw_data_length - current_len)) { result = FALSE; break; } kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_X5_THE_ELEMENT_SIZE_x02X, element_size); if (((attribute_type == DETD_SEQ) || (attribute_type == DETD_ALT)) && (element_size > 0)) { if (!BTAppVerifyApplicationDataElement((U8*) & data[element_header_size], element_size, (U8) (deepth + 1))) { result = FALSE; } } } break; default: result = FALSE; break; } if (!result) { break; } if (result) { kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_ATTRIBUTE_VALUE_ELEMENT_SIZE_x02X, element_size); attribute_len = (element_header_size + element_size); } if (!result) { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_VERIFY_FAILED); return FALSE; } } if (current_len != raw_data_length) { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_DATA_ELEMENT_PEASE_DATA_ELEMENT_FAILED); return FALSE; } else { return TRUE; } }
// data is the attribute_value passed from the SDP callback. // The formate of a profile descriptor is: BtStatus parseAvrcpVersion(U8 *data, U16 *version) { BtStatus status = BT_STATUS_FAILED; U8 type = 0; U16 local_pos = 0, offset = 0, len = 0; U16 value_len = 0; U16 uuid16 = 0; U32 uuid32 = 0; U8 uuid128[16] = {0}; type = SDP_GetElemType(data[local_pos]); len = SDP_ParseDataElement(&data[local_pos], &offset); OS_Report("[AVRCP] %s() type: %d, len: %d", __FUNCTION__, type, len); local_pos += offset; type = SDP_GetElemType(data[local_pos]); if (type == DETD_UUID) { value_len = SDP_ParseDataElement(&data[local_pos], &offset); local_pos += offset; // Print out the UUID field. Checking function can be added here. switch (value_len) { case 2: uuid16 = SDP_GetU16(&data[local_pos]); OS_Report("[AVRCP] %s() UUID16: 0x%04x", __FUNCTION__, uuid16); break; case 4: uuid32 = SDP_GetU32(&data[local_pos]); OS_Report("[AVRCP] %s() UUID32: 0x%08x", __FUNCTION__, uuid32); break; case 16: OS_MemCopy(uuid128, &data[local_pos], 16); OS_Report("[AVRCP] %s() UUID128: %02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x", __FUNCTION__, data[local_pos], data[local_pos + 1], data[local_pos + 2], data[local_pos + 3], data[local_pos + 4], data[local_pos + 5], data[local_pos + 6], data[local_pos + 7], data[local_pos + 8], data[local_pos + 9], data[local_pos + 10], data[local_pos + 11], data[local_pos + 12], data[local_pos + 13], data[local_pos + 14], data[local_pos + 15]); break; default: OS_Report("[AVRCP] %s() Invalide uuid_len: %d", __FUNCTION__, value_len); return status; } local_pos += value_len; } else { OS_Report("[AVRCP] %s() Invalid type: %d when parsing uuid.", __FUNCTION__, type); } type = SDP_GetElemType(data[local_pos]); len = SDP_ParseDataElement(&data[local_pos], &offset); if (type == DETD_UINT) { local_pos += offset; *version = SDP_GetU16(&data[local_pos]); OS_Report("[AVRCP] %s() version:0x%x", __FUNCTION__, *version); status = BT_STATUS_SUCCESS; } else { OS_Report("[AVRCP] %s() Invalid type: %d when parsing version.", __FUNCTION__ , type); } return status; }
/***************************************************************************** * FUNCTION * BTAppVerifyApplicationRecord * DESCRIPTION * * PARAMETERS * raw_data [IN] * raw_data_length [IN] * attribute_no [IN] * ptr [IN] * RETURNS * *****************************************************************************/ BOOL BTAppVerifyApplicationRecord(U8 *raw_data, U16 raw_data_length, U8 *attribute_no, U8 *ptr) { U16 attr_id = 0; U16 offset = 0; U16 element_size = 0; U16 element_header_size = 0; U8 *data = 0; BOOL result = TRUE; U16 i = 0; BOOL attribute_data_element = FALSE; U16 attribute_len = 0; U8 attribute_type = 0; U8 size_descriptor = 0; U8 attribute_index = 0; BT_APP_ATTRIBUTE_struct_t *attribute_buffer = NULL; attribute_index = 0; *attribute_no = 0; kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_RECORD_LENGTHx04X, raw_data_length); for (i = 0; i < raw_data_length; i += 8) { kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_ITS_DATAx02Xx02Xx02Xx02Xx02Xx02Xx02Xx02X, raw_data[i], raw_data[i + 1], raw_data[i + 2], raw_data[i + 3], raw_data[i + 4], raw_data[i + 5], raw_data[i + 6], raw_data[i + 7]); } /* attribute_len: attribute value's length; +2: attribute ID's length is two bytes */ for (offset = 0; offset < raw_data_length; offset += (attribute_len + 2)) { if (attribute_index > BT_APP_MAX_ATTRIBUTE_SIZE) { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_ATTRIBUTE_INDEX_xD_TOO_LARGE, attribute_index); } data = (U8*) (raw_data + offset); kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_DATA0x02X_DATA1x02X, data[0], data[1]); attr_id = ((((U16) data[0]) << 8) | ((U16) data[1])); kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_THE_ATTRIBUTE_ID_xD, attr_id); data += 2; /* Retrieve attribute id */ (*attribute_no)++; kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_THE_ELEMENT_TYPE_x02X, data[0]); attribute_data_element = FALSE; /* Retrieve attribute value size index and type descriptor */ size_descriptor = SDP_GetElemSize(data[0]); attribute_type = SDP_GetElemType(data[0]); switch (attribute_type) { case DETD_NIL: element_header_size = 1; if (size_descriptor != DESD_1BYTE) { result = FALSE; } else { element_size = 0; } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_A_THE_ELEMENT_SIZE_x02X, element_size); break; case DETD_BOOL: element_header_size = 1; if (size_descriptor != DESD_1BYTE) { result = FALSE; } else { element_size = BTAppSdpGetValidSize(size_descriptor); } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_A_THE_ELEMENT_SIZE_x02X, element_size); break; case DETD_UINT: case DETD_SINT: element_header_size = 1; kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_B_THE_ELEMENT_SIZE_x02X, element_size); if (size_descriptor > DESD_16BYTES) { result = FALSE; } else { element_size = BTAppSdpGetValidSize(size_descriptor); } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_B_THE_ELEMENT_SIZE_x02X, element_size); break; case DETD_UUID: element_header_size = 1; if ((size_descriptor != DESD_2BYTES) && (size_descriptor != DESD_4BYTES) && (size_descriptor != DESD_16BYTES)) { result = FALSE; } else { element_size = BTAppSdpGetValidSize(size_descriptor); } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_C_THE_ELEMENT_SIZE_x02X, element_size); break; case DETD_SEQ: /* Data Element Sequence. Valid Size descriptor: 5,6,7 */ case DETD_ALT: /* Data Alternative. Valid Size descriptor: 5,6,7 */ case DETD_TEXT: /* Text string. Valid Size 5,6,7 */ case DETD_URL: /* Uniform Resource Locator. Valid size 5,6,7 */ element_header_size = SDP_GetElemSize(data[0]); kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_TYPEx02X_SIZE_INDEXx02X, attribute_type, element_header_size); if (element_header_size < DESD_ADD_8BITS) { result = FALSE; } else { if ((attribute_type == DETD_SEQ) || (attribute_type == DETD_ALT)) { attribute_data_element = TRUE; } /* If size descriptor=5,6,7 then its additional size_bytes=1(5-4),2(6-4),4(7-4+1) followed (Type descriptor:5-bits size descriptor:3-bits) */ /* element_header_size -= 4; */ if (element_header_size == DESD_ADD_8BITS) { element_header_size = 1; } else if (element_header_size == DESD_ADD_16BITS) { element_header_size = 2; } else if (element_header_size == DESD_ADD_32BITS) { element_header_size = 4; } else { kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_INVALID_SIZE_DESCRIPTOR_VALUEx02X, element_header_size); result = FALSE; return result; } element_size = 0; /* * The for loop is used to obtain the actual data size and stores this actual data size to element_size * data[0]: Type descriptor(5-bits) + size descriptor(3-bits) * data[1] or data[1]-data[2] or data[1]-data[4] are actual data size */ for (i = 0; i < element_header_size; i++) { element_size = (element_size << 8) | (data[1 + i]); } /* * 5-bits (Type descriptor) + 3-bits (size descriptor) + 1 or 2 or 4 bytes (actual data size) * +1: it means that this one byte: 5-bits (Type descriptor) + 3-bits (size descriptor) */ element_header_size += 1; if ((element_header_size + element_size) > (raw_data_length - offset)) { result = FALSE; break; } kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_E_THE_ELEMENT_SIZE_x02X, element_size); } break; default: result = FALSE; break; } if (result) { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_ATTRIBUTE_VALUE_ELEMENT_SIZE_x04X, element_size); kal_trace( BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_ATTRIBUTE_VALUE_ELEMENT_HEADER_SIZE_x04X, element_header_size); if ((attribute_data_element) && (element_size > 0) && (element_size < BT_APP_MAX_DATA_ELEMENT_SIZE)) { /* Process the attribute_value part and its data type belongs to Data Element Sequence (Because attribute_data_element is TRUE) */ if (!BTAppVerifyApplicationDataElement(data + element_header_size, element_size, 0)) { result = FALSE; return FALSE; } } attribute_data_element = FALSE; } /* The BTstack will automatically assign the record handle of the record in SDP_AddRecord()'s SDPS(nextHandle) */ /* From SdpMarkAttribute(): It can be known that: aid= 0x0000 and aid= 0x0002 are assigned by BTStack */ if (attr_id != AID_SERVICE_RECORD_HANDLE && attr_id != AID_SERVICE_RECORD_STATE) { attribute_buffer = (BT_APP_ATTRIBUTE_struct_t*) (ptr + sizeof(BT_APP_ATTRIBUTE_struct_t) * attribute_index); attribute_buffer->attribute_id = attr_id; attribute_buffer->attribute_value = data; attribute_buffer->attribute_size = element_size + element_header_size; attribute_index++; } attribute_len = (element_size + element_header_size); } if (offset != raw_data_length) { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_VERIFY_FAILED); return FALSE; } else { kal_trace(BT_TRACE_JSR82_GROUP, BT_JSR82_VERIFY_RECORD_FINALLY_ATTRIBUTE_INDEXx02X, attribute_index); BTAppSdpCreateSortingAttributes(ptr, attribute_index); /* Note 2008-0410: actual stored attribute no is equal to attribute_index (aid=0x0000 is not stored) */ (*attribute_no) = attribute_index; return TRUE; } }
/*--------------------------------------------------------------------------- * HidSdpParseDescriptorList() *--------------------------------------------------------------------------- * * Synopsis: Parses the SDP query response for an 16 bit value. * * Return: (see SDP_ParseAttributes) */ static void HidSdpParseDescriptorList(HidChannel *Channel, U8 *in_value, U16 in_len, U8 result) { // HidParseData *hpd; //hpd = Hid_Init_Parser(); if (in_value == NULL) { return; } if (!(Channel->queryRsp.queryFlags & SDPQ_FLAG_DESCRIPTOR_LIST)) { if (in_len == 0) { return; } //if ((result == BT_STATUS_SDP_CONT_STATE) && if(Channel->queryRsp.descriptorLenOffset == 0) { U8 elemType = 0; U8 elemSizeDescpt = 0; U8 elemSize = 0; U8 elemAddSize = 0; U8 offset = 0; U8 i = 0; /* Only the first packet is preceded with data element header. The packet * in continuation sequence is raw data. */ while (offset + Channel->queryRsp.descriptorLen < in_len) { elemType = SDP_GetElemType(in_value[offset]); elemSizeDescpt = SDP_GetElemSize(in_value[offset]); switch (elemType) { case DETD_SEQ: if (elemSizeDescpt == DESD_ADD_8BITS) { offset = offset + 1; } else if (elemSizeDescpt == DESD_ADD_16BITS) { offset = offset + 2; } else if (elemSizeDescpt == DESD_ADD_32BITS) { offset = offset + 4; } break; case DETD_UINT: if (elemSizeDescpt > DESD_16BYTES) { return; } else { elemSize = HidSdpGetValidSize(elemSizeDescpt); offset += elemSize; } break; case DETD_TEXT: if (elemSizeDescpt == DESD_ADD_8BITS) { elemAddSize = 1; } else if (elemSizeDescpt == DESD_ADD_16BITS) { elemAddSize = 2; } else if (elemSizeDescpt == DESD_ADD_32BITS) { elemAddSize = 4; } for (i = 0; i < elemAddSize; i++) { Channel->queryRsp.descriptorLen = (Channel->queryRsp.descriptorLen << 8) | (in_value[offset + i + 1]); } offset = offset + elemAddSize; break; default: // other data element shall not be come out in HID attribute list break; } offset++; } if((in_len - offset) <= 0) { return; } /* Allocate a new buffer */ Channel->queryRsp.descriptorList = (U8 *)hid_malloc((U32)Channel->queryRsp.descriptorLen); if (Channel->queryRsp.descriptorList == NULL) { return; } btmtk_os_memset(Channel->queryRsp.descriptorList, 0, Channel->queryRsp.descriptorLen); /* Copy whatever data is available */ btmtk_os_memcpy(Channel->queryRsp.descriptorList, in_value + offset, in_len - offset); Channel->queryRsp.descriptorLenOffset = in_len - offset; } else { btmtk_os_memcpy(Channel->queryRsp.descriptorList + Channel->queryRsp.descriptorLenOffset, in_value, in_len); /* in case that there is more continuation packet */ Channel->queryRsp.descriptorLenOffset += in_len; /* if(Hid_SdpParse(Channel, hpd) == BT_STATUS_SUCCESS) bt_prompt_trace(MOD_BT,"[HID]Successed SDP parser "); else if(Hid_SdpParse(Channel, hpd) == BT_STATUS_FAILED) bt_prompt_trace(MOD_BT,"[HID]Failed SDP parser "); Hid_Free_Parser(hpd);*/ } kal_trace(BT_TRACE_G2_PROFILES,HID_SDP_PARSEATTRIBUTES_SUCCEEDED_BYTES_READ__xD_UPDATED_BUFF_LEN__xD , in_len, Channel->queryRsp.descriptorLenOffset); if (result == BT_STATUS_SUCCESS) { Channel->queryRsp.queryFlags |= SDPQ_FLAG_DESCRIPTOR_LIST; } } }