alder_lake_bios/Intel/AlderLake/Features/BluetoothPkg/Library/BluetoothLib/BluetoothLibGatt.c

461 lines
16 KiB
C

//
// This file contains a 'Sample Driver' and is licensed as such
// under the terms of your license agreement with Intel or your
// vendor. This file may be modified by the user, subject to
// the additional terms of the license agreement
//
/** @file
The help functions which is used to read and parse bluetooth attributes.
Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
**/
#include <Library/DebugLib.h>
#include <Library/BluetoothLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <IndustryStandard/BluetoothAtt.h>
#include <IndustryStandard/BluetoothAssignedNumbers.h>
/**
Compares two Bluetooth UUID data.
@param[in] Uuid1 A pointer to the EFI_BLUETOOTH_UUID structure.
@param[in] Uuid2 A pointer to the EFI_BLUETOOTH_UUID structure.
@retval TRUE Uuid1 and Uuid2 are identical.
@retval FALSE Uuid1 and Uuid2 are not identical.
**/
STATIC
BOOLEAN
UuidCompareInternal(
IN EFI_BLUETOOTH_UUID *Uuid1,
IN EFI_BLUETOOTH_UUID *Uuid2
)
{
if (Uuid1->Length != Uuid2->Length)
return FALSE;
if ((Uuid1->Length == UUID_16BIT_TYPE_LEN) && (Uuid1->Data.Uuid16 == Uuid2->Data.Uuid16))
return TRUE;
if ((Uuid1->Length == UUID_32BIT_TYPE_LEN) && (Uuid1->Data.Uuid32 == Uuid2->Data.Uuid32))
return TRUE;
if ((Uuid1->Length == UUID_128BIT_TYPE_LEN) && (!CompareMem(Uuid1->Data.Uuid128, Uuid2->Data.Uuid128, UUID_128BIT_TYPE_LEN)))
return TRUE;
return FALSE;
}
/**
Converts a given Bluetooth UUID to 128-bit UUID data.
If the given UUID is a 128-bit Bluetooth UUID data, the origin UUID will be
returned. Otherwise, the converted 128-bit UUID data will be returned.
@param[in, out] Uuid On input, a pointer to the EFI_BLUETOOTH_UUID
structure that specifies the UUID to convert. On
output, the converted 128-bit UUID data.
**/
STATIC
VOID
UuidToUuid128Internal(
IN OUT EFI_BLUETOOTH_UUID *Uuid
)
{
UINT8 BaseUuidArray[16];
BaseUuidArray[0] = 0x00;
BaseUuidArray[1] = 0x00;
BaseUuidArray[2] = 0x00;
BaseUuidArray[3] = 0x00;
BaseUuidArray[4] = 0x00;
BaseUuidArray[5] = 0x00;
BaseUuidArray[6] = 0x10;
BaseUuidArray[7] = 0x00;
BaseUuidArray[8] = 0x80;
BaseUuidArray[9] = 0x00;
BaseUuidArray[10] = 0x00;
BaseUuidArray[11] = 0x80;
BaseUuidArray[12] = 0x5F;
BaseUuidArray[13] = 0x9B;
BaseUuidArray[14] = 0x34;
BaseUuidArray[15] = 0xFB;
if (Uuid->Length == UUID_128BIT_TYPE_LEN)
return;
if (Uuid->Length == UUID_16BIT_TYPE_LEN)
{
BaseUuidArray[2] = (UINT8)((Uuid->Data.Uuid16 & 0xFF00) >> 8);
BaseUuidArray[3] = (UINT8)((Uuid->Data.Uuid16 & 0x00FF));
}
else if(Uuid->Length == UUID_32BIT_TYPE_LEN)
{
BaseUuidArray[0] = (UINT8)((Uuid->Data.Uuid32 & 0xFF000000) >> 24);
BaseUuidArray[1] = (UINT8)((Uuid->Data.Uuid32 & 0x00FF0000) >> 16);
BaseUuidArray[2] = (UINT8)((Uuid->Data.Uuid32 & 0x0000FF00) >> 8);
BaseUuidArray[3] = (UINT8)(Uuid->Data.Uuid32 & 0x000000FF);
}
Uuid->Length = UUID_128BIT_TYPE_LEN;
CopyMem(Uuid->Data.Uuid128, BaseUuidArray, UUID_128BIT_TYPE_LEN);
}
/**
Compares two Bluetooth UUID data.
If the length of the two UUIDs is different, both UUIDs will be converted to
128-bit Bluetooth UUID data before comparison.
@param[in] Uuid1 A pointer to the EFI_BLUETOOTH_UUID structure.
@param[in] Uuid2 A pointer to the EFI_BLUETOOTH_UUID structure.
@retval TRUE Uuid1 and Uuid2 represent the same UUID.
@retval FALSE Uuid1 and Uuid2 represent different UUIDs.
**/
BOOLEAN
EFIAPI
BluetoothUuidCompare (
IN EFI_BLUETOOTH_UUID *Uuid1,
IN EFI_BLUETOOTH_UUID *Uuid2
)
{
EFI_BLUETOOTH_UUID Uuid1Copy, Uuid2Copy;
if (Uuid1->Length == Uuid2->Length)
return UuidCompareInternal(Uuid1, Uuid2);
CopyMem (&Uuid1Copy, Uuid1, sizeof (EFI_BLUETOOTH_UUID));
CopyMem (&Uuid2Copy, Uuid2, sizeof (EFI_BLUETOOTH_UUID));
UuidToUuid128Internal(&Uuid1Copy);
UuidToUuid128Internal(&Uuid2Copy);
return UuidCompareInternal((&Uuid1Copy), (&Uuid2Copy));
}
/**
Checks whether an attribute can be found on a Bluetooth device. The attribute
is specified by the service type and service UUID.
@param[in] This A pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL
instance.
@param[in] Type Type of the Bluetooth service.
@param[in] Uuid The Bluetooth Service Discovery UUID.
@param[in] StartHandle The starting identifier for a range of attributes to obtain.
@param[out] Attribute A pointer to the attribute data if the specified
attribute is found on the Bluetooth device.
@retval EFI_SUCCESS The specified attribute is found on the Bluetooth
device.
@retval EFI_NOT_FOUND The specified attribute is not found on the Bluetooth
device.
**/
EFI_STATUS
EFIAPI
BluetoothAttributeSearch (
IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This,
IN UINT16 Type,
IN EFI_BLUETOOTH_UUID *Uuid,
IN UINT16 StartHandle,
OUT EFI_BLUETOOTH_ATTRIBUTE_HEADER *Attribute
)
{
EFI_STATUS Status;
UINT8 *ServiceInfo;
VOID *ServiceInfoCopy;
UINTN ServiceInfoSize;
UINT8 AttrSize;
EFI_BLUETOOTH_ATTRIBUTE_HEADER *Attr;
EFI_BLUETOOTH_GATT_PRIMARY_SERVICE_INFO *ServiceVal;
EFI_BLUETOOTH_GATT_INCLUDE_SERVICE_INFO *IncludeVal;
EFI_BLUETOOTH_GATT_CHARACTERISTIC_INFO *CharVal;
EFI_BLUETOOTH_GATT_CHARACTERISTIC_DESCRIPTOR_INFO *DescVal;
Status = This->GetServiceInfo(This, &ServiceInfoSize, (VOID**) &ServiceInfo);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
ServiceInfoCopy = ServiceInfo;
while (ServiceInfoSize > 0) {
Attr = (EFI_BLUETOOTH_ATTRIBUTE_HEADER*) ServiceInfo;
if (BLUETOOTH_IS_ATTRIBUTE_OF_TYPE(Attr, BluetoothGattTypePrimaryService)) {
AttrSize = sizeof(EFI_BLUETOOTH_GATT_PRIMARY_SERVICE_INFO);
if (Type == BluetoothGattTypePrimaryService) {
ServiceVal = (EFI_BLUETOOTH_GATT_PRIMARY_SERVICE_INFO *) Attr;
if ((BluetoothUuidCompare(&ServiceVal->ServiceUuid, Uuid)) && (ServiceVal->Header.AttributeHandle >= StartHandle)) {
if (Attribute != NULL) {
CopyMem(Attribute, Attr, AttrSize);
}
break;
}
}
ServiceInfo += AttrSize;
ServiceInfoSize -= AttrSize;
}
else if (BLUETOOTH_IS_ATTRIBUTE_OF_TYPE(Attr, BluetoothGattTypeInclude)) {
AttrSize = sizeof(EFI_BLUETOOTH_GATT_INCLUDE_SERVICE_INFO);
if (Type == BluetoothGattTypeInclude) {
IncludeVal = (EFI_BLUETOOTH_GATT_INCLUDE_SERVICE_INFO*) Attr;
if ((BluetoothUuidCompare(&IncludeVal->ServiceUuid, Uuid)) && (IncludeVal->Header.AttributeHandle >= StartHandle)) {
if (Attribute != NULL) {
CopyMem(Attribute, Attr, AttrSize);
}
break;
}
}
ServiceInfo += AttrSize;
ServiceInfoSize -= AttrSize;
}
else if (BLUETOOTH_IS_ATTRIBUTE_OF_TYPE(Attr, BluetoothGattTypeCharacteristic)) {
AttrSize = sizeof(EFI_BLUETOOTH_GATT_CHARACTERISTIC_INFO);
if (Type == BluetoothGattTypeCharacteristic) {
CharVal = (EFI_BLUETOOTH_GATT_CHARACTERISTIC_INFO*) Attr;
if ((BluetoothUuidCompare(&CharVal->CharacteristicUuid, Uuid)) && (CharVal->Header.AttributeHandle >= StartHandle)) {
if (Attribute != NULL) {
CopyMem(Attribute, Attr, AttrSize);
}
break;
}
}
ServiceInfo += AttrSize;
ServiceInfoSize -= AttrSize;
}
else if (BLUETOOTH_IS_ATTRIBUTE_OF_TYPE(Attr, BluetoothGattTypeCharacteristicExtendedProperties)) {
AttrSize = sizeof(EFI_BLUETOOTH_GATT_CHARACTERISTIC_DESCRIPTOR_INFO);
if (Type == BluetoothGattTypeCharacteristicExtendedProperties) {
DescVal = (EFI_BLUETOOTH_GATT_CHARACTERISTIC_DESCRIPTOR_INFO*) Attr;
if ((BluetoothUuidCompare(&DescVal->CharacteristicDescriptorUuid, Uuid)) && (DescVal->Header.AttributeHandle >= StartHandle)) {
if (Attribute != NULL) {
CopyMem(Attribute, Attr, AttrSize);
}
break;
}
}
ServiceInfo += AttrSize;
ServiceInfoSize -= AttrSize;
} else {
/* Characteristic Value */
AttrSize = sizeof(EFI_BLUETOOTH_GATT_CHARACTERISTIC_INFO);
ServiceInfo += AttrSize;
ServiceInfoSize -= AttrSize;
}
}
FreePool(ServiceInfoCopy);
if (ServiceInfoSize != 0) {
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
/**
Submits a request to obtain the value of attributes from a remote server.
@param[in] This A pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL
interface.
@param[in] Handle If Uuid is NULL, a 16-bit identifier for the attribute
to obtain. Otherwise, the starting identifier for a
range of attributes to obtain.
@param[in] EndHandle The 16-bit ending identifier for a range of attributes
to obtain.
@param[in] Uuid A UUID to specify the type of the attribute to obtain.
@param[in] Callback The callback function when a response is received from
the remote server.
@param[in] Context Data passed into Callback function.
@retval EFI_SUCCESS The request is sent successfully.
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
@retval Other A error from other functions.
**/
EFI_STATUS
EFIAPI
BluetoothAttributeRead (
IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This,
IN UINT16 Handle,
IN UINT16 EndHandle,
IN EFI_BLUETOOTH_UUID *Uuid,
IN EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_FUNCTION Callback,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT16 Length;
UINT8 *Buffer;
Length = 0;
Buffer = NULL;
Buffer = AllocateZeroPool (sizeof (UINT8) + 2 * sizeof (UINT16) + UUID_128BIT_TYPE_LEN);
if (Buffer == NULL) {
ASSERT (Buffer != NULL);
return EFI_OUT_OF_RESOURCES;
}
if (Uuid != NULL) {
*(Buffer+Length) = BluetoothAttOpReadByTypeRequest;
Length++;
*((UINT16*)(Buffer+Length)) = Handle;
Length += 2;
*((UINT16*)(Buffer+Length)) = EndHandle;
Length += 2;
if (Uuid->Length == UUID_16BIT_TYPE_LEN) {
CopyMem ((Buffer + Length), &Uuid->Data.Uuid16, UUID_16BIT_TYPE_LEN);
}
if (Uuid->Length == UUID_32BIT_TYPE_LEN) {
CopyMem ((Buffer + Length), &Uuid->Data.Uuid32, UUID_32BIT_TYPE_LEN);
}
if (Uuid->Length == UUID_128BIT_TYPE_LEN) {
CopyMem ((Buffer + Length), &Uuid->Data.Uuid128, UUID_128BIT_TYPE_LEN);
}
Length += Uuid->Length;
} else {
*(Buffer+Length) = BluetoothAttOpReadRequest;
Length++;
*((UINT16*)(Buffer+Length)) = Handle;
Length += 2;
}
Status = This->SendRequest (This, Buffer, Length, Callback, Context);
FreePool (Buffer);
return Status;
}
/**
Submits a request to obtain the value of attributes using multiple handles.
@param[in] This A pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL
instance.
@param[in] Handles A list of 16-bit identifiers for the attributes to
obtain.
@param[in] NumHandles The number of handles in the list.
@param[in] Callback The callback function when a response is received
from the remote server.
@param[in] Context Data passed into Callback function.
@retval EFI_SUCCESS The request is sent successfully.
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
@retval Other A error from other functions.
**/
EFI_STATUS
EFIAPI
BluetoothAttributeMultiRead (
IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This,
IN UINT16 *Handles,
IN UINT8 NumHandles,
IN EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_FUNCTION Callback,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT16 Length;
UINT8 *Buffer;
Length = 0;
Buffer = NULL;
Buffer = AllocateZeroPool (sizeof (UINT8) + 10 * sizeof (UINT16));
if (Buffer == NULL) {
ASSERT (Buffer != NULL);
return EFI_OUT_OF_RESOURCES;
}
*(Buffer+Length) = BluetoothAttOpReadMultipleRequest;
Length++;
CopyMem ((Buffer+Length), Handles, NumHandles * sizeof (UINT16));
Length += (NumHandles * sizeof (UINT16));
Status = This->SendRequest (This, Buffer, Length, Callback, Context);
FreePool(Buffer);
return Status;
}
/**
Submits a request to write the value of an attribute to a remote server.
@param[in] This A pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL
instance.
@param[in] Handle A 16-bit identifier for the attribute to write.
@param[in] WriteType The type of write operation that will be sent to the
server.
@param[in] DataSize The size of Data in bytes, of the data buffer
specified by Data.
@param[in] Data A pointer to the buffer of data that will be sent.
@param[in] Callback The callback function when a response is received from
the remote server.
@param[in] Context Data passed into Callback function.
@retval EFI_SUCCESS The request is sent successfully.
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
@retval Other A error from other functions.
**/
EFI_STATUS
EFIAPI
BluetoothAttributeWrite (
IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This,
IN UINT16 Handle,
IN EFI_BLUETOOTH_ATTRIBUTE_WRITE_TYPE WriteType,
IN UINT16 DataSize,
IN VOID *Data,
IN EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_FUNCTION Callback,
IN VOID *Context
)
{
EFI_STATUS Status;
UINT16 Length;
UINT8 *Buffer;
Length = 0;
Buffer = NULL;
Buffer = AllocateZeroPool (sizeof (UINT8) + sizeof (UINT16) + DataSize);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
switch (WriteType) {
case EfiBluetoothAttributeWriteRequest:
*(Buffer+Length) = BluetoothAttOpWriteRequest;
break;
case EfiBluetoothAttributeWriteCommand:
*(Buffer+Length) = BluetoothAttOpWriteCommand;
break;
case EfiBluetoothAttributeSignedWrite:
*(Buffer+Length) = BluetoothAttOpSignedWriteCommand;
break;
case EfiBluetoothAttributeReliableWrite:
*(Buffer+Length) = BluetoothAttOpPrepareWriteRequest;
break;
}
Length++;
*((UINT16*)(Buffer+Length)) = Handle;
Length += 2;
CopyMem ((Buffer+Length), Data, DataSize);
Length += DataSize;
Status = This->SendRequest (This, Buffer, Length, Callback, Context);
FreePool (Buffer);
return Status;
}