예제 #1
0
/** Retrieves the size of a Data Element container from the current input buffer, and advances the input buffer
 *  pointer to the start of the Data Element's contents.
 *
 *  \param[in, out] DataElementHeader  Pointer to the start of a Data Element header
 *  \param[out]     ElementHeaderSize  Size in bytes of the header that was skipped
 *
 *  \return Size in bytes of the Data Element container's contents, minus the header
 */
static uint32_t SDP_GetDataElementSize(const void** const DataElementHeader,
                                       uint8_t* const ElementHeaderSize)
{
	/* Fetch the size of the Data Element structure from the header, increment the current buffer pos */
	uint8_t  SizeIndex = (SDP_ReadData8(DataElementHeader) & 0x07);

	uint32_t ElementValueSize;

	/* Convert the Data Element size index into a size in bytes */
	switch (SizeIndex)
	{
		case SDP_DATASIZE_Variable8Bit:
			*ElementHeaderSize  = (1 + sizeof(uint8_t));
			ElementValueSize    = SDP_ReadData8(DataElementHeader);
			break;
		case SDP_DATASIZE_Variable16Bit:
			*ElementHeaderSize  = (1 + sizeof(uint16_t));
			ElementValueSize    = SDP_ReadData16(DataElementHeader);
			break;
		case SDP_DATASIZE_Variable32Bit:
			*ElementHeaderSize  = (1 + sizeof(uint32_t));
			ElementValueSize    = SDP_ReadData32(DataElementHeader);
			break;
		default:
			*ElementHeaderSize  = 1;
			ElementValueSize    = (1 << SizeIndex);
			break;
	}

	return ElementValueSize;
}
예제 #2
0
static void SDP_ServiceAttribute(BT_StackConfig_t* const StackState,
                                 BT_L2CAP_Channel_t* const Channel,
                                 BT_SDP_PDUHeader_t* const SDPHeader)
{
	const void* CurrParameterPos = SDPHeader->Parameters;

	/* Read service record handle */
	uint32_t RecordHandle         = SDP_ReadData32(&CurrParameterPos);

	/* Read maximum attribute size byte count for the response */
	uint16_t MaximumAttributeSize = SDP_ReadData16(&CurrParameterPos);

	/* Read search Attribute list sequence header and obtain its data size and a pointer to start of the data */
	uint16_t AttributeList[8][2];
	uint8_t  TotalAttributes      = SDP_GetAttributeList(AttributeList, &CurrParameterPos);

	/* Read continuation state value from the client */
	uint8_t  ContinuationState    = SDP_ReadData8(&CurrParameterPos);

	struct
	{
		BT_SDP_PDUHeader_t SDPHeader;
		uint16_t           AttributeListByteCount;
		uint8_t            ResponseData[200];
	} ATTR_PACKED ResponsePacket;

	/* Create a pointer to the buffer to indicate the current location for response data to be added */
	void* CurrResponsePos = ResponsePacket.ResponseData;

	/* Clamp the maximum attribute size to the size of the allocated buffer */
	if (MaximumAttributeSize > sizeof(ResponsePacket.ResponseData))
	  MaximumAttributeSize = sizeof(ResponsePacket.ResponseData);

	/* Search through all registered services, looking for UUID matches */
	SDP_ServiceEntry_t* CurrentService = RegisteredServices;
	while (CurrentService != NULL)
	{
		/* Retrieve a PROGMEM pointer to the value of the Service Record Handle */
		const void* ServiceRecord = SDP_GetAttributeValue(CurrentService, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);

		/* Check if matching service record found in the table */
		if (ServiceRecord)
		{
			/* Get the size of the header for the Service Record Handle */
			uint8_t AttrHeaderSize;
			SDP_GetLocalAttributeContainerSize(ServiceRecord, &AttrHeaderSize);

			/* Retrieve the endian-swapped service handle of the current service being examined */
			uint32_t CurrServiceHandle = be32_to_cpu(pgm_read_dword(ServiceRecord + AttrHeaderSize));

			/* Check if the current service in the service table has the requested service handle */
			if (RecordHandle == CurrServiceHandle)
			{
				/* Add the listed attributes for the found UUID to the response */
				SDP_AddListedAttributesToResponse(CurrentService, AttributeList, TotalAttributes, &CurrResponsePos);

				/* Requested service found, abort the search through the service table */
				break;
			}
		}

		/* Select next registered service in the service table list */
		CurrentService = CurrentService->NextService;
	}

	/* Continuation state - always zero */
	SDP_WriteData8(&CurrResponsePos, 0);

	/* Set the total response list size to the size of the outer container plus its header size and continuation state */
	ResponsePacket.AttributeListByteCount    = cpu_to_be16((uintptr_t)CurrResponsePos - (uintptr_t)ResponsePacket.ResponseData - sizeof(uint8_t));

	/* Fill in the response packet's header */
	ResponsePacket.SDPHeader.PDU             = SDP_PDU_SERVICEATTRIBUTERESPONSE;
	ResponsePacket.SDPHeader.TransactionID   = SDPHeader->TransactionID;
	ResponsePacket.SDPHeader.ParameterLength = cpu_to_be16(sizeof(ResponsePacket.AttributeListByteCount) + be16_to_cpu(ResponsePacket.AttributeListByteCount) + sizeof(uint8_t));

	/* Send the completed response packet to the sender */
	SDP_SendFrame(StackState, Channel, (sizeof(ResponsePacket.SDPHeader) + be16_to_cpu(ResponsePacket.SDPHeader.ParameterLength)), &ResponsePacket);
}
예제 #3
0
파일: SDP.c 프로젝트: davr/lufa-lib
/** Internal processing routine for SDP Service Attribute Requests.
 *
 *  \param[in] SDPHeader  Pointer to the start of the issued SDP request
 *  \param[in] Channel    Pointer to the Bluetooth channel structure the request was issued to
 */
