git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10420 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			282 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Helper functions to parse HID report descriptor and items.
 | |
| 
 | |
| Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "UsbMouseAbsolutePointer.h"
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Get next HID item from report descriptor.
 | |
| 
 | |
|   This function retrieves next HID item from report descriptor, according to
 | |
|   the start position.
 | |
|   According to USB HID Specification, An item is piece of information
 | |
|   about the device. All items have a one-byte prefix that contains
 | |
|   the item tag, item type, and item size.
 | |
|   There are two basic types of items: short items and long items.
 | |
|   If the item is a short item, its optional data size may be 0, 1, 2, or 4 bytes.
 | |
|   Only short item is supported here.
 | |
| 
 | |
|   @param  StartPos          Start position of the HID item to get.
 | |
|   @param  EndPos            End position of the range to get the the next HID item.
 | |
|   @param  HidItem           Buffer for the HID Item to return.
 | |
| 
 | |
|   @return Pointer to end of the HID item returned.
 | |
|           NULL if no HID item retrieved.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| GetNextHidItem (
 | |
|   IN  UINT8    *StartPos,
 | |
|   IN  UINT8    *EndPos,
 | |
|   OUT HID_ITEM *HidItem
 | |
|   )
 | |
| {
 | |
|   UINT8 Temp;
 | |
| 
 | |
|   if (EndPos <= StartPos) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   Temp = *StartPos;
 | |
|   StartPos++;
 | |
| 
 | |
|   //
 | |
|   // Bit format of prefix byte:
 | |
|   // Bits 0-1: Size
 | |
|   // Bits 2-3: Type
 | |
|   // Bits 4-7: Tag
 | |
|   //
 | |
|   HidItem->Type = BitFieldRead8 (Temp, 2, 3);
 | |
|   HidItem->Tag  = BitFieldRead8 (Temp, 4, 7);
 | |
| 
 | |
|   if (HidItem->Tag == HID_ITEM_TAG_LONG) {
 | |
|     //
 | |
|     // Long Items are not supported, although we try to parse it.
 | |
|     //
 | |
|     HidItem->Format = HID_ITEM_FORMAT_LONG;
 | |
| 
 | |
|     if ((EndPos - StartPos) >= 2) {
 | |
|       HidItem->Size = *StartPos++;
 | |
|       HidItem->Tag  = *StartPos++;
 | |
| 
 | |
|       if ((EndPos - StartPos) >= HidItem->Size) {
 | |
|         HidItem->Data.LongData = StartPos;
 | |
|         StartPos += HidItem->Size;
 | |
|         return StartPos;
 | |
|       }
 | |
|     }
 | |
|   } else {
 | |
|     HidItem->Format = HID_ITEM_FORMAT_SHORT;
 | |
|     HidItem->Size   = BitFieldRead8 (Temp, 0, 1);
 | |
| 
 | |
|     switch (HidItem->Size) {
 | |
|     case 0:
 | |
|       //
 | |
|       // No data
 | |
|       //
 | |
|       return StartPos;
 | |
| 
 | |
|     case 1:
 | |
|       //
 | |
|       // 1-byte data
 | |
|       //
 | |
|       if ((EndPos - StartPos) >= 1) {
 | |
|         HidItem->Data.Uint8 = *StartPos++;
 | |
|         return StartPos;
 | |
|       }
 | |
| 
 | |
|     case 2:
 | |
|       //
 | |
|       // 2-byte data
 | |
|       //
 | |
|       if ((EndPos - StartPos) >= 2) {
 | |
|         CopyMem (&HidItem->Data.Uint16, StartPos, sizeof (UINT16));
 | |
|         StartPos += 2;
 | |
|         return StartPos;
 | |
|       }
 | |
| 
 | |
|     case 3:
 | |
|       //
 | |
|       // 4-byte data, adjust size
 | |
|       //
 | |
|       HidItem->Size = 4;
 | |
|       if ((EndPos - StartPos) >= 4) {
 | |
|         CopyMem (&HidItem->Data.Uint32, StartPos, sizeof (UINT32));
 | |
|         StartPos += 4;
 | |
|         return StartPos;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Get data from HID item.
 | |
| 
 | |
|   This function retrieves data from HID item.
 | |
|   It only supports short items, which has 4 types of data:
 | |
|   0, 1, 2, or 4 bytes.
 | |
| 
 | |
|   @param  HidItem       Pointer to the HID item.
 | |
| 
 | |
|   @return The data of HID item.
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| GetItemData (
 | |
|   IN  HID_ITEM *HidItem
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Get data from HID item.
 | |
|   //
 | |
|   switch (HidItem->Size) {
 | |
|   case 1:
 | |
|     return HidItem->Data.Uint8;
 | |
|   case 2:
 | |
|     return HidItem->Data.Uint16;
 | |
|   case 4:
 | |
|     return HidItem->Data.Uint32;
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parse HID item from report descriptor.
 | |
| 
 | |
|   There are three item types: Main, Global, and Local.
 | |
|   This function parses these types of HID items according
 | |
|   to tag info.
 | |
| 
 | |
|   @param  UsbMouse          The instance of USB_MOUSE_ABSOLUTE_POINTER_DEV
 | |
|   @param  HidItem           The HID item to parse
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ParseHidItem (
 | |
|   IN  USB_MOUSE_ABSOLUTE_POINTER_DEV   *UsbMouse,
 | |
|   IN  HID_ITEM                         *HidItem
 | |
|   )
 | |
| {
 | |
|   UINT8  Data;
 | |
| 
 | |
|   switch (HidItem->Type) {
 | |
| 
 | |
|   case HID_ITEM_TYPE_MAIN:
 | |
|     //
 | |
|     // we don't care any main items, just skip
 | |
|     //
 | |
|     return ;
 | |
| 
 | |
|   case HID_ITEM_TYPE_GLOBAL:
 | |
|     //
 | |
|     // For global items, we only care Usage Page tag for Button Page here
 | |
|     //
 | |
|     if (HidItem->Tag == HID_GLOBAL_ITEM_TAG_USAGE_PAGE) {
 | |
|       Data = (UINT8) GetItemData (HidItem);
 | |
|       if (Data == 0x09) {
 | |
|         //
 | |
|         // Button Page
 | |
|         //
 | |
|         UsbMouse->PrivateData.ButtonDetected = TRUE;
 | |
|       }
 | |
|   }
 | |
|     return;
 | |
| 
 | |
|   case HID_ITEM_TYPE_LOCAL:
 | |
|     if (HidItem->Size == 0) {
 | |
|     //
 | |
|       // No expected data for local item
 | |
|     //
 | |
|     return ;
 | |
|     }
 | |
| 
 | |
|     Data = (UINT8) GetItemData (HidItem);
 | |
| 
 | |
|     switch (HidItem->Tag) {
 | |
|     case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
 | |
|       if (UsbMouse->PrivateData.ButtonDetected) {
 | |
|         UsbMouse->PrivateData.ButtonMinIndex = Data;
 | |
|     }
 | |
|     return ;
 | |
| 
 | |
|     case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
 | |
|     {
 | |
|       if (UsbMouse->PrivateData.ButtonDetected) {
 | |
|         UsbMouse->PrivateData.ButtonMaxIndex = Data;
 | |
|       }
 | |
|       return ;
 | |
|     }
 | |
| 
 | |
|     default:
 | |
|         return ;
 | |
|       }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Parse Mouse Report Descriptor.
 | |
| 
 | |
|   According to USB HID Specification, report descriptors are
 | |
|   composed of pieces of information. Each piece of information
 | |
|   is called an Item. This function retrieves each item from
 | |
|   the report descriptor and updates USB_MOUSE_ABSOLUTE_POINTER_DEV.
 | |
| 
 | |
|   @param  UsbMouseAbsolutePointer  The instance of USB_MOUSE_ABSOLUTE_POINTER_DEV
 | |
|   @param  ReportDescriptor         Report descriptor to parse
 | |
|   @param  ReportSize               Report descriptor size
 | |
| 
 | |
|   @retval EFI_SUCCESS              Report descriptor successfully parsed.
 | |
|   @retval EFI_UNSUPPORTED          Report descriptor contains long item.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| ParseMouseReportDescriptor (
 | |
|   OUT USB_MOUSE_ABSOLUTE_POINTER_DEV   *UsbMouseAbsolutePointer,
 | |
|   IN  UINT8                            *ReportDescriptor,
 | |
|   IN  UINTN                            ReportSize
 | |
|   )
 | |
| {
 | |
|   UINT8     *DescriptorEnd;
 | |
|   UINT8     *Ptr;
 | |
|   HID_ITEM  HidItem;
 | |
| 
 | |
|   DescriptorEnd = ReportDescriptor + ReportSize;
 | |
| 
 | |
|   Ptr = GetNextHidItem (ReportDescriptor, DescriptorEnd, &HidItem);
 | |
|   while (Ptr != NULL) {
 | |
|     if (HidItem.Format != HID_ITEM_FORMAT_SHORT) {
 | |
|       //
 | |
|       // Long Item is not supported at current HID revision
 | |
|       //
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
| 
 | |
|     ParseHidItem (UsbMouseAbsolutePointer, &HidItem);
 | |
| 
 | |
|     Ptr = GetNextHidItem (Ptr, DescriptorEnd, &HidItem);
 | |
|   }
 | |
| 
 | |
|   UsbMouseAbsolutePointer->NumberOfButtons = (UINT8) (UsbMouseAbsolutePointer->PrivateData.ButtonMaxIndex - UsbMouseAbsolutePointer->PrivateData.ButtonMinIndex + 1);
 | |
|   UsbMouseAbsolutePointer->XLogicMax = 1023;
 | |
|   UsbMouseAbsolutePointer->YLogicMax = 1023;
 | |
|   UsbMouseAbsolutePointer->XLogicMin = -1023;
 | |
|   UsbMouseAbsolutePointer->YLogicMin = -1023;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |