1 /**************************************************************************/ 2 /* */ 3 /* Copyright (c) Microsoft Corporation. All rights reserved. */ 4 /* */ 5 /* This software is licensed under the Microsoft Software License */ 6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */ 7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ 8 /* and in the root directory of this software. */ 9 /* */ 10 /**************************************************************************/ 11 12 13 /**************************************************************************/ 14 /**************************************************************************/ 15 /** */ 16 /** USBX Component */ 17 /** */ 18 /** HID Class */ 19 /** */ 20 /**************************************************************************/ 21 /**************************************************************************/ 22 23 24 /* Include necessary system files. */ 25 26 #define UX_SOURCE_CODE 27 28 #include "ux_api.h" 29 #include "ux_host_class_hid.h" 30 #include "ux_host_stack.h" 31 32 33 /**************************************************************************/ 34 /* */ 35 /* FUNCTION RELEASE */ 36 /* */ 37 /* _ux_host_class_hid_field_decompress PORTABLE C */ 38 /* 6.1 */ 39 /* AUTHOR */ 40 /* */ 41 /* Chaoqiong Xiao, Microsoft Corporation */ 42 /* */ 43 /* DESCRIPTION */ 44 /* */ 45 /* This function will decompress a field and return the usage/value. */ 46 /* */ 47 /* INPUT */ 48 /* */ 49 /* hid_field Pointer to HID field */ 50 /* report_buffer Pointer to report buffer */ 51 /* client_report Pointer to client report */ 52 /* */ 53 /* OUTPUT */ 54 /* */ 55 /* Completion Status */ 56 /* */ 57 /* CALLS */ 58 /* */ 59 /* None */ 60 /* */ 61 /* CALLED BY */ 62 /* */ 63 /* HID Class */ 64 /* */ 65 /* RELEASE HISTORY */ 66 /* */ 67 /* DATE NAME DESCRIPTION */ 68 /* */ 69 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ 70 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ 71 /* resulting in version 6.1 */ 72 /* */ 73 /**************************************************************************/ _ux_host_class_hid_field_decompress(UX_HOST_CLASS_HID_FIELD * hid_field,UCHAR * report_buffer,UX_HOST_CLASS_HID_CLIENT_REPORT * client_report)74UINT _ux_host_class_hid_field_decompress(UX_HOST_CLASS_HID_FIELD *hid_field, UCHAR *report_buffer, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report) 75 { 76 77 ULONG field_report_count; 78 ULONG field_report_size; 79 ULONG data_offset_byte; 80 ULONG data_offset_bit; 81 ULONG data_offset_bit_in_report; 82 ULONG field_value; 83 ULONG field_value_bit_shifting; 84 ULONG field_usage; 85 ULONG report_content; 86 87 88 /* Calculate the address of the beginning of the field in the report. */ 89 data_offset_byte = (hid_field -> ux_host_class_hid_field_report_offset >> 3); 90 91 /* Calculate the bit start address. Hopefully things will be on a boundary but not necessary. */ 92 data_offset_bit = hid_field -> ux_host_class_hid_field_report_offset & 7; 93 94 /* Each report field has a report_count value. This count is used to extract values from the 95 incoming report and build each usage/value instance. */ 96 for (field_report_count = 0; field_report_count < hid_field -> ux_host_class_hid_field_report_count; field_report_count++) 97 { 98 99 /* Get the report size in bits. */ 100 field_report_size = hid_field -> ux_host_class_hid_field_report_size; 101 102 /* We use the bit offset for this report and not the generic field bit offset. */ 103 data_offset_bit_in_report = data_offset_bit; 104 105 /* Reset the local value. */ 106 field_value = 0; 107 108 /* And start with bit 0 in the target value. */ 109 field_value_bit_shifting = 0; 110 111 /* Build the value field bit by bit. */ 112 while (field_report_size-- != 0) 113 { 114 115 /* Read the content. This method is redundant if we are not changing byte but it 116 makes the algorithm much easier. */ 117 report_content = (ULONG) *(report_buffer + data_offset_byte + (data_offset_bit_in_report >> 3)); 118 119 /* Shift the current value content to allow space to store the new bit. */ 120 field_value |= ((report_content >> (data_offset_bit_in_report & 7)) & 1) << field_value_bit_shifting; 121 122 /* Move to next bit in the report. */ 123 data_offset_bit_in_report++; 124 125 /* And the next bit in the value. */ 126 field_value_bit_shifting++; 127 } 128 129 /* The Usage value will depend if the data is defined as a variable or an array in the HID report. */ 130 if (hid_field -> ux_host_class_hid_field_value & UX_HOST_CLASS_HID_ITEM_VARIABLE) 131 { 132 133 /* Take the usage directly from the usage array. */ 134 field_usage = *(hid_field -> ux_host_class_hid_field_usages + field_report_count); 135 } 136 else 137 { 138 139 /* This is an array, so compute the usage from the min value, the report count and the 140 computed report value. */ 141 field_usage = hid_field -> ux_host_class_hid_field_usage_min + (ULONG)((SLONG)field_value - hid_field -> ux_host_class_hid_field_logical_min); 142 143 /* Also add the usage page. */ 144 field_usage |= (hid_field -> ux_host_class_hid_field_usage_page << 16); 145 } 146 147 /* Put the value and the usage into the caller's buffer. */ 148 *(client_report -> ux_host_class_hid_client_report_buffer + client_report -> ux_host_class_hid_client_report_actual_length) = field_usage; 149 client_report -> ux_host_class_hid_client_report_actual_length++; 150 *(client_report -> ux_host_class_hid_client_report_buffer + client_report -> ux_host_class_hid_client_report_actual_length) = field_value; 151 client_report -> ux_host_class_hid_client_report_actual_length++; 152 153 /* Calculate the next address for this field. */ 154 data_offset_bit += hid_field -> ux_host_class_hid_field_report_size; 155 } 156 157 /* Return successful completion. */ 158 return(UX_SUCCESS); 159 } 160 161