575 lines
19 KiB
C
575 lines
19 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
|
|
This file implements the interfaces defined in EDKII_HID_PROTOCOL.
|
|
|
|
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 "BluetoothHidDxe.h"
|
|
|
|
typedef struct {
|
|
VOID *Command;
|
|
UINTN CommandSize;
|
|
UINT8 StopResponseCode;
|
|
VOID *Payload;
|
|
UINTN PayloadSize;
|
|
} BLUETOOTH_L2CAP_COMMAND_STRUCTURE;
|
|
|
|
UINT8 gHid1[] = {0xa2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
UINT8 gHid2[] = {0xa2, 0x02, 0x00, 0x00, 0x00, 0x00};
|
|
UINT8 gHid3[] = {0xa2, 0x03, 0x00};
|
|
UINT8 gHid4[] = {0xa2, 0x04, 0x00};
|
|
UINT8 gHid5[] = {0xa2, 0x05, 0x00};
|
|
UINT8 gHid6[] = {0xa2, 0xff, 0x00};
|
|
UINT8 gHidC7[] = {0x41, 0x03};
|
|
UINT8 gHidC8[] = {0x41, 0x03};
|
|
|
|
UINT8 mHidr1[] = {0x41, 0x03};
|
|
|
|
BLUETOOTH_L2CAP_COMMAND_STRUCTURE mCommandHidInit3[] = {
|
|
{&gHid1, sizeof(gHid1),},
|
|
{&gHid2, sizeof(gHid2),},
|
|
{&gHid3, sizeof(gHid3),},
|
|
{&gHid4, sizeof(gHid4),},
|
|
{&gHid5, sizeof(gHid5),},
|
|
{&gHid6, sizeof(gHid6),},
|
|
};
|
|
|
|
BLUETOOTH_L2CAP_COMMAND_STRUCTURE mCommandHidInit4[] = {
|
|
{&gHidC7, sizeof(gHidC7),},
|
|
{&gHidC8, sizeof(gHidC8),},
|
|
};
|
|
|
|
STATIC volatile BOOLEAN RequestOngoing = FALSE;
|
|
STATIC VOID *ResponseData = NULL;
|
|
STATIC UINTN ResponseDataLength= 0;
|
|
|
|
/**
|
|
Retrieves the information of a Bluetooth human interface device.
|
|
|
|
@param[in] This A pointer to the EDKII_HID_PROTOCOL instance.
|
|
@param[out] HidInfo A pointer to the EDKII_HID_INFO structure.
|
|
|
|
@retval EFI_SUCCESS The information of a Bluetooth human interface device
|
|
has been retrieved.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BtHidGetDeviceInfo (
|
|
IN EDKII_HID_PROTOCOL *This,
|
|
OUT EDKII_HID_INFO *HidInfo
|
|
)
|
|
{
|
|
BT_HID_DEV *BtHidDev;
|
|
LIST_ENTRY *Link;
|
|
HID_REPORT_FMT *ReportFormatList;
|
|
|
|
BtHidDev = BT_HID_DEV_FROM_HID_PROTOCOL (This);
|
|
|
|
Link = GetFirstNode (&BtHidDev->ReportFormatList);
|
|
while (!IsNull (&BtHidDev->ReportFormatList, Link)) {
|
|
ReportFormatList = ITEM_FROM_LINK(Link);
|
|
|
|
if ( ReportFormatList->UsagePage == BT_HID_BUTTON_USAGE_PAGE && ReportFormatList->Usage == BT_HID_POINTER_USAGE ) {
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
HidInfo->HidType |= HidTypeMouse;
|
|
#else
|
|
HidInfo->HidType = HidTypeMouse;
|
|
break;
|
|
#endif
|
|
} else if ( ReportFormatList->UsagePage == BT_HID_KEYBOARD_USAGE_PAGE && ReportFormatList->Usage == BT_HID_KEYBOARD_USAGE ) {
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
HidInfo->HidType |= HidTypeKeyBoard;
|
|
#else
|
|
HidInfo->HidType = HidTypeKeyBoard;
|
|
#endif
|
|
}
|
|
|
|
Link = GetNextNode (&ReportFormatList->Link, Link);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Starts the data transmission for a Bluetooth human interface device.
|
|
|
|
@param[in] This A pointer to the EDKII_HID_PROTOCOL
|
|
interface.
|
|
@param[in] HidControlCallback The callback function for data
|
|
transferred via control transfer.
|
|
@param[in] HidControlCallbackContext Data passed into the control transfer
|
|
callback function.
|
|
@param[in] HidInterruptCallback The callback function for data
|
|
transferred via interrupt transfer.
|
|
@param[in] HidInterrupCallbackContext Data passed into the interrupt
|
|
transfer callback function.
|
|
@param[in] HidInfo EDKII_HID_INFO structure to inform
|
|
interrupt is for HID Mouse or Keyboard.
|
|
Applcable only if UEFI_COMBO_DEVICE_SUPPORTED
|
|
is defined.
|
|
|
|
@retval EFI_SUCCESS The operation succeeds.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BtHidStart (
|
|
IN EDKII_HID_PROTOCOL *This,
|
|
IN EDKII_HID_SERVICE_CALLBACK HidControlCallback,
|
|
IN VOID *HidControlCallbackContext,
|
|
IN EDKII_HID_SERVICE_CALLBACK HidInterruptCallback,
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
IN VOID *HidInterrupCallbackContext,
|
|
IN EDKII_HID_INFO HidInfo
|
|
#else
|
|
IN VOID *HidInterrupCallbackContext
|
|
#endif
|
|
)
|
|
{
|
|
BT_HID_DEV *BtHidDev;
|
|
|
|
BtHidDev = BT_HID_DEV_FROM_HID_PROTOCOL (This);
|
|
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
if (HidInfo.HidType & HidTypeMouse) {
|
|
BtHidDev->HidMouseInterruptCallback = HidInterruptCallback;
|
|
BtHidDev->HidMouseInterruptCallbackContext = HidInterrupCallbackContext;
|
|
} else if (HidInfo.HidType & HidTypeKeyBoard) {
|
|
BtHidDev->HidKeyboardInterruptCallback = HidInterruptCallback;
|
|
BtHidDev->HidKeyboardInterruptCallbackContext = HidInterrupCallbackContext;
|
|
}
|
|
#else
|
|
BtHidDev->HidInterruptCallback = HidInterruptCallback;
|
|
BtHidDev->HidInterruptCallbackContext = HidInterrupCallbackContext;
|
|
#endif
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Stops the data transmission for a Bluetooth human interface device.
|
|
|
|
@param[in] This A pointer to the EDKII_HID_PROTOCOL instance.
|
|
|
|
@retval EFI_UNSUPPORTED The operation is not supported.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BtHidStop (
|
|
IN EDKII_HID_PROTOCOL *This
|
|
)
|
|
{
|
|
BT_HID_DEV *BtHidDev;
|
|
|
|
BtHidDev = BT_HID_DEV_FROM_HID_PROTOCOL (This);
|
|
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
BtHidDev->HidMouseInterruptCallback = NULL;
|
|
BtHidDev->HidMouseInterruptCallbackContext = NULL;
|
|
|
|
BtHidDev->HidKeyboardInterruptCallback = NULL;
|
|
BtHidDev->HidKeyboardInterruptCallbackContext = NULL;
|
|
#else
|
|
BtHidDev->HidInterruptCallback = NULL;
|
|
BtHidDev->HidInterruptCallbackContext = NULL;
|
|
#endif
|
|
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
/**
|
|
The callback function to a read attribute request.
|
|
|
|
@param[in] This A pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL
|
|
instance.
|
|
@param[in] Data Data received. The first byte is the attribute
|
|
opcode, followed by opcode specific fields.
|
|
See Bluetooth specification, Vol 3, Part F, Attribute
|
|
Protocol. It might be a normal RESPONSE message, or
|
|
ERROR RESPONSE message.
|
|
@param[in] DataLength The length of Data in bytes.
|
|
@param[in] Context The context passed from the callback registration
|
|
request.
|
|
|
|
@retval EFI_SUCCESS The callback function completes successfully.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ReadCallback (
|
|
IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This,
|
|
IN VOID *Data,
|
|
IN UINTN DataLength,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
UINT8 *Buffer;
|
|
UINT8 OpCode;
|
|
UINT16 Handle;
|
|
UINTN CopyLength;
|
|
|
|
Buffer = Data;
|
|
OpCode = *Buffer;
|
|
Handle = Context != NULL ? *((UINT16*)Context) : 0;
|
|
|
|
DEBUG ((EFI_D_INFO, "Got opcode 0x%02x for handle 0x%04x\n", OpCode, Handle));
|
|
|
|
Buffer++;
|
|
DataLength--;
|
|
CopyLength = MIN(DataLength, ResponseDataLength);
|
|
|
|
switch (OpCode) {
|
|
case BluetoothAttOpReadResponse:
|
|
CopyMem (ResponseData, Buffer, CopyLength);
|
|
break;
|
|
case BluetoothAttOpReadByTypeResponse:
|
|
case BluetoothAttOpReadMultipleResponse:
|
|
case BluetoothAttOpErrorResponse:
|
|
default:
|
|
DEBUG ((EFI_D_ERROR, "Invalid opcode\n"));
|
|
}
|
|
|
|
RequestOngoing = FALSE;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Submit a request to a Bluetooth human interface device over the Bluetooth
|
|
L2CAP layer.
|
|
|
|
@param[in] This A pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL
|
|
instance.
|
|
@param[in] Request A pointer to the EDKII_HID_REQUEST_TYPE structure that
|
|
specifies the type of the request.
|
|
@param[in] Value Value to set for the Bluetooth human interface
|
|
device.
|
|
@param[in] Length The length of Data in bytes.
|
|
@param[in,out] Data A pointer to the buffer for data transmission.
|
|
|
|
@retval EFI_UNSUPPORTED The type of request is not supported.
|
|
@retval EFI_OUT_OF_RESOURCES The operation fails due to memory allocation
|
|
failure.
|
|
@retval Other A value from other functions.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BtHidSendRequest (
|
|
IN EDKII_HID_PROTOCOL *This,
|
|
IN EDKII_HID_REQUEST_TYPE Request,
|
|
IN UINT16 Value,
|
|
IN UINT16 Length,
|
|
IN OUT VOID *Data
|
|
)
|
|
{
|
|
BT_HID_DEV *BtHidDev;
|
|
EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *BluetoothAttribute;
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *Link;
|
|
HID_REPORT_INFO *ReportInfo;
|
|
HID_REPORT_FMT *ReportItem;
|
|
UINT8 LedReportId;
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
UINT8 MouseReportId;
|
|
UINT8 KeyboardReportId;
|
|
#endif
|
|
UINT8 *Buffer;
|
|
|
|
BtHidDev = BT_HID_DEV_FROM_HID_PROTOCOL (This);
|
|
BluetoothAttribute = BtHidDev->BluetoothAttribute;
|
|
LedReportId = 0;
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
MouseReportId = 0;
|
|
KeyboardReportId = 0;
|
|
#endif
|
|
|
|
//DEBUG ((EFI_D_INFO, "HidSendRequest!\n"));
|
|
Status = EFI_SUCCESS;
|
|
switch (Request) {
|
|
case EdkiiHidRequestSetReport:
|
|
if (BtHidDev->LEDReportHandle > 0) {
|
|
Status = BluetoothAttributeWrite(BluetoothAttribute, BtHidDev->LEDReportHandle + 1, EfiBluetoothAttributeWriteCommand, Length, Data, NULL, NULL);
|
|
}
|
|
break;
|
|
case EdkiiHidRequestGetReportMap:
|
|
RequestOngoing = TRUE;
|
|
ResponseData = Data;
|
|
ResponseDataLength = Length;
|
|
Status = BluetoothAttributeRead(BluetoothAttribute, BtHidDev->ReportMapHandle + 1, 0, 0, ReadCallback, &BtHidDev->ReportMapHandle);
|
|
do {} while (RequestOngoing);
|
|
break;
|
|
case EdkiiHidRequestGetReportReferDesc:
|
|
Link = GetFirstNode (&BtHidDev->ReportFormatList);
|
|
while (!IsNull (&BtHidDev->ReportFormatList, Link)) {
|
|
ReportItem = ITEM_FROM_LINK(Link);
|
|
|
|
if (ReportItem->UsagePage == BT_HID_LED_USAGE_PAGE) {
|
|
LedReportId = ReportItem->ReportId;
|
|
break;
|
|
}
|
|
|
|
Link = GetNextNode (&BtHidDev->ReportFormatList, Link);
|
|
}
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
// Searching for Mouse Report
|
|
Link = GetFirstNode (&BtHidDev->ReportFormatList);
|
|
while (!IsNull (&BtHidDev->ReportFormatList, Link)) {
|
|
ReportItem = ITEM_FROM_LINK(Link);
|
|
|
|
if ((ReportItem->UsagePage == BT_HID_BUTTON_USAGE_PAGE) && (ReportItem->Usage == BT_HID_POINTER_USAGE)) {
|
|
MouseReportId = ReportItem->ReportId;
|
|
break;
|
|
}
|
|
|
|
Link = GetNextNode (&BtHidDev->ReportFormatList, Link);
|
|
}
|
|
|
|
// Searching for Keyboard Report
|
|
Link = GetFirstNode (&BtHidDev->ReportFormatList);
|
|
while (!IsNull (&BtHidDev->ReportFormatList, Link)) {
|
|
ReportItem = ITEM_FROM_LINK(Link);
|
|
|
|
if ((ReportItem->UsagePage == BT_HID_KEYBOARD_USAGE_PAGE) && (ReportItem->Usage == BT_HID_KEYBOARD_USAGE)) {
|
|
KeyboardReportId = ReportItem->ReportId;
|
|
break;
|
|
}
|
|
|
|
Link = GetNextNode (&BtHidDev->ReportFormatList, Link);
|
|
}
|
|
#endif
|
|
Link = GetFirstNode (&BtHidDev->HidReportInfo);
|
|
while (!IsNull (&BtHidDev->HidReportInfo, Link)) {
|
|
ReportInfo = BT_HID_REPORT_INFO_FROM_LINK(Link);
|
|
RequestOngoing = TRUE;
|
|
ResponseDataLength = 10;
|
|
ResponseData = AllocateZeroPool(ResponseDataLength);
|
|
if (ResponseData == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Status = BluetoothAttributeRead(BluetoothAttribute, ReportInfo->ReportReferDescHandle, 0, 0, ReadCallback, &ReportInfo->ReportHandle);
|
|
do {} while (RequestOngoing);
|
|
Buffer = ResponseData;
|
|
ReportInfo->ReportID = Buffer[0];
|
|
ReportInfo->ReportType = Buffer[1];
|
|
|
|
// If the Output report is for setting the LEDs, set the handle correctly
|
|
if ((ReportInfo->ReportType == HID_REPORT_TYPE_OUTPUT) && (ReportInfo->ReportID == LedReportId)) {
|
|
BtHidDev->LEDReportHandle = ReportInfo->ReportHandle;
|
|
}
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
// Setting Keyboard and/or Mouse Report Handle
|
|
if ((ReportInfo->ReportType == HID_REPORT_TYPE_INPUT) && (ReportInfo->ReportID == MouseReportId)) {
|
|
BtHidDev->MouseReportHandle = ReportInfo->ReportHandle;
|
|
} else if ((ReportInfo->ReportType == HID_REPORT_TYPE_INPUT) && (ReportInfo->ReportID == KeyboardReportId)) {
|
|
BtHidDev->KeyboardReportHandle = ReportInfo->ReportHandle;
|
|
}
|
|
#endif
|
|
FreePool(ResponseData);
|
|
Link = GetNextNode (&BtHidDev->HidReportInfo, Link);
|
|
}
|
|
break;
|
|
case EdkiiHidRequestGetReport:
|
|
case EdkiiHidRequestGetIdle:
|
|
case EdkiiHidRequestSetIdle:
|
|
default:
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
The callback function to the SetNotification request.
|
|
|
|
@param[in] This A pointer to the EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL
|
|
instance.
|
|
@param[in] Data Data received. The first byte is the attribute
|
|
opcode, followed by opcode specific fields.
|
|
See Bluetooth specification, Vol 3, Part F, Attribute
|
|
Protocol. It might be a normal RESPONSE message, or
|
|
ERROR RESPONSE message.
|
|
@param[in] DataLength The length of Data in bytes.
|
|
@param[in] Context The context passed from the callback registration
|
|
request.
|
|
|
|
@retval EFI_SUCCESS The callback function completes successfully.
|
|
@retval EFI_INVALID_PARAMETER The input parameters are invalid.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
NotificationCallback (
|
|
IN EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *This,
|
|
IN VOID *Data,
|
|
IN UINTN DataLength,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
UINT8 *Buffer;
|
|
UINT8 OpCode;
|
|
BT_HID_DEV *BtHidDev;
|
|
LIST_ENTRY *Link;
|
|
HID_REPORT_INFO *ReportInfo;
|
|
UINT16 ReportHandle;
|
|
|
|
//
|
|
// Within this function, the first 3 bytes of 'Data' will be explicitly
|
|
// consumed. Byte 0 is the opcode, bytes 1-2 are used for report handle.
|
|
//
|
|
if ((Data == NULL) || (DataLength < 3)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Buffer = Data;
|
|
OpCode = *Buffer;
|
|
BtHidDev = (BT_HID_DEV *)Context;
|
|
|
|
Buffer++;
|
|
DataLength--;
|
|
|
|
ReportHandle = *(UINT16 *)Buffer;
|
|
|
|
switch (OpCode) {
|
|
case BluetoothAttOpHandleValueNotification:
|
|
|
|
/* Zero filling the byte since it will not be used further */
|
|
Buffer[0] = 0;
|
|
|
|
/* The buffer that we plan to pass to the callback needs
|
|
* to have the report id appended before the buffer. We are using the lower byte of the opcode field to store this value.
|
|
* Thus, Advancing the buffer pointer by 1 and decrementing the length by 1.
|
|
*/
|
|
Buffer += 1;
|
|
DataLength -= 1;
|
|
Link = GetFirstNode (&BtHidDev->HidReportInfo);
|
|
// Populate the report ID correctly and proceed
|
|
while (!IsNull (&BtHidDev->HidReportInfo, Link)) {
|
|
ReportInfo = BT_HID_REPORT_INFO_FROM_LINK(Link);
|
|
|
|
if ( ReportInfo->ReportHandle + 1 == ReportHandle ) {
|
|
Buffer[0] = ReportInfo->ReportID;
|
|
break;
|
|
}
|
|
|
|
Link = GetNextNode (&BtHidDev->HidReportInfo, Link);
|
|
}
|
|
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
if ((BtHidDev->MouseReportHandle + 1) == ReportHandle) {
|
|
if (BtHidDev->HidMouseInterruptCallback) {
|
|
BtHidDev->HidMouseInterruptCallback(Buffer, DataLength, BtHidDev->HidMouseInterruptCallbackContext);
|
|
}
|
|
} else if ((BtHidDev->KeyboardReportHandle + 1) == ReportHandle) {
|
|
if (BtHidDev->HidKeyboardInterruptCallback) {
|
|
BtHidDev->HidKeyboardInterruptCallback(Buffer, DataLength, BtHidDev->HidKeyboardInterruptCallbackContext);
|
|
}
|
|
} else {
|
|
if (BtHidDev->HidMouseInterruptCallback) {
|
|
BtHidDev->HidMouseInterruptCallback(Buffer, DataLength, BtHidDev->HidMouseInterruptCallbackContext);
|
|
}
|
|
if (BtHidDev->HidKeyboardInterruptCallback) {
|
|
BtHidDev->HidKeyboardInterruptCallback(Buffer, DataLength, BtHidDev->HidKeyboardInterruptCallbackContext);
|
|
}
|
|
}
|
|
#else
|
|
BtHidDev->HidInterruptCallback(Buffer, DataLength, BtHidDev->HidInterruptCallbackContext);
|
|
#endif
|
|
break;
|
|
case BluetoothAttOpHandleValueIndication:
|
|
break;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Registers or unregisters a server initiated message on a characteristic value
|
|
on remote server.
|
|
|
|
@param[in] This A pointer to the EDKII_HID_PROTOCOL instance.
|
|
@param[in] Value Type of notification for server initiated attribute
|
|
protocol. A value of zero means unregister the server
|
|
initiated callback.
|
|
|
|
@retval EFI_UNSUPPORTED The operation is not supported
|
|
@retval Other A value from other functions.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BtHidSetNotification (
|
|
IN EDKII_HID_PROTOCOL *This,
|
|
IN UINT8 Value
|
|
)
|
|
{
|
|
BT_HID_DEV *BtHidDev;
|
|
EFI_BLUETOOTH_ATTRIBUTE_PROTOCOL *BluetoothAttribute;
|
|
EFI_STATUS Status;
|
|
EFI_BLUETOOTH_ATTRIBUTE_CALLBACK_PARAMETER NotifyParam;
|
|
LIST_ENTRY *Link;
|
|
HID_REPORT_INFO *ReportInfo;
|
|
|
|
BtHidDev = BT_HID_DEV_FROM_HID_PROTOCOL (This);
|
|
BluetoothAttribute = BtHidDev->BluetoothAttribute;
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
if (BluetoothAttribute == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//DEBUG ((EFI_D_INFO, "SetNotification!\n"));
|
|
|
|
NotifyParam.AttributeOpCode = Value;
|
|
|
|
Link = GetFirstNode (&BtHidDev->HidReportInfo);
|
|
while (!IsNull (&BtHidDev->HidReportInfo, Link)) {
|
|
ReportInfo = BT_HID_REPORT_INFO_FROM_LINK(Link);
|
|
// Register for all Input Reports
|
|
if (ReportInfo->ReportType == HID_REPORT_TYPE_INPUT) {
|
|
NotifyParam.Parameter.Notification.AttributeHandle = ReportInfo->ReportHandle;
|
|
if (Value != 0) {
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
Status = EFI_SUCCESS;
|
|
// Avoiding Enabling Notification if already enabled
|
|
if (ReportInfo->IsNotificationEnabled == FALSE) {
|
|
Status = BluetoothAttribute->RegisterForServerNotification(BluetoothAttribute, &NotifyParam, NotificationCallback, BtHidDev);
|
|
ReportInfo->IsNotificationEnabled = TRUE;
|
|
}
|
|
#else
|
|
Status = BluetoothAttribute->RegisterForServerNotification(BluetoothAttribute, &NotifyParam, NotificationCallback, BtHidDev);
|
|
#endif
|
|
} else {
|
|
Status = BluetoothAttribute->RegisterForServerNotification(BluetoothAttribute, &NotifyParam, 0, 0);
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
ReportInfo->IsNotificationEnabled = FALSE;
|
|
#endif
|
|
}
|
|
}
|
|
Link = GetNextNode (&BtHidDev->HidReportInfo, Link);
|
|
}
|
|
|
|
DEBUG ((EFI_D_INFO, "RegisterForServerNotification - %r\n", Status));
|
|
|
|
return Status;
|
|
}
|
|
|
|
|