618 lines
18 KiB
C
618 lines
18 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
|
|
Bluetooth HID Driver which is used to produce EDKII_HID_PROTOCOL for upper
|
|
layer use.
|
|
|
|
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 "BluetoothHidParser.h"
|
|
#include "BluetoothHidDxe.h"
|
|
|
|
EFI_DRIVER_BINDING_PROTOCOL gBluetoothHidDriverBinding = {
|
|
BluetoothHidDriverBindingSupported,
|
|
BluetoothHidDriverBindingStart,
|
|
BluetoothHidDriverBindingStop,
|
|
0xa,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
EDKII_HID_PROTOCOL mHid = {
|
|
BtHidGetDeviceInfo,
|
|
BtHidStart,
|
|
BtHidStop,
|
|
BtHidSendRequest,
|
|
BtHidSetNotification,
|
|
BtHidGetReportFormatList
|
|
};
|
|
|
|
HID_DEVICE_PATH mBluetoothHidDevicePath = {
|
|
{
|
|
{
|
|
MESSAGING_DEVICE_PATH,
|
|
MSG_VENDOR_DP,
|
|
{
|
|
(UINT8) (sizeof (EFI_BLUETOOTH_HID_DEVICE_PATH)),
|
|
(UINT8) ((sizeof (EFI_BLUETOOTH_HID_DEVICE_PATH)) >> 8)
|
|
}
|
|
},
|
|
EFI_BLUETOOTH_HID_DEVICE_PATH_GUID,
|
|
},
|
|
{
|
|
END_DEVICE_PATH_TYPE,
|
|
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
|
{
|
|
END_DEVICE_PATH_LENGTH,
|
|
0
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
Entrypoint of BT HID Driver.
|
|
|
|
This function is the entrypoint of BT HID Driver. It installs Driver Binding
|
|
Protocols together with Component Name Protocols.
|
|
|
|
@param ImageHandle The firmware allocated handle for the EFI image.
|
|
@param SystemTable A pointer to the EFI System Table.
|
|
|
|
@retval EFI_SUCCESS The entry point is executed successfully.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BluetoothHidDriverBindingEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gBluetoothHidDriverBinding,
|
|
ImageHandle,
|
|
&gBluetoothHidComponentName,
|
|
&gBluetoothHidComponentName2
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Updates the GATT characteristic handle information of a Bluetooth human
|
|
interface device.
|
|
|
|
@param[in] BtHidDev A pointer to the BT_HID_DEV structure.
|
|
|
|
@retval EFI_UNSUPPORTED The EFI Bluetooth attribute protocol is not
|
|
supported.
|
|
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
|
|
@retval Other A value from other functions.
|
|
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
UpdateHogpHandles (
|
|
IN BT_HID_DEV *BtHidDev
|
|
)
|
|
{
|
|
EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *BluetoothAttribute;
|
|
EFI_BLUETOOTH_GATT_CHARACTERISTIC_INFO Attr;
|
|
EFI_BLUETOOTH_UUID Uuid;
|
|
EFI_STATUS Status;
|
|
HID_REPORT_INFO *HidReportInfo;
|
|
|
|
//DEBUG ((EFI_D_INFO, "UpdateHogpHandles:\n"));
|
|
|
|
BluetoothAttribute = BtHidDev->BluetoothAttribute;
|
|
|
|
if (BluetoothAttribute == NULL)
|
|
return EFI_UNSUPPORTED;
|
|
|
|
Uuid.Length = UUID_16BIT_TYPE_LEN;
|
|
|
|
InitializeListHead (&BtHidDev->HidReportInfo);
|
|
|
|
//
|
|
// Read Report Map first.
|
|
//
|
|
Uuid.Data.Uuid16 = BluetoothGattTypeHidReportMap;
|
|
Status = BluetoothAttributeSearch (BluetoothAttribute, BluetoothGattTypeCharacteristic, &Uuid, 0, &Attr.Header);
|
|
if (!EFI_ERROR(Status)) {
|
|
BtHidDev->ReportMapHandle = Attr.Header.AttributeHandle;
|
|
BtHidDev->ReportMapLen = BT_HID_REPORT_MAP_LEN;
|
|
BtHidDev->ReportMap = AllocateZeroPool (BtHidDev->ReportMapLen);
|
|
Status = HidGetReportMap(
|
|
&BtHidDev->Hid,
|
|
&BtHidDev->ReportMapLen,
|
|
BtHidDev->ReportMap
|
|
);
|
|
|
|
// Parse the report map
|
|
if (!EFI_ERROR(Status)) {
|
|
BtHidParseReportMap(BtHidDev);
|
|
}
|
|
|
|
//
|
|
// Read Report Reference Descriptor
|
|
//
|
|
ZeroMem(&Attr, sizeof(EFI_BLUETOOTH_GATT_CHARACTERISTIC_INFO));
|
|
do {
|
|
Uuid.Data.Uuid16 = BluetoothGattTypeHidReport;
|
|
Status = BluetoothAttributeSearch (BluetoothAttribute, BluetoothGattTypeCharacteristic, &Uuid, Attr.Header.AttributeHandle, &Attr.Header);
|
|
if (!EFI_ERROR(Status)) {
|
|
HidReportInfo = AllocateZeroPool (sizeof(HID_REPORT_INFO));
|
|
if (HidReportInfo == NULL) {
|
|
ASSERT (HidReportInfo != NULL);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
HidReportInfo->Signature = BT_HID_REPORT_INFO_SIGNATURE;
|
|
HidReportInfo->ReportHandle = Attr.Header.AttributeHandle;
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
HidReportInfo->IsNotificationEnabled = FALSE;
|
|
#endif
|
|
|
|
Uuid.Data.Uuid16 = BluetoothGattTypeDescReportRefer;
|
|
Status = BluetoothAttributeSearch (BluetoothAttribute, BluetoothGattTypeCharacteristicExtendedProperties, &Uuid, Attr.Header.AttributeHandle, &Attr.Header);
|
|
if (!EFI_ERROR(Status)) {
|
|
HidReportInfo->ReportReferDescHandle = Attr.Header.AttributeHandle;
|
|
InsertTailList (&BtHidDev->HidReportInfo, &HidReportInfo->Link);
|
|
} else {
|
|
FreePool(HidReportInfo);
|
|
}
|
|
}
|
|
} while(!EFI_ERROR(Status));
|
|
|
|
HidGetReportReferDesc(
|
|
&BtHidDev->Hid
|
|
);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Creates a Bluetooth attribute child handle.
|
|
|
|
@param[in] Controller The handle for the EFI Bluetooth
|
|
attribute service binding protocol
|
|
interface that is being opened.
|
|
@param[in] Image The handle of the agent that is opening
|
|
the EFI Bluetooth attribute service
|
|
binding protocol interface.
|
|
@param[in] ServiceBindingGuid The published unique identifier of the
|
|
EFI Bluetooth attribute service binding
|
|
protocol.
|
|
@param[in,out] ChildHandle Pointer to the handle of the child to
|
|
create. If it is NULL, then a new handle
|
|
is created. If it is a pointer to an
|
|
existing UEFI handle, then the protocol
|
|
is added to the existing UEFI handle.
|
|
|
|
@retval Other A value from other functions.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BluetoothCreateServiceChild (
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_HANDLE Image,
|
|
IN EFI_GUID *ServiceBindingGuid,
|
|
IN OUT EFI_HANDLE *ChildHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SERVICE_BINDING_PROTOCOL *Service;
|
|
|
|
|
|
ASSERT ((ServiceBindingGuid != NULL) && (ChildHandle != NULL));
|
|
|
|
//
|
|
// Get the ServiceBinding Protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
ServiceBindingGuid,
|
|
(VOID **) &Service,
|
|
Image,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Create a child
|
|
//
|
|
Status = Service->CreateChild (Service, ChildHandle);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Destroys a Bluetooth attribute child handle.
|
|
|
|
@param[in] Controller The handle for the EFI Bluetooth attribute
|
|
service binding protocol interface that is
|
|
being opened.
|
|
@param[in] Image The handle of the agent that is opening the
|
|
EFI Bluetooth attribute service binding
|
|
protocol interface.
|
|
@param[in] ServiceBindingGuid The published unique identifier of the EFI
|
|
Bluetooth attribute service binding protocol.
|
|
@param[in] ChildHandle Handle of the child to destroy.
|
|
|
|
@retval Other A value from other functions.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BluetoothDestroyServiceChild (
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_HANDLE Image,
|
|
IN EFI_GUID *ServiceBindingGuid,
|
|
IN EFI_HANDLE ChildHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SERVICE_BINDING_PROTOCOL *Service;
|
|
|
|
ASSERT (ServiceBindingGuid != NULL);
|
|
|
|
//
|
|
// Get the ServiceBinding Protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
ServiceBindingGuid,
|
|
(VOID **) &Service,
|
|
Image,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// destroy the child
|
|
//
|
|
Status = Service->DestroyChild (Service, ChildHandle);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Check whether BT HID driver supports this device.
|
|
|
|
@param This The BT HID driver binding protocol.
|
|
@param Controller The controller handle to check.
|
|
@param RemainingDevicePath The remaining device path.
|
|
|
|
@retval EFI_SUCCESS The driver supports this controller.
|
|
@retval other This device isn't supported.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BluetoothHidDriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiDevicePathProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
return gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiBluetoothAttributeServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
Starts the BT HID device with this driver.
|
|
|
|
This function consumes Bluetooth I/O Portocol, intializes BT HID device,
|
|
installs Hid Protocol.
|
|
|
|
@param This The BT HID driver binding instance.
|
|
@param Controller Handle of device to bind driver to.
|
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCESS This driver supports this device.
|
|
@retval EFI_UNSUPPORTED This driver does not support this device.
|
|
@retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
|
|
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
|
|
@retval EFI_ALREADY_STARTED This driver has been started.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BluetoothHidDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *BluetoothAttribute;
|
|
BT_HID_DEV *BtHidDev;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_DEVICE_PATH_PROTOCOL *Node;
|
|
EFI_BLUETOOTH_UUID Uuid;
|
|
EFI_HANDLE ChildHandle;
|
|
|
|
DEBUG ((EFI_D_ERROR, "BluetoothHidDriverBindingStart: %p %p \n", Controller, This->DriverBindingHandle));
|
|
BtHidDev = NULL;
|
|
ChildHandle = NULL;
|
|
BluetoothAttribute = NULL;
|
|
DevicePath = NULL;
|
|
|
|
//
|
|
// Get Device Path from Controller (It's Ble device)
|
|
// The DevicePath is opened BY_DRIVER by BluetoothAttributeDriverBinding
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
DevicePath = AppendDevicePath (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&mBluetoothHidDevicePath);
|
|
ASSERT (DevicePath != NULL);
|
|
|
|
Node = DevicePath;
|
|
Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Node, &ChildHandle);
|
|
if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {
|
|
//
|
|
// The HID child is already created.
|
|
//
|
|
FreePool (DevicePath);
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
//
|
|
// Create a Bluetooth Attribute child instance.
|
|
//
|
|
Status = BluetoothCreateServiceChild (
|
|
Controller,
|
|
This->DriverBindingHandle,
|
|
&gEfiBluetoothAttributeServiceBindingProtocolGuid,
|
|
&ChildHandle
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = gBS->OpenProtocol (
|
|
ChildHandle,
|
|
&gEfiBluetoothAttributeProtocolGuid,
|
|
(VOID**)&BluetoothAttribute,
|
|
This->DriverBindingHandle,
|
|
ChildHandle,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Uuid.Length = UUID_16BIT_TYPE_LEN;
|
|
Uuid.Data.Uuid16 = BluetoothUuidHumanInterfaceDevice;
|
|
Status = BluetoothAttributeSearch (BluetoothAttribute, BluetoothGattTypePrimaryService, &Uuid, 0, NULL);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "BluetoothHidDriverBindingStart: %r\n", Status));
|
|
FreePool (DevicePath);
|
|
goto ErrorExit;
|
|
} else {
|
|
DEBUG ((EFI_D_ERROR, "BluetoothHidDriverBindingStart: Find HID service\n"));
|
|
}
|
|
|
|
BtHidDev = AllocateZeroPool (sizeof (BT_HID_DEV));
|
|
if (BtHidDev == NULL) {
|
|
ASSERT (BtHidDev != NULL);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
BtHidDev->Signature = BT_HID_DEV_SIGNATURE;
|
|
BtHidDev->BluetoothAttribute = BluetoothAttribute;
|
|
CopyMem (&BtHidDev->Hid, &mHid, sizeof(mHid));
|
|
BtHidDev->DevicePath = DevicePath;
|
|
BtHidDev->ControllerHandle = ChildHandle;
|
|
BtHidDev->ParentHandle = Controller;
|
|
|
|
UpdateHogpHandles(BtHidDev);
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&BtHidDev->ControllerHandle,
|
|
&gEfiDevicePathProtocolGuid, BtHidDev->DevicePath,
|
|
&gEdkiiHidProtocolGuid, &BtHidDev->Hid,
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
&gEdkiiHid2ProtocolGuid, &BtHidDev->Hid,
|
|
#endif
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
BtHidDev->ControllerNameTable = NULL;
|
|
AddUnicodeString2 (
|
|
"eng",
|
|
gBluetoothHidComponentName.SupportedLanguages,
|
|
&BtHidDev->ControllerNameTable,
|
|
L"Generic Bluetooth HID",
|
|
TRUE
|
|
);
|
|
AddUnicodeString2 (
|
|
"en",
|
|
gBluetoothHidComponentName2.SupportedLanguages,
|
|
&BtHidDev->ControllerNameTable,
|
|
L"Generic Bluetooth HID",
|
|
FALSE
|
|
);
|
|
|
|
DEBUG ((EFI_D_ERROR, "BluetoothHidDriverBindingStart: ctrl = %x, child = %x, Exit - %r\n", Controller, ChildHandle, Status));
|
|
return Status;
|
|
|
|
//
|
|
// Error handler
|
|
//
|
|
ErrorExit:
|
|
Status = gBS->CloseProtocol (
|
|
ChildHandle,
|
|
&gEfiBluetoothAttributeProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
ChildHandle
|
|
);
|
|
|
|
Status = BluetoothDestroyServiceChild (
|
|
Controller,
|
|
This->DriverBindingHandle,
|
|
&gEfiBluetoothAttributeServiceBindingProtocolGuid,
|
|
ChildHandle
|
|
);
|
|
|
|
DEBUG ((EFI_D_ERROR, "BluetoothHidDriverBindingStart: Exit - %r\n", Status));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
|
|
/**
|
|
Stop the BT HID device handled by this driver.
|
|
|
|
@param This The BT HID driver binding protocol.
|
|
@param Controller The controller to release.
|
|
@param NumberOfChildren The number of handles in ChildHandleBuffer.
|
|
@param ChildHandleBuffer The array of child handle.
|
|
|
|
@retval EFI_SUCCESS The device was stopped.
|
|
@retval EFI_UNSUPPORTED Hid Protocol is not installed on Controller.
|
|
@retval Others Fail to uninstall protocols attached on the device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BluetoothHidDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BT_HID_DEV *BtHidDev;
|
|
EDKII_HID_PROTOCOL *Hid;
|
|
LIST_ENTRY *Link;
|
|
HID_REPORT_INFO *ReportInfo;
|
|
HID_REPORT_FMT *ReportFormatList;
|
|
|
|
DEBUG ((EFI_D_ERROR, "BluetoothHidDriverBindingStop: ctrl = %x, no = %x\n", Controller, NumberOfChildren));
|
|
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEdkiiHidProtocolGuid,
|
|
(VOID **) &Hid,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
BtHidDev = BT_HID_DEV_FROM_HID_PROTOCOL (Hid);
|
|
|
|
HidStopNotification (Hid);
|
|
FreePool(BtHidDev->ReportMap);
|
|
|
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
BtHidDev->ControllerHandle,
|
|
&gEfiDevicePathProtocolGuid, BtHidDev->DevicePath,
|
|
&gEdkiiHidProtocolGuid, &BtHidDev->Hid,
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
&gEdkiiHid2ProtocolGuid, &BtHidDev->Hid,
|
|
#endif
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEfiBluetoothAttributeProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
Status = BluetoothDestroyServiceChild (
|
|
BtHidDev->ParentHandle,
|
|
This->DriverBindingHandle,
|
|
&gEfiBluetoothAttributeServiceBindingProtocolGuid,
|
|
BtHidDev->ControllerHandle
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Free all resources.
|
|
//
|
|
if (BtHidDev->ControllerNameTable != NULL) {
|
|
FreeUnicodeStringTable (BtHidDev->ControllerNameTable);
|
|
}
|
|
|
|
Link = GetFirstNode (&BtHidDev->HidReportInfo);
|
|
while (!IsNull (&BtHidDev->HidReportInfo, Link)) {
|
|
ReportInfo = BT_HID_REPORT_INFO_FROM_LINK (Link);
|
|
Link = RemoveEntryList (&ReportInfo->Link);
|
|
FreePool (ReportInfo);
|
|
}
|
|
|
|
Link = GetFirstNode (&BtHidDev->ReportFormatList);
|
|
while (!IsNull (&BtHidDev->ReportFormatList, Link)) {
|
|
ReportFormatList = ITEM_FROM_LINK(Link);
|
|
Link = RemoveEntryList (&ReportFormatList->Link);
|
|
FreePool (ReportFormatList);
|
|
}
|
|
|
|
FreePool (BtHidDev);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|