static void SDP_ProcessServiceAttribute(const SDP_PDUHeader_t* const SDPHeader,
                                        Bluetooth_Channel_t* const Channel)
{
	const void* CurrentParameter = ((const void*)SDPHeader + sizeof(SDP_PDUHeader_t));

	BT_SDP_DEBUG(1, "<< Service Attribute");

	/* Retrieve the service handle whose attributes are to be examined */
	uint32_t ServiceHandle = SDP_ReadData32(&CurrentParameter);
	BT_SDP_DEBUG(2, "-- Service Handle: 0x%08lX", ServiceHandle);
	
	/* Retrieve the maximum Attribute response size from the request */
	uint16_t MaxAttributeSize = SDP_ReadData16(&CurrentParameter);
	BT_SDP_DEBUG(2, "-- Max Return Attribute Bytes: 0x%04X", MaxAttributeSize);
	
	/* Retrieve the list of Attributes from the request */
	uint16_t AttributeList[8][2];
	uint8_t  TotalAttributes = SDP_GetAttributeList(AttributeList, &CurrentParameter);
	BT_SDP_DEBUG(2, "-- Total Attributes: %d", TotalAttributes);

	struct
	{
		SDP_PDUHeader_t SDPHeader;
		uint16_t        AttributeListByteCount;
		uint8_t         ResponseData[100];
	} ResponsePacket;

	/* Create a pointer to the buffer to indicate the current location for response data to be added */
	void* CurrResponsePos = ResponsePacket.ResponseData;

	/* Clamp the maximum attribute size to the size of the allocated buffer */
	if (MaxAttributeSize > sizeof(ResponsePacket.ResponseData))
	  MaxAttributeSize = sizeof(ResponsePacket.ResponseData);

	uint16_t TotalResponseSize = 0;

	/* Search through the global UUID list an item at a time */
	for (uint8_t CurrTableItem = 0; CurrTableItem < (sizeof(SDP_Services_Table) / sizeof(void*)); CurrTableItem++)
	{
		/* Read in a pointer to the current UUID table entry's Attribute table */
		ServiceAttributeTable_t* CurrAttributeTable = pgm_read_ptr(&SDP_Services_Table[CurrTableItem]);
		
		/* Retrieve a PROGMEM pointer to the value of the Service Record Handle */
		const void* ServiceRecord = SDP_GetAttributeValue(CurrAttributeTable, SDP_ATTRIBUTE_ID_SERVICERECORDHANDLE);
		
		/* Get the size of the header for the Service Record Handle */
		uint8_t AttrHeaderSize;
		SDP_GetLocalAttributeContainerSize(ServiceRecord, &AttrHeaderSize);
		
		/* Retrieve the endian-swapped service handle of the current service being examined */
		uint32_t CurrServiceHandle = SwapEndian_32(pgm_read_dword(ServiceRecord + AttrHeaderSize));
		
		/* Check if the current service in the service table has the requested service handle */
		if (ServiceHandle == CurrServiceHandle)
		{
			/* Add the listed attributes for the found UUID to the response */
			TotalResponseSize = SDP_AddListedAttributesToResponse(CurrAttributeTable, AttributeList, TotalAttributes,
		                                                          &CurrResponsePos);
			
			/* Requested service found, abort the search through the service table */
			break;
		}
	}

	/* Continuation state - always zero */
	SDP_WriteData8(&CurrResponsePos, 0);

	/* Set the total response list size to the size of the outer container plus its header size and continuation state */
	ResponsePacket.AttributeListByteCount    = SwapEndian_16(TotalResponseSize);

	/* Calculate the total parameter length that is to be sent, including the fixed return parameters, the created attribute
	   value list and the SDP continuation state */
	uint16_t ParamLength = (sizeof(ResponsePacket.AttributeListByteCount) + TotalResponseSize + sizeof(uint8_t));
	
	/* Fill in the response packet's header */
	ResponsePacket.SDPHeader.PDU             = SDP_PDU_SERVICEATTRIBUTERESPONSE;
	ResponsePacket.SDPHeader.TransactionID   = SDPHeader->TransactionID;
	ResponsePacket.SDPHeader.ParameterLength = SwapEndian_16(ParamLength);

	BT_SDP_DEBUG(1, ">> Service Attribute Response");
	BT_SDP_DEBUG(2, "-- Param Len 0x%04X", ParamLength);

	/* Send the completed response packet to the sender */
	Bluetooth_SendPacket(&ResponsePacket, (sizeof(ResponsePacket.SDPHeader) + ParamLength), Channel);
}