94 Commits

Author SHA1 Message Date
Michael Banther
94a05a8ece Merge pull request #232 from xmos/release/v3.0.0
Release v3.0.0
2021-12-24 15:55:13 +00:00
Michael Banther
a93987d281 Merge pull request #227 from xmos/develop
Merge develop into release/v3.0.0
2021-12-23 15:50:22 +00:00
Michael Banther
4f35551547 Merge pull request #230 from CiaranWoodward/feature/unit-functional
Modify unit test report descriptor to match the working 3610
2021-12-23 15:06:48 +00:00
Ciaran Woodward
cb774f3c11 Modify unit test report descriptor to match the working 3610 2021-12-23 12:38:27 +00:00
Michael Banther
66a611f4fd Merge pull request #229 from mbanth/feature/multiple_hid_reports
Iterate through the correct set of HID Report IDs, plus some clean up.
2021-12-23 11:04:18 +00:00
mbanth
b61ea63d40 Iterate through the correct set of HID Report IDs, plus some clean up. 2021-12-23 10:31:07 +00:00
Michael Banther
8c132af069 Merge pull request #228 from CiaranWoodward/feature/multiple_hid_reports
Fix the handling of setidle requests
2021-12-22 17:15:05 +00:00
Ciaran Woodward
93229a7509 Fix refactoring error 2021-12-22 16:52:54 +00:00
Ciaran Woodward
466cc0abbb Fix the handling of setidle requests 2021-12-22 16:29:03 +00:00
Michael Banther
d5d5bd0637 Merge pull request #226 from CiaranWoodward/feature/multiple_hid_reports
Support multiple HID Reports & update examples for new API
2021-12-21 16:53:54 +00:00
Ciaran Woodward
ee6c22bd37 Loosen up usage page check in validate
While the implementation can only support one usage per report id,
the report collections themselves have usages, which are acceptable.
This change allows these usages to pass the validate check.
2021-12-21 12:43:34 +00:00
Ciaran Woodward
703a277059 Remove debug printfs 2021-12-21 12:18:57 +00:00
Ciaran Woodward
b88342ab2b Add new hid page ID constant 2021-12-21 11:21:17 +00:00
Ciaran Woodward
e7f9428731 Fix typos in unit tests 2021-12-20 17:34:01 +00:00
Ciaran Woodward
6400e146d0 Add an iterator style mechanism for iterating through report IDs 2021-12-20 17:26:08 +00:00
Ciaran Woodward
da114a1dea Merge pull request #1 from ACascarino/feature/multiple_hid_reports
Update lib_xua multiple_hid_reports from review
2021-12-20 17:21:25 +00:00
Angel Cascarino
77398218b5 Apply suggestions from code review
Co-authored-by: Ciaran Woodward <ciaranwoodward@gmail.com>
2021-12-20 17:17:34 +00:00
Angel Cascarino
244a7718a1 Corrected type in documentation 2021-12-20 17:11:50 +00:00
Angel Cascarino
e71ffdba00 Missed a semicolon... 2021-12-20 17:10:48 +00:00
Angel Cascarino
625123e4a6 Clarified ep_buffer.xc setup stall
Added getter hidIsReportDescriptorPrepared(),
allowing more readable logic in the setup phase of
ep_buffer.xc
2021-12-20 16:45:24 +00:00
Angel Cascarino
548992ab5c Removed USB_HID_REPORT_ID_CONSUMER as per review. 2021-12-20 15:46:15 +00:00
Ciaran Woodward
ccc1ee4021 Fix inverted isSilenced logic, add INVALID_ID constant 2021-12-20 14:47:20 +00:00
Angel Cascarino
ab96a726d6 Altered format on test report_descriptor.h 2021-12-20 12:51:26 +00:00
Ciaran Woodward
d3d9b5ba23 Add hidReportIdInUse command to determine whether report IDs are used 2021-12-17 14:35:23 +00:00
Ciaran Woodward
c3e95a379f Add some report time tests & fix comments] 2021-12-15 12:44:39 +00:00
Ciaran Woodward
5be97ac227 Begin work on setidle unit tests 2021-12-14 14:15:48 +00:00
Ciaran Woodward
8799f5f36e Refactor HID report descriptor validation function 2021-12-13 12:51:40 +00:00
Ciaran Woodward
71dd8b5409 Add descriptor validation function & fix issues it found
Note this is in progress, I either want to move the check function somewhere else,
or convert the printf calls to something else (I imagine some kind of log function
exists?)
2021-12-10 18:00:04 +00:00
Ciaran Woodward
e41aed6ffb Update examples to work with new API 2021-12-10 11:46:01 +00:00
Ciaran Woodward
548ccebb27 Propegate constants and helper macro around codebase 2021-12-10 11:32:04 +00:00
Ciaran Woodward
3895b486ab Add constants header for common constants; helper macro for header 2021-12-10 10:45:54 +00:00
Michael Banther
ebeae1fa17 Merge pull request #2 from CiaranWoodward/feature/multiple_hid_reports_tests
Update tests to work with new report-id api
2021-12-09 18:45:08 +00:00
Ciaran Woodward
f328deb336 style 2021-12-09 18:02:42 +00:00
Ciaran Woodward
353d7c3c8d Fix merge issues 2021-12-09 17:28:16 +00:00
Ciaran Woodward
5f971af054 Merge remote-tracking branch 'michael/feature/multiple_hid_reports' into feature/multiple_hid_reports_tests 2021-12-09 17:19:04 +00:00
mbanth
2b5dab51b5 Add explicit initialization of static variables in hid_report.c 2021-12-09 16:15:29 +00:00
Ciaran Woodward
19be25809b Fix implementation of hidGetReportIdLimit to match docs & usage 2021-12-09 16:10:28 +00:00
mbanth
26cac1abb1 Update includes of xua_hid_report.h 2021-12-09 15:58:51 +00:00
mbanth
03a5024520 Renamed xua_hid_report_descriptor.h to xua_hid_report.h 2021-12-09 15:45:05 +00:00
mbanth
08ed5ee668 Renamed hid_report_descriptor.c to hid_report.c 2021-12-09 15:44:19 +00:00
mbanth
2b96ea0171 Increment major version and add change log entries 2021-12-09 15:29:45 +00:00
Ciaran Woodward
1b186a0c2f Remove test-specific information from hid_report_descriptor.h 2021-12-09 14:55:38 +00:00
Ciaran Woodward
ed7a33b40f Write a bunch of unit tests that exercise the HID report IDs 2021-12-09 11:45:03 +00:00
Ciaran Woodward
459ce6bd63 Begin building up a set of multi-report unit tests
This work is starting by expanding the tests written for
single report purposes. I have also added a couple of
extra simple tests that made sense (under/overflow of
report IDs) as I went along.
2021-12-08 17:55:33 +00:00
Ciaran Woodward
3819f30ad0 Enable waf building unit tests in different confgurations 2021-12-08 15:47:15 +00:00
Ciaran Woodward
79e256f829 Update existing unit tests to work with the new API 2021-12-08 12:34:14 +00:00
Ciaran Woodward
be90779db5 Temporary workaround for ENDPOINT_INT_INTERVAL_IN_HID definition 2021-12-08 12:33:37 +00:00
Ciaran Woodward
de382e5cc0 Merge remote-tracking branch 'angel/feature/multiple_hid_reports' into feature/multiple_hid_reports_tests 2021-12-08 11:28:37 +00:00
Angel Cascarino
6dfc934d36 Correct error in hidCaptureReportTime 2021-12-08 11:14:52 +00:00
Ciaran Woodward
7dfd78deb4 Update unit test header to match new report id api 2021-12-08 11:01:33 +00:00
Angel Cascarino
fac0542920 Merge branch 'mbanth:feature/multiple_hid_reports' into feature/multiple_hid_reports 2021-12-08 10:47:55 +00:00
mbanth
8c9e8b11b9 Changes to support the Set Idle request with multiple Report IDs 2021-12-07 18:50:28 +00:00
Angel Cascarino
21b259bc88 Update legacy_test to new HID API 2021-12-07 18:12:00 +00:00
Angel Cascarino
589c16d56c Updated gitignore 2021-12-07 17:17:14 +00:00
mbanth
b4d5cb93f1 Use an unsigned constant with an unsigned variable 2021-12-07 10:35:20 +00:00
mbanth
1d22975fd2 Update HID initialisation and handling to include multiple reports and the effect of the Set Idle command 2021-12-06 17:28:30 +00:00
mbanth
5354d94987 Remove unused pointer 2021-12-06 17:16:11 +00:00
mbanth
171ef30f42 Remove redundant function declaration 2021-12-06 13:53:20 +00:00
mbanth
8c175187c8 Modify hidClearChangePending(), hidIsChangePending() amd hidSetChangePending() to operate on a Report ID basis 2021-12-01 12:26:26 +00:00
mbanth
53f80dfba4 Add documentation 2021-12-01 12:25:18 +00:00
mbanth
21c1e661ae Change static variable names to indicate that they are static. 2021-12-01 09:47:52 +00:00
mbanth
d515458b83 Add id parameter to hidClearChangePending(), hidIsChangePending() and hidSetChangePending(). Correct the name of the underlying static variable. 2021-12-01 09:42:32 +00:00
mbanth
b853589120 Move the HID Clear Pending, Is Pending and Set Pending functions from hid.xc to hid_report_descriptor.c.
These functions are called from the application so they do not belong in hid.xc which contains internal XUA functionality.
2021-11-30 18:29:17 +00:00
mbanth
966d8db9a9 Additional documentation and a minor renaming of an automatic variable 2021-11-30 15:05:37 +00:00
mbanth
dc22b0593f Additional documentation 2021-11-30 15:04:33 +00:00
mbanth
0892ff9a8b Move the declaration of the HID Get Report Limit function and provide its definition 2021-11-29 17:09:26 +00:00
mbanth
65b1b41ec4 Change the interface to UserHIDGetData() and UserHIDRecordEvent() 2021-11-26 16:32:12 +00:00
mbanth
3b6f1c80e2 Move HID_REPORT_COUNT to hid_report_descriptor.h 2021-11-26 16:30:47 +00:00
mbanth
bf9e150310 Use size_t for each index into an array. 2021-11-26 13:40:58 +00:00
mbanth
1857ddbc67 Set constant values explicitly to unsigned. Add access function for HID Report length. Update hidGetReportItem() and hidSetReportItem() to check for correct Reporty ID. Update hidGetReportLength() to report the length of the given HID Report. Update hidGetUsagePage() to iterate across all HID Reports. 2021-11-26 10:50:53 +00:00
mbanth
145c0cb80f Set constant values explicitly to unsigned 2021-11-26 10:46:03 +00:00
mbanth
1fe4fc6771 Safety commit. Builds but not run. 2021-11-25 17:30:30 +00:00
mbanth
88a3d6b20d Initial commit made to keep a safe copy. Builds but will not run and definitely very incomplete. 2021-11-24 16:06:17 +00:00
Ross Owen
33ec43134c Merge pull request #224 from xross/fix/223
fix/223
2021-10-26 14:57:45 +01:00
xross
2bbebc0a39 Further removed of XS1 support items 2021-10-18 17:05:35 +01:00
xross
32af5b7b20 Removed XS1 implementation in fastmix.S 2021-10-18 16:54:54 +01:00
xross
fc6915be6f Removed XS3 related warning from reboot.xc 2021-10-18 16:49:46 +01:00
xross
d9dc7cc7c7 XS2 now special case in DFU flag check 2021-10-18 16:45:07 +01:00
xross
898a6c2410 Remove XS1 related USB port. Also fixed errors related to removing XS1 support from ADAT 2021-10-18 16:38:32 +01:00
xross
da758f48fa Removed remaining references to SU1 devices 2021-10-18 16:37:33 +01:00
Michael Banther
2923f7574b Merge pull request #220 from xmos/release/v2.1.1
Release v2.1.1
2021-09-08 15:02:41 +01:00
Michael Banther
436a268781 Merge pull request #219 from xmos/develop
Prepare release of v2.1.1
2021-09-08 11:28:45 +01:00
Michael Banther
8233ef1d47 Merge pull request #218 from mbanth/feature/fix_hid_set_report_item
Fix hid set report item
2021-08-26 16:52:06 +01:00
mbanth
1109e08dd8 Increment version and add change log entry 2021-08-26 16:25:40 +01:00
mbanth
15f1d4de59 Use correct order of expected vs actual results in test assertions 2021-08-26 16:13:23 +01:00
mbanth
911a82cd83 Add test for the case of a modified item that of length 1 that overwrites data of length 2 2021-08-25 18:16:54 +01:00
mbanth
ec657d1e8d Zero the MSB if given an item of length 1 2021-08-25 18:13:12 +01:00
Luciano Martin
9e82d613bb Merge pull request #217 from xmos/release/v2.1.0
Merge release/v2.1.0 into master
2021-08-20 16:05:48 +01:00
Luciano Martin
eb62940dc6 Merge pull request #215 from xmos/develop
Merge develop into release/v2.1.0
2021-08-20 15:48:30 +01:00
Luciano Martin
ef46bd72b9 Merge pull request #216 from xmos/feature/update_dependency_version
Updare lib_xud dependency version
2021-08-20 15:48:17 +01:00
lucianom
7abcb487a9 Updare lib_xud dependency version 2021-08-20 14:55:05 +01:00
Luciano Martin
e87a53ff83 Merge pull request #214 from lucianomartin/feature/lib_xud_v2_0_0
Update clock blocks to support lib_xud v2.0.0
2021-08-06 11:50:43 +01:00
lucianom
8e05595710 Update clock in unit test 2021-08-06 10:21:38 +01:00
lucianom
ffee831f5d Updated clock blocks to support lib_xud v2.0.0 2021-08-06 08:52:36 +01:00
35 changed files with 3539 additions and 1004 deletions

2
.gitignore vendored
View File

@@ -20,6 +20,8 @@
test_results.csv
_build*
**/.venv/**
**/.vscode/**
**.egg-info
# waf build files
.lock-waf_*

View File

@@ -1,6 +1,26 @@
lib_xua Change Log
==================
3.0.0
-----
* ADDED: Support for HID Report IDs
* REMOVED: Support for HID Reports containing controls from mixed Usage
pages
* CHANGED: Renamed the HID API file xua_hid_report_descriptor.h to
xua_hid_report.h
2.1.1
-----
* CHANGED: Setting of HID report items
2.1.0
-----
* CHANGED: Updated clock blocks to support lib_xud v2.0.0
* CHANGED: Updated dependency on lib_xud to v2.0.0 for use by XVF3600
2.0.1
-----

2
Jenkinsfile vendored
View File

@@ -45,7 +45,7 @@ pipeline {
// runWaf('.', "configure clean build --target=xcoreai")
// stash name: 'xua_unit_tests', includes: 'bin/*xcoreai.xe, '
viewEnv() {
runPython("TARGET=XCORE200 pytest -n 1")
runPython("TARGET=XCORE200 pytest -s")
}
}
}

View File

@@ -3,7 +3,7 @@
#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__
#include "xua_hid_report_descriptor.h"
#include "xua_hid_report.h"
#if 0
/* Existing static report descriptor kept for reference */
@@ -32,38 +32,92 @@ unsigned char hidReportDescriptor[] =
/*
* Define non-configurable items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t hidCollectionApplication = { .header = 0xA1, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionEnd = { .header = 0xC0, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionApplication = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionEnd = {
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidInputConstArray = { .header = 0x81, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputDataVar = { .header = 0x81, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputConstArray = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidInputDataVar = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = { .header = 0x25, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = { .header = 0x25, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = { .header = 0x15, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount2 = { .header = 0x95, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount6 = { .header = 0x95, .data = { 0x06, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportSize1 = { .header = 0x75, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount2 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount6 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x06, 0x00 } };
static const USB_HID_Short_Item_t hidReportSize1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsageConsumerControl = { .header = 0x09, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsagePageConsumer = { .header = 0x05, .data = { 0x0C, 0x00 }, .location = 0x00 };
/*
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
*/
static const USB_HID_Report_Element_t hidReportPageConsumer = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 2, 0, 0 )
};
/*
* Define configurable items in the HID Report descriptor.
*/
static USB_HID_Short_Item_t hidUsageByte0Bit5 = { .header = 0x09, .data = { 0xE2, 0x00 }, .location = 0x50 }; // Mute
static USB_HID_Short_Item_t hidUsageByte0Bit4 = { .header = 0x09, .data = { 0xEA, 0x00 }, .location = 0x40 }; // Vol-
static USB_HID_Short_Item_t hidUsageByte0Bit3 = { .header = 0x09, .data = { 0xE9, 0x00 }, .location = 0x30 }; // Vol+
static USB_HID_Short_Item_t hidUsageByte0Bit2 = { .header = 0x09, .data = { 0xB6, 0x00 }, .location = 0x20 }; // Scan Prev
static USB_HID_Short_Item_t hidUsageByte0Bit1 = { .header = 0x09, .data = { 0xB5, 0x00 }, .location = 0x10 }; // Scan Next
static USB_HID_Short_Item_t hidUsageByte0Bit0 = { .header = 0x09, .data = { 0xB0, 0x00 }, .location = 0x00 }; // Play
static USB_HID_Report_Element_t hidUsageByte0Bit5 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE2, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
}; // Mute
static USB_HID_Report_Element_t hidUsageByte0Bit4 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xEA, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 4)
}; // Vol-
static USB_HID_Report_Element_t hidUsageByte0Bit3 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE9, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 3)
}; // Vol+
static USB_HID_Report_Element_t hidUsageByte0Bit2 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB6, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 2)
}; // Scan Prev
static USB_HID_Report_Element_t hidUsageByte0Bit1 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB5, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 1)
}; // Scan Next
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB0, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 0)
}; // Play
/*
* List the configurable items in the HID Report descriptor.
* List the configurable elements in the HID Report descriptor.
*/
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
@@ -73,27 +127,28 @@ static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
};
/*
* List Usage pages in the HID Report descriptor, one per byte.
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
* If not using report IDs - still have one with report ID 0
*/
static const USB_HID_Short_Item_t* const hidUsagePages[] = {
&hidUsagePageConsumer
static const USB_HID_Report_Element_t* const hidReports[] = {
&hidReportPageConsumer
};
/*
* List all items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
&hidUsagePageConsumer,
&(hidReportPageConsumer.item),
&hidUsageConsumerControl,
&hidCollectionApplication,
&hidLogicalMinimum0,
&hidLogicalMaximum1,
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
&hidUsageByte0Bit3,
&hidUsageByte0Bit4,
&hidUsageByte0Bit5,
&(hidUsageByte0Bit0.item),
&(hidUsageByte0Bit1.item),
&(hidUsageByte0Bit2.item),
&(hidUsageByte0Bit3.item),
&(hidUsageByte0Bit4.item),
&(hidUsageByte0Bit5.item),
&hidReportSize1,
&hidReportCount6,
&hidInputDataVar,
@@ -104,9 +159,10 @@ static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
};
/*
* Define the length of the HID Report.
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
* Define the number of HID Reports
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
*/
#define HID_REPORT_LENGTH ( 1 )
#define HID_REPORT_COUNT ( 1 )
#endif // __hid_report_descriptor_h__

View File

@@ -3,7 +3,7 @@
#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__
#include "xua_hid_report_descriptor.h"
#include "xua_hid_report.h"
#if 0
/* Existing static report descriptor kept for reference */
@@ -32,38 +32,92 @@ unsigned char hidReportDescriptor[] =
/*
* Define non-configurable items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t hidCollectionApplication = { .header = 0xA1, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionEnd = { .header = 0xC0, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionApplication = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionEnd = {
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidInputConstArray = { .header = 0x81, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputDataVar = { .header = 0x81, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputConstArray = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidInputDataVar = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = { .header = 0x25, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = { .header = 0x25, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = { .header = 0x15, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount2 = { .header = 0x95, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount6 = { .header = 0x95, .data = { 0x06, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportSize1 = { .header = 0x75, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount2 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount6 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x06, 0x00 } };
static const USB_HID_Short_Item_t hidReportSize1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsageConsumerControl = { .header = 0x09, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsagePageConsumer = { .header = 0x05, .data = { 0x0C, 0x00 }, .location = 0x00 };
/*
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
*/
static const USB_HID_Report_Element_t hidReportPageConsumer = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 2, 0, 0 )
};
/*
* Define configurable items in the HID Report descriptor.
*/
static USB_HID_Short_Item_t hidUsageByte0Bit5 = { .header = 0x09, .data = { 0xE2, 0x00 }, .location = 0x50 }; // Mute
static USB_HID_Short_Item_t hidUsageByte0Bit4 = { .header = 0x09, .data = { 0xEA, 0x00 }, .location = 0x40 }; // Vol-
static USB_HID_Short_Item_t hidUsageByte0Bit3 = { .header = 0x09, .data = { 0xE9, 0x00 }, .location = 0x30 }; // Vol+
static USB_HID_Short_Item_t hidUsageByte0Bit2 = { .header = 0x09, .data = { 0xB6, 0x00 }, .location = 0x20 }; // Scan Prev
static USB_HID_Short_Item_t hidUsageByte0Bit1 = { .header = 0x09, .data = { 0xB5, 0x00 }, .location = 0x10 }; // Scan Next
static USB_HID_Short_Item_t hidUsageByte0Bit0 = { .header = 0x09, .data = { 0xB0, 0x00 }, .location = 0x00 }; // Play
static USB_HID_Report_Element_t hidUsageByte0Bit5 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE2, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
}; // Mute
static USB_HID_Report_Element_t hidUsageByte0Bit4 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xEA, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 4)
}; // Vol-
static USB_HID_Report_Element_t hidUsageByte0Bit3 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE9, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 3)
}; // Vol+
static USB_HID_Report_Element_t hidUsageByte0Bit2 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB6, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 2)
}; // Scan Prev
static USB_HID_Report_Element_t hidUsageByte0Bit1 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB5, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 1)
}; // Scan Next
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB0, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 0)
}; // Play
/*
* List the configurable items in the HID Report descriptor.
* List the configurable elements in the HID Report descriptor.
*/
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
@@ -73,27 +127,28 @@ static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
};
/*
* List Usage pages in the HID Report descriptor, one per byte.
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
* If not using report IDs - still have one with report ID 0
*/
static const USB_HID_Short_Item_t* const hidUsagePages[] = {
&hidUsagePageConsumer
static const USB_HID_Report_Element_t* const hidReports[] = {
&hidReportPageConsumer
};
/*
* List all items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
&hidUsagePageConsumer,
&(hidReportPageConsumer.item),
&hidUsageConsumerControl,
&hidCollectionApplication,
&hidLogicalMinimum0,
&hidLogicalMaximum1,
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
&hidUsageByte0Bit3,
&hidUsageByte0Bit4,
&hidUsageByte0Bit5,
&(hidUsageByte0Bit0.item),
&(hidUsageByte0Bit1.item),
&(hidUsageByte0Bit2.item),
&(hidUsageByte0Bit3.item),
&(hidUsageByte0Bit4.item),
&(hidUsageByte0Bit5.item),
&hidReportSize1,
&hidReportCount6,
&hidInputDataVar,
@@ -104,9 +159,10 @@ static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
};
/*
* Define the length of the HID Report.
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
* Define the number of HID Reports
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
*/
#define HID_REPORT_LENGTH ( 1 )
#define HID_REPORT_COUNT ( 1 )
#endif // __hid_report_descriptor_h__

View File

@@ -3,7 +3,7 @@
#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__
#include "xua_hid_report_descriptor.h"
#include "xua_hid_report.h"
#if 0
/* Existing static report descriptor kept for reference */
@@ -32,38 +32,92 @@ unsigned char hidReportDescriptor[] =
/*
* Define non-configurable items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t hidCollectionApplication = { .header = 0xA1, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionEnd = { .header = 0xC0, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionApplication = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionEnd = {
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidInputConstArray = { .header = 0x81, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputDataVar = { .header = 0x81, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputConstArray = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidInputDataVar = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = { .header = 0x25, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = { .header = 0x25, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = { .header = 0x15, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount2 = { .header = 0x95, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount6 = { .header = 0x95, .data = { 0x06, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportSize1 = { .header = 0x75, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount2 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount6 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x06, 0x00 } };
static const USB_HID_Short_Item_t hidReportSize1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsageConsumerControl = { .header = 0x09, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsagePageConsumer = { .header = 0x05, .data = { 0x0C, 0x00 }, .location = 0x00 };
/*
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
*/
static const USB_HID_Report_Element_t hidReportPageConsumer = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 2, 0, 0 )
};
/*
* Define configurable items in the HID Report descriptor.
*/
static USB_HID_Short_Item_t hidUsageByte0Bit5 = { .header = 0x09, .data = { 0xE2, 0x00 }, .location = 0x50 }; // Mute
static USB_HID_Short_Item_t hidUsageByte0Bit4 = { .header = 0x09, .data = { 0xEA, 0x00 }, .location = 0x40 }; // Vol-
static USB_HID_Short_Item_t hidUsageByte0Bit3 = { .header = 0x09, .data = { 0xE9, 0x00 }, .location = 0x30 }; // Vol+
static USB_HID_Short_Item_t hidUsageByte0Bit2 = { .header = 0x09, .data = { 0xB6, 0x00 }, .location = 0x20 }; // Scan Prev
static USB_HID_Short_Item_t hidUsageByte0Bit1 = { .header = 0x09, .data = { 0xB5, 0x00 }, .location = 0x10 }; // Scan Next
static USB_HID_Short_Item_t hidUsageByte0Bit0 = { .header = 0x09, .data = { 0xB0, 0x00 }, .location = 0x00 }; // Play
static USB_HID_Report_Element_t hidUsageByte0Bit5 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE2, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
}; // Mute
static USB_HID_Report_Element_t hidUsageByte0Bit4 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xEA, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 4)
}; // Vol-
static USB_HID_Report_Element_t hidUsageByte0Bit3 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE9, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 3)
}; // Vol+
static USB_HID_Report_Element_t hidUsageByte0Bit2 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB6, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 2)
}; // Scan Prev
static USB_HID_Report_Element_t hidUsageByte0Bit1 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB5, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 1)
}; // Scan Next
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB0, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 0)
}; // Play
/*
* List the configurable items in the HID Report descriptor.
* List the configurable elements in the HID Report descriptor.
*/
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
@@ -73,27 +127,28 @@ static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
};
/*
* List Usage pages in the HID Report descriptor, one per byte.
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
* If not using report IDs - still have one with report ID 0
*/
static const USB_HID_Short_Item_t* const hidUsagePages[] = {
&hidUsagePageConsumer
static const USB_HID_Report_Element_t* const hidReports[] = {
&hidReportPageConsumer
};
/*
* List all items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
&hidUsagePageConsumer,
&(hidReportPageConsumer.item),
&hidUsageConsumerControl,
&hidCollectionApplication,
&hidLogicalMinimum0,
&hidLogicalMaximum1,
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
&hidUsageByte0Bit3,
&hidUsageByte0Bit4,
&hidUsageByte0Bit5,
&(hidUsageByte0Bit0.item),
&(hidUsageByte0Bit1.item),
&(hidUsageByte0Bit2.item),
&(hidUsageByte0Bit3.item),
&(hidUsageByte0Bit4.item),
&(hidUsageByte0Bit5.item),
&hidReportSize1,
&hidReportCount6,
&hidInputDataVar,
@@ -104,9 +159,10 @@ static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
};
/*
* Define the length of the HID Report.
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
* Define the number of HID Reports
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
*/
#define HID_REPORT_LENGTH ( 1 )
#define HID_REPORT_COUNT ( 1 )
#endif // __hid_report_descriptor_h__

View File

@@ -3,7 +3,7 @@
#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__
#include "xua_hid_report_descriptor.h"
#include "xua_hid_report.h"
#if 0
/* Existing static report descriptor kept for reference */
@@ -32,38 +32,91 @@ unsigned char hidReportDescriptor[] =
/*
* Define non-configurable items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t hidCollectionApplication = { .header = 0xA1, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionEnd = { .header = 0xC0, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionApplication = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionEnd = {
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidInputConstArray = { .header = 0x81, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputDataVar = { .header = 0x81, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputConstArray = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidInputDataVar = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = { .header = 0x25, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = { .header = 0x25, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = { .header = 0x15, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount2 = { .header = 0x95, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount6 = { .header = 0x95, .data = { 0x06, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportSize1 = { .header = 0x75, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount2 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount6 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x06, 0x00 } };
static const USB_HID_Short_Item_t hidReportSize1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsageConsumerControl = { .header = 0x09, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsagePageConsumer = { .header = 0x05, .data = { 0x0C, 0x00 }, .location = 0x00 };
/*
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
*/
static const USB_HID_Report_Element_t hidReportPageConsumer = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 1, 0, 0 ) };
/*
* Define configurable items in the HID Report descriptor.
*/
static USB_HID_Short_Item_t hidUsageByte0Bit5 = { .header = 0x09, .data = { 0xE2, 0x00 }, .location = 0x50 }; // Mute
static USB_HID_Short_Item_t hidUsageByte0Bit4 = { .header = 0x09, .data = { 0xEA, 0x00 }, .location = 0x40 }; // Vol-
static USB_HID_Short_Item_t hidUsageByte0Bit3 = { .header = 0x09, .data = { 0xE9, 0x00 }, .location = 0x30 }; // Vol+
static USB_HID_Short_Item_t hidUsageByte0Bit2 = { .header = 0x09, .data = { 0xB6, 0x00 }, .location = 0x20 }; // Scan Prev
static USB_HID_Short_Item_t hidUsageByte0Bit1 = { .header = 0x09, .data = { 0xB5, 0x00 }, .location = 0x10 }; // Scan Next
static USB_HID_Short_Item_t hidUsageByte0Bit0 = { .header = 0x09, .data = { 0xB0, 0x00 }, .location = 0x00 }; // Play
static USB_HID_Report_Element_t hidUsageByte0Bit5 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE2, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 0, 0, 5 )
}; // Mute
static USB_HID_Report_Element_t hidUsageByte0Bit4 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xEA, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 0, 0, 4 )
}; // Vol-
static USB_HID_Report_Element_t hidUsageByte0Bit3 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE9, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 0, 0, 3 )
}; // Vol+
static USB_HID_Report_Element_t hidUsageByte0Bit2 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB6, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 0, 0, 2 )
}; // Scan Prev
static USB_HID_Report_Element_t hidUsageByte0Bit1 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB5, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 0, 0, 1 )
}; // Scan Next
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xB0, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 0, 0, 0 )
}; // Play
/*
* List the configurable items in the HID Report descriptor.
*/
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
@@ -73,27 +126,28 @@ static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
};
/*
* List Usage pages in the HID Report descriptor, one per byte.
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
* If not using report IDs - still have one with report ID 0
*/
static const USB_HID_Short_Item_t* const hidUsagePages[] = {
&hidUsagePageConsumer
static const USB_HID_Report_Element_t* const hidReports[] = {
&hidReportPageConsumer
};
/*
* List all items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
&hidUsagePageConsumer,
static const USB_HID_Short_Item_t * const hidReportDescriptorItems[] = {
&(hidReportPageConsumer.item),
&hidUsageConsumerControl,
&hidCollectionApplication,
&hidLogicalMinimum0,
&hidLogicalMaximum1,
&hidUsageByte0Bit0,
&hidUsageByte0Bit1,
&hidUsageByte0Bit2,
&hidUsageByte0Bit3,
&hidUsageByte0Bit4,
&hidUsageByte0Bit5,
&(hidUsageByte0Bit0.item),
&(hidUsageByte0Bit1.item),
&(hidUsageByte0Bit2.item),
&(hidUsageByte0Bit3.item),
&(hidUsageByte0Bit4.item),
&(hidUsageByte0Bit5.item),
&hidReportSize1,
&hidReportCount6,
&hidInputDataVar,
@@ -104,9 +158,10 @@ static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
};
/*
* Define the length of the HID Report.
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
* Define the number of HID Reports
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
*/
#define HID_REPORT_LENGTH ( 1 )
#define HID_REPORT_COUNT ( 1 )
#endif // __hid_report_descriptor_h__

View File

@@ -1244,10 +1244,6 @@ enum USBEndpointNumber_Out
#define MAX_VOL (0x20000000)
#if defined(SU1_ADC_ENABLE) && (SU1_ADC_ENABLE == 0)
#undef SU1_ADC_ENABLE
#endif
#if defined(LEVEL_METER_LEDS) && !defined(LEVEL_UPDATE_RATE)
#define LEVEL_UPDATE_RATE 400000
#endif

View File

@@ -1,8 +1,8 @@
VERSION = 2.0.1
VERSION = 3.0.0
DEPENDENT_MODULES = lib_logging(>=3.0.0) \
lib_xassert(>=4.0.0) \
lib_xud(>=1.2.0) \
lib_xud(>=2.0.1) \
lib_spdif(>=4.0.0) \
lib_mic_array(>=4.0.0)

View File

@@ -72,13 +72,8 @@
//int ksp_enter, ksp_exit, r11_store;
#if defined(__XS2A__) || defined(__XS3A__)
#define ISSUE_MODE_SINGLE ".issue_mode single\n"
#define ISSUE_MODE_DUAL ".issue_mode dual\n"
#else
#define ISSUE_MODE_SINGLE
#define ISSUE_MODE_DUAL
#endif
#define do_interrupt_handler(f,args) \
asm(ISSUE_MODE_SINGLE\

View File

@@ -21,9 +21,10 @@
#include "testct_byref.h"
#if( 0 < HID_CONTROLS )
#include "xua_hid_report_descriptor.h"
#include "xua_hid_report.h"
#include "user_hid.h"
unsigned char g_hidData[HID_MAX_DATA_BYTES] = {0};
#include "xua_hid.h"
unsigned char g_hidData[HID_MAX_DATA_BYTES] = {0U};
#endif
void GetADCCounts(unsigned samFreq, int &min, int &mid, int &max);
@@ -372,10 +373,16 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#endif
#if( 0 < HID_CONTROLS )
{
int hidDataLength = hidGetReportLength();
XUD_SetReady_In(ep_hid, g_hidData, hidDataLength);
}
UserHIDInit();
while (!hidIsReportDescriptorPrepared())
;
/* Get the a report - we don't really care which it is, so long as there's some data we can grab. */
int hidReportLength = (int) UserHIDGetData(hidGetNextValidReportId(0), g_hidData);
XUD_SetReady_In(ep_hid, g_hidData, hidReportLength);
#endif
#if (AUDIO_CLASS == 1)
@@ -887,11 +894,22 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#if( 0 < HID_CONTROLS )
/* HID Report Data */
case XUD_SetData_Select(c_hid, ep_hid, result):
case (hidIsChangePending(0U) || !HidIsSetIdleSilenced(0U)) => XUD_SetData_Select(c_hid, ep_hid, result):
{
int hidDataLength = hidGetReportLength();
UserHIDGetData(g_hidData);
XUD_SetReady_In(ep_hid, g_hidData, hidDataLength);
timer tmr;
unsigned reportTime;
tmr :> reportTime;
for(unsigned id = hidIsReportIdInUse(); id < hidGetReportIdLimit(); ++id) {
if(0U == id || (hidIsChangePending(id) || !HidIsSetIdleSilenced(id))) {
hidCaptureReportTime(id, reportTime);
int hidDataLength = (int) UserHIDGetData(id, g_hidData);
XUD_SetReady_In(ep_hid, g_hidData, hidDataLength);
hidCalcNextReportTime(id);
hidClearChangePending(id);
break;
}
}
}
break;
#endif

View File

@@ -66,7 +66,7 @@ enum USBInterfaceNumber
INTERFACE_COUNT /* End marker */
};
#if( 0 < HID_CONTROLS )
#ifndef ENDPOINT_INT_INTERVAL_IN_HID
#define ENDPOINT_INT_INTERVAL_IN_HID 0x08
#endif

View File

@@ -28,7 +28,7 @@
#if( 0 < HID_CONTROLS )
#include "hid.h"
#include "xua_hid.h"
#include "xua_hid_report_descriptor.h"
#include "xua_hid_report.h"
#endif
#if DSD_CHANS_DAC > 0
@@ -525,6 +525,7 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, NULLABLE_RESOURCE(c
#endif
#if( 0 < HID_CONTROLS )
hidReportInit();
hidPrepareReportDescriptor();
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();

View File

@@ -196,14 +196,6 @@ in port p_pdm_mclk = PORT_PDM_MCLK;
#endif
#endif
#if (defined(__XS2A__) && (ADAT_RX))
/* Cannot use default clock (CLKBLK_REF) for ADAT RX since it is tied to the
60MHz USB clock on XS2 processors. */
on tile[XUD_TILE] : clock clk_adat_rx = CLKBLK_ADAT_RX;
#endif
on tile[AUDIO_IO_TILE] : clock clk_audio_mclk = CLKBLK_MCLK; /* Master clock */
#if(AUDIO_IO_TILE != XUD_TILE) && XUA_USB_EN
@@ -214,15 +206,6 @@ on tile[XUD_TILE] : in port p_mclk_in_usb = PORT_MCLK_IN_USB;
on tile[AUDIO_IO_TILE] : clock clk_audio_bclk = CLKBLK_I2S_BIT; /* Bit clock */
/* L/G Series needs a port to use for USB reset */
#if ((defined(__XS2A__) || defined (__XS3A__)) && defined(PORT_USB_RESET))
/* This define is checked since it could be on a shift reg or similar */
on tile[XUD_TILE] : out port p_usb_rst = PORT_USB_RESET;
#else
#define p_usb_rst null
#endif
#ifdef IAP
/* I2C ports - in a struct for use with module_i2c_shared & module_i2c_simple/module_i2c_single_port */
#ifdef PORT_I2C
@@ -443,7 +426,7 @@ void SpdifTxWrapper(chanend c_spdif_tx)
}
#endif
void usb_audio_io(chanend ?c_aud_in, chanend ?c_adc,
void usb_audio_io(chanend ?c_aud_in,
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
chanend c_spdif_tx,
#endif
@@ -571,11 +554,6 @@ int main()
chan c_ea_data;
#endif
#endif
#ifdef SU1_ADC_ENABLE
chan c_adc;
#else
#define c_adc null
#endif
#ifdef MIXER
chan c_mix_ctl;
@@ -659,7 +637,7 @@ int main()
on tile[AUDIO_IO_TILE]:
{
usb_audio_io(c_mix_out, c_adc
usb_audio_io(c_mix_out
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
@@ -725,11 +703,6 @@ int main()
{
set_thread_fast_mode_on();
#if defined(__XS2A__)
/* Can't use REF clock as this is usb clock */
set_port_clock(p_adat_rx, clk_adat_rx);
start_clock(clk_adat_rx);
#endif
while (1)
{
adatReceiver48000(p_adat_rx, c_adat_rx);
@@ -765,11 +738,6 @@ int main()
#endif /*MIC_PROCESSING_USE_INTERFACE*/
#endif /*XUA_NUM_PDM_MICS > 0*/
#endif /*PDM_RECORD*/
#ifdef SU1_ADC_ENABLE
xs1_su_adc_service(c_adc);
#endif
}
return 0;

View File

@@ -1,13 +1,9 @@
// Copyright 2018-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
//#include "devicedefines.h"
#define MAX_MIX_COUNT 8
#define MIX_INPUTS 18
#if defined(__XS2A__) || defined(__XS3A__)
#define DOMIX_TOP(i) \
.cc_top doMix##i.function,doMix##i; \
.align 4 ;\
@@ -50,52 +46,6 @@ doMix##i##: ;\
.size doMix##i, .-doMix##i; \
.cc_bottom doMix##i##.function;
#else
#define DOMIX_TOP(i) \
.cc_top doMix##i.function,doMix##i; \
.align 4 ;\
.globl doMix##i ;\
.type doMix##i, @function ;\
.globl doMix##i##.nstackwords ;\
.globl doMix##i##.maxthreads ; \
.globl doMix##i##.maxtimers ; \
.globl doMix##i##.maxchanends ; \
.globl doMix##i##.maxsync ;\
.linkset doMix##i##.locnoside, 1; \
.linkset doMix##i##.locnochandec, 1;\
.linkset doMix##i##.nstackwords, 0 ;\
.linkset doMix##i##.maxchanends, 0 ;\
.linkset doMix##i##.maxtimers, 0 ;\
.linkset doMix##i##.maxthreads, 1; \
doMix##i##: ;\
set cp, r0; \
set dp, r1; \
lsub r0, r1, r0, r0, r0;\
.label_##i##:
#define DOMIX_BOT(i) \
ldap r11, _dp; \
set dp, r11;\
ldap r11, _cp;\
set cp, r11;\
\
mov r0, r1;\
ldc r2, 0x19;\
sext r0, r2;\
eq r0, r0, r1;\
bf r0, .L20; \
\
shl r0, r1, 0x7;\
retsp 0x0;\
\
\
.size doMix##i, .-doMix##i; \
.cc_bottom doMix##i##.function;
#endif
#define N MIX_INPUTS
#define BODY(i) \
ldw r2,cp[i]; \
@@ -115,8 +65,6 @@ doMix##i##: ;\
retsp 0x0; \
#if(MAX_MIX_COUNT > 0)
DOMIX_TOP(0)
#include "repeat.h"

View File

@@ -62,37 +62,12 @@ unsigned int divide, unsigned curSamFreq)
}
#endif
#if defined(__XS2A__) || defined(__XS3A__)
unsafe
{
/* Clock bitclock clock block from master clock pin (divided) */
configure_clock_src_divide(clk_audio_bclk, (port) p_mclk_in, (divide/2));
configure_port_clock_output(p_bclk, clk_audio_bclk);
}
#else
#error XS1 no longer supported in audio core
/* For a divide of one (i.e. bitclock == master-clock) BClk is set to clock_output mode.
* In this mode it outputs an edge clock on every tick of itsassociated clock_block.
*
* For all other divides, BClk is clocked by the master clock and data
* will be output to p_bclk to generate the bit clock.
*/
if (divide == 1) /* e.g. 176.4KHz from 11.2896 */
{
configure_port_clock_output(p_bclk, clk_audio_mclk);
/* Generate bit clock block straight from mclk */
configure_clock_src(clk_audio_bclk, p_mclk_in);
}
else
{
/* bit clock port from master clock clock-clock block */
configure_out_port_no_ready(p_bclk, clk_audio_mclk, 0);
/* Generate bit clock block from pin */
configure_clock_src(clk_audio_bclk, p_bclk);
}
#endif
if(!isnull(p_lrclk))
{

View File

@@ -38,8 +38,6 @@ void device_reboot(void)
/* Disconnect from bus */
unsigned data[] = {4};
write_periph_32(usb_tile, XS2_SU_PERIPH_USB_ID, XS1_GLX_PER_UIFM_FUNC_CONTROL_NUM, 1, data);
#elif defined(__XS3A__)
#warning Assuming that tile reset also resets USB in XS3 architectures
#endif
tileArrayLength = sizeof(tile)/sizeof(tileref);

View File

@@ -9,9 +9,9 @@
#define CLKBLK_MIDI XS1_CLKBLK_REF;
#define CLKBLK_SPDIF_TX XS1_CLKBLK_1
#define CLKBLK_SPDIF_RX XS1_CLKBLK_1
#define CLKBLK_MCLK XS1_CLKBLK_4
#define CLKBLK_MCLK XS1_CLKBLK_2
#define CLKBLK_FLASHLIB XS1_CLKBLK_3 /* Clock block for use by flash lib */
#define CLKBLK_ADAT_RX XS1_CLKBLK_REF /* Use REF for ADAT_RX on U/x200 series */
#define CLKBLK_I2S_BIT XS1_CLKBLK_5
#define CLKBLK_I2S_BIT XS1_CLKBLK_3
#endif /* _UAC_HWRESOURCES_H_ */

View File

@@ -1,36 +1,60 @@
// Copyright 2013-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
* @brief Human Interface Device (HID) API
*
* This file defines the Application Programming Interface (API) used to record HID
* events and retrieve a HID Report for sending to a host.
* The using application has the responsibility to fulfill this API.
* Document section numbers refer to the HID Device Class Definition, version 1.11.
*/
#ifndef __USER_HID_H__
#define __USER_HID_H__
#include <stddef.h>
/**
* \brief HID event
*
* This struct identifies the location within the HID Report for an event and
* The value to report for that location.
* This struct identifies:
* - the HID Report that reports an event, i.e., the ID,
* - the location within the HID Report for the event, i.e., the byte and bit, and
* - the value to report for that location (typically interpreted as a Boolean).
* It assumes only single bit flags within the HID Report.
*/
typedef struct hidEvent_t {
unsigned bit;
unsigned byte;
unsigned id;
unsigned value;
} hidEvent_t;
#define HID_MAX_DATA_BYTES 4
#define HID_MAX_DATA_BYTES ( 4 )
#define HID_EVENT_INVALID_ID ( 0x100 )
#if( 0 < HID_CONTROLS )
/**
* \brief Get the data for the next HID report
* \brief Get the data for the next HID Report
*
* \note This function returns the HID data as a list of unsigned char because the
* \c XUD_SetReady_In() accepts data for transmission to the USB Host using
* this type.
*
* \param{out} hidData The HID data
* \param[in] id The HID Report ID (see 5.6, 6.2.2.7, 8.1 and 8.2)
* Set to zero if the application provides only one HID Report
* which does not include a Report ID
* \param[out] hidData The HID data
* If using Report IDs, this function places the Report ID in
* the first element; otherwise the first element holds the
* first byte of HID event data.
*
* \returns The length of the HID Report in the \a hidData argument
* \retval Zero means no new HID event data has been recorded for the given \a id
*/
void UserHIDGetData( unsigned char hidData[ HID_MAX_DATA_BYTES ]);
size_t UserHIDGetData( const unsigned id, unsigned char hidData[ HID_MAX_DATA_BYTES ]);
/**
* \brief Initialize HID processing
@@ -40,15 +64,18 @@ void UserHIDInit( void );
/**
* \brief Record that a HID event has occurred
*
* \param{in} hidEvent A list of events which have occurred.
* Each element specifies a bit and byte in the HID Report and the value for it.
* \param{in} hidEventCnt The length of the \a hidEvent list.
* \param[in] hidEvent A list of events which have occurred.
* Each element specifies a HID Report ID, a bit and byte
* within the HID Report and the value for it.
* Set the Report ID to zero if not using Report IDs
* (see 5.6, 6.2.2.7, 8.1 and 8.2).
* \param[in] hidEventCnt The length of the \a hidEvent list.
*
* \returns A Boolean flag indicating the status of the operation
* \retval False No recording of the event(s) occurred
* \retval True Recording of the event(s) occurred
* \returns The index of the first unrecorded event in \a hidEvent
* \retval Zero indicates no events were recorded
* \retval \a hidEventCnt indicates all events were recorded
*/
unsigned UserHIDRecordEvent( const hidEvent_t hidEvent[], const unsigned hidEventCnt );
size_t UserHIDRecordEvent( const hidEvent_t hidEvent[], const size_t hidEventCnt );
#endif /* ( 0 < HID_CONTROLS ) */
#endif /* __USER_HID_H__ */

View File

@@ -11,11 +11,12 @@
#include "flash_interface.h"
#include "dfu_interface.h"
#if defined(__XS3A__)
#define FLAG_ADDRESS 0xfffcc
#elif defined(__XS2A__)
#if defined(__XS2A__)
/* Note range 0x7FFC8 - 0x7FFFF guarenteed to be untouched by tools */
#define FLAG_ADDRESS 0x7ffcc
#else
/* Note range 0xFFFC8 - 0xFFFFF guarenteed to be untouched by tools */
#define FLAG_ADDRESS 0xfffcc
#endif
/* Store Flag to fixed address */

View File

@@ -7,38 +7,15 @@
#include "xud.h"
#include "xud_std_requests.h"
#include "xua_hid.h"
#include "xua_hid_report.h"
#if( 0 < HID_CONTROLS )
#define MS_IN_TICKS 100000U
static unsigned s_hidChangePending = 0U;
static unsigned s_hidCurrentPeriod = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
static unsigned s_hidIdleActive = 0U;
static unsigned s_hidIndefiniteDuration = 0U;
static unsigned s_hidNextReportTime = 0U;
static unsigned s_hidReportTime = 0U;
unsafe {
volatile unsigned * unsafe s_hidChangePendingPtr = &s_hidChangePending;
}
static unsigned HidCalcNewReportTime( const unsigned currentPeriod, const unsigned reportTime, const unsigned reportToSetIdleInterval, const unsigned newPeriod );
static unsigned HidCalcReportToSetIdleInterval( const unsigned reportTime );
static unsigned HidFindSetIdleActivationPoint( const unsigned currentPeriod, const unsigned timeWithinPeriod );
static XUD_Result_t HidProcessSetIdleRequest( XUD_ep c_ep0_out, XUD_ep c_ep0_in, USB_SetupPacket_t &sp );
static unsigned HidTimeDiff( const unsigned earlierTime, const unsigned laterTime );
void HidCalcNextReportTime( void )
{
s_hidNextReportTime = s_hidReportTime + s_hidCurrentPeriod;
}
void HidCaptureReportTime( void )
{
timer tmr;
tmr :> s_hidReportTime;
}
XUD_Result_t HidInterfaceClassRequests(
XUD_ep c_ep0_out,
XUD_ep c_ep0_in,
@@ -58,41 +35,22 @@ XUD_Result_t HidInterfaceClassRequests(
return result;
}
void HidClearChangePending( void )
unsigned HidIsSetIdleSilenced( const unsigned id )
{
unsafe {
*s_hidChangePendingPtr = 0U;
}
}
unsigned isSilenced = hidIsIdleActive( id );
unsigned HidIsChangePending( void )
{
return( s_hidChangePending != 0 );
}
unsigned HidIsSetIdleSilenced( void )
{
unsigned isSilenced = s_hidIdleActive;
if( s_hidIdleActive ) {
if( !isSilenced ) {
unsigned currentTime;
// Use inline assembly to access the time without creating a side-effect.
// The mapper complains if the time comes from an XC timer because this function is called in the guard of a select case.
// Appearently the use of a timer creates a side-effect that prohibits the operation of the select functionality.
asm volatile( "gettime %0" : "=r" ( currentTime ));
isSilenced = ( s_hidIndefiniteDuration || ( timeafter( s_hidNextReportTime, currentTime )));
isSilenced = ( 0U == hidGetReportPeriod( id ) || ( timeafter( hidGetNextReportTime( id ), currentTime )));
}
return isSilenced;
}
void HidSetChangePending( void )
{
unsafe {
*s_hidChangePendingPtr = 1;
}
}
/**
* \brief Calculate the timer value for sending the next HID Report.
*
@@ -112,7 +70,7 @@ void HidSetChangePending( void )
*/
static unsigned HidCalcNewReportTime( const unsigned currentPeriod, const unsigned reportTime, const unsigned reportToSetIdleInterval, const unsigned newPeriod )
{
unsigned nextReportTime = 0;
unsigned nextReportTime = 0U;
if( HidFindSetIdleActivationPoint( currentPeriod, reportToSetIdleInterval )) {
/* Activate immediately after sending the next HID Report */
@@ -171,6 +129,31 @@ static unsigned HidFindSetIdleActivationPoint( const unsigned currentPeriod, con
return result;
}
/**
* \brief Configure a hid report's next report time and idle status based on a setidle request
*
* \param[in] reportId -- The report ID to modify
* \param[in] reportDuration -- The duration of the setidle request
*
*/
static void HidUpdateReportPeriod( unsigned reportId, unsigned reportDuration ) {
unsigned currentPeriod = hidGetReportPeriod( reportId );
hidSetIdle( reportId, ( 0U == reportDuration ) || ( ENDPOINT_INT_INTERVAL_IN_HID < reportDuration ));
if( hidIsIdleActive( reportId )) {
unsigned reportTime = hidGetReportTime( reportId );
unsigned reportToSetIdleInterval = HidCalcReportToSetIdleInterval( reportTime );
unsigned nextReportTime = HidCalcNewReportTime( currentPeriod, reportTime, reportToSetIdleInterval, reportDuration * MS_IN_TICKS );
hidSetNextReportTime( reportId, nextReportTime );
currentPeriod = reportDuration * MS_IN_TICKS;
} else {
currentPeriod = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
}
hidSetReportPeriod( reportId, currentPeriod );
}
/**
* \brief Process a Set Idle request
*
@@ -208,20 +191,24 @@ static XUD_Result_t HidProcessSetIdleRequest( XUD_ep c_ep0_out, XUD_ep c_ep0_in,
Any Interface value other than INTERFACE_NUMBER_HID indicates an error by the USB Host.
*/
if(( 0U == reportId ) && ( INTERFACE_NUMBER_HID == interfaceNum )) {
s_hidIdleActive = (( 0U == duration ) || ( ENDPOINT_INT_INTERVAL_IN_HID < duration ));
if( INTERFACE_NUMBER_HID == interfaceNum ) {
if( hidIsReportIdValid( reportId ) ) {
HidUpdateReportPeriod( reportId, duration );
if( s_hidIdleActive ) {
unsigned reportToSetIdleInterval = HidCalcReportToSetIdleInterval( s_hidReportTime );
s_hidNextReportTime = HidCalcNewReportTime( s_hidCurrentPeriod, s_hidReportTime, reportToSetIdleInterval, duration * MS_IN_TICKS );
s_hidCurrentPeriod = duration * MS_IN_TICKS;
s_hidIndefiniteDuration = ( 0U == duration );
} else {
s_hidCurrentPeriod = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
s_hidIndefiniteDuration = 0U;
result = XUD_DoSetRequestStatus( c_ep0_in );
}
else if ( reportId == 0U ) {
// Wildcard request - set all report IDs to idle
unsigned startReportId = hidGetNextValidReportId(reportId);
result = XUD_DoSetRequestStatus( c_ep0_in );
reportId = startReportId;
do {
HidUpdateReportPeriod( reportId, duration );
reportId = hidGetNextValidReportId( reportId );
} while( reportId != startReportId);
result = XUD_DoSetRequestStatus( c_ep0_in );
}
}
return result;

View File

@@ -0,0 +1,799 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <xs1.h>
#include "descriptor_defs.h"
#include "xua_hid_report.h"
#include "hid_report_descriptor.h"
#define HID_REPORT_ITEM_LOCATION_SIZE ( 1 )
#define HID_REPORT_DESCRIPTOR_ITEM_COUNT ( sizeof hidReportDescriptorItems / sizeof ( USB_HID_Short_Item_t* ))
#define HID_REPORT_DESCRIPTOR_MAX_LENGTH ( HID_REPORT_DESCRIPTOR_ITEM_COUNT * \
( sizeof ( USB_HID_Short_Item_t ) - HID_REPORT_ITEM_LOCATION_SIZE ))
/*
* Each element in s_hidChangePending corresponds to an element in hidReports.
*/
static unsigned s_hidChangePending[ HID_REPORT_COUNT ];
static unsigned char s_hidReportDescriptor[ HID_REPORT_DESCRIPTOR_MAX_LENGTH ];
static size_t s_hidReportDescriptorLength;
static unsigned s_hidReportDescriptorPrepared;
static unsigned s_hidCurrentPeriod[ HID_REPORT_COUNT ];
static unsigned s_hidIdleActive[ HID_REPORT_COUNT ];
static unsigned s_hidNextReportTime[ HID_REPORT_COUNT ];
static unsigned s_hidReportTime[ HID_REPORT_COUNT ];
/**
* @brief Get the bit position from the location of a report element
*
* Parameters:
*
* @param[in] location The \c location field from a \c USB_HID_Report_Element_t
*
* @return The bit position of the report element
*/
static unsigned hidGetElementBitLocation( const unsigned short location );
/**
* @brief Get the byte position from the location of a report element
*
* Parameters:
*
* @param[in] location The \c location field from a \c USB_HID_Report_Element_t
*
* @return The byte position of the report element within the HID report
*/
static unsigned hidGetElementByteLocation( const unsigned short location );
/**
* @brief Get the report identifier from the location of a report element
*
* Parameters:
*
* @param[in] location The \c location field from a \c USB_HID_Report_Element_t
*
* @return The report id of the report element within the HID report
*/
static unsigned hidGetElementReportId( const unsigned short location );
/**
* @brief Get the report length from the location of a report element
*
* Parameters:
*
* @param[in] location The \c location field from a \c USB_HID_Report_Element_t
*
* @return The length of the HID report
*/
static size_t hidGetElementReportLength( const unsigned short location );
/**
* @brief Get the number of data bytes from the header of an Item
*
* Parameters:
*
* @param[in] header The \c header field from a \c USB_HID_Short_Item
*
* @return The amount of data for the Item
*/
static unsigned hidGetItemSize( const unsigned char header );
/**
* @brief Get the Tag from the header of an Item
*
* Parameters:
*
* @param[in] header The \c header field from a \c USB_HID_Short_Item
*
* @return The Tag of the Item
*/
static unsigned hidGetItemTag( const unsigned char header );
/**
* @brief Get the Type from the header of an Item
*
* Parameters:
*
* @param[in] header The \c header field from a \c USB_HID_Short_Item
*
* @return The Type of the Item
*/
static unsigned hidGetItemType( const unsigned char header );
/**
* @brief Get the Usage Page number for a given byte in the HID Report
*
* Parameters:
*
* @param[in] id The HID Report ID for the Usage Page.
* A value of zero means the application does not use Report IDs.
*
* @return The USB HID Usage Page code or zero if the \a id parameter is out-of-range
*/
static unsigned hidGetUsagePage( const unsigned id );
/**
* @brief Translate an Item from the \c USB_HID_Short_Item format to raw bytes
*
* Parameters:
*
* @param[in] inPtr A pointer to a \c USB_HID_Short_Item
* @param[in,out] outPtrPtr A pointer to a pointer to the next available space in the raw
* byte buffer. Passed as a pointer to a pointer to allow this
* function to return the updated pointer to the raw byte buffer.
*
* @return The number of bytes placed in the raw byte buffer
*/
static size_t hidTranslateItem( const USB_HID_Short_Item_t* inPtr, unsigned char** outPtrPtr );
void hidCalcNextReportTime( const unsigned id )
{
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
s_hidNextReportTime[ idx ] = s_hidReportTime[ idx ] + s_hidCurrentPeriod[ idx ];
}
}
}
void hidCaptureReportTime( const unsigned id, const unsigned time )
{
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
s_hidReportTime[ idx ] = time;
}
}
}
void hidClearChangePending( const unsigned id )
{
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if(( id == 0U ) || ( id == hidGetElementReportId( hidReports[ idx ]->location ))) {
s_hidChangePending[ idx ] = 0U;
break;
}
}
}
static unsigned hidGetElementBitLocation( const unsigned short location )
{
unsigned bBit = ( location & HID_REPORT_ELEMENT_LOC_BIT_MASK ) >> HID_REPORT_ELEMENT_LOC_BIT_SHIFT;
return bBit;
}
static unsigned hidGetElementByteLocation( const unsigned short location )
{
unsigned bByte = ( location & HID_REPORT_ELEMENT_LOC_BYTE_MASK ) >> HID_REPORT_ELEMENT_LOC_BYTE_SHIFT;
return bByte;
}
static unsigned hidGetElementReportId( const unsigned short location )
{
unsigned bReportId = ( location & HID_REPORT_ELEMENT_LOC_ID_MASK ) >> HID_REPORT_ELEMENT_LOC_ID_SHIFT;
return bReportId;
}
static size_t hidGetElementReportLength( const unsigned short location )
{
size_t bReportLen = (size_t)( location & HID_REPORT_ELEMENT_LOC_LEN_MASK ) >> HID_REPORT_ELEMENT_LOC_LEN_SHIFT;
return bReportLen;
}
static unsigned hidGetItemSize( const unsigned char header )
{
unsigned bSize = ( header & HID_REPORT_ITEM_HDR_SIZE_MASK ) >> HID_REPORT_ITEM_HDR_SIZE_SHIFT;
return bSize;
}
static unsigned hidGetItemTag( const unsigned char header )
{
unsigned bTag = ( header & HID_REPORT_ITEM_HDR_TAG_MASK ) >> HID_REPORT_ITEM_HDR_TAG_SHIFT;
return bTag;
}
static unsigned hidGetItemType( const unsigned char header )
{
unsigned bType = ( header & HID_REPORT_ITEM_HDR_TYPE_MASK ) >> HID_REPORT_ITEM_HDR_TYPE_SHIFT;
return bType;
}
unsigned hidGetNextReportTime( const unsigned id ) {
unsigned retVal = 0U;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
retVal = s_hidNextReportTime[ idx ];
}
}
return retVal;
}
unsigned hidIsReportDescriptorPrepared( void )
{
return s_hidReportDescriptorPrepared;
}
unsigned char* hidGetReportDescriptor( void )
{
unsigned char* retVal = NULL;
if( s_hidReportDescriptorPrepared ) {
retVal = s_hidReportDescriptor;
}
return retVal;
}
size_t hidGetReportDescriptorLength( void )
{
size_t retVal = ( s_hidReportDescriptorPrepared ) ? s_hidReportDescriptorLength : 0U;
return retVal;
}
unsigned hidGetReportIdLimit ( void ) {
unsigned retVal = 0U;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
unsigned reportId = hidGetElementReportId( hidReports[ idx ]->location );
if( reportId >= retVal ) {
retVal = reportId + 1;
}
}
return retVal;
}
unsigned hidIsReportIdInUse ( void ) {
if ( hidGetElementReportId( hidReports[ 0 ]->location ) ) {
return 1;
}
return 0;
}
unsigned hidIsReportIdValid ( unsigned id ) {
size_t retVal = 0;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
unsigned reportId = hidGetElementReportId( hidReports[ idx ]->location );
if( reportId == id ) {
retVal = 1;
break;
}
}
return retVal;
}
unsigned hidGetNextValidReportId ( unsigned idPrev ) {
size_t retIndex = 0;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
unsigned reportId = hidGetElementReportId( hidReports[ idx ]->location );
if( reportId == idPrev ) {
retIndex = (idx + 1) % HID_REPORT_COUNT;
break;
}
}
return hidGetElementReportId( hidReports[ retIndex ]->location );
}
#define HID_CONFIGURABLE_ELEMENT_COUNT ( sizeof hidConfigurableElements / sizeof ( USB_HID_Report_Element_t* ))
unsigned hidGetReportItem(
const unsigned id,
const unsigned byte,
const unsigned bit,
unsigned char* const page,
unsigned char* const header,
unsigned char data[]
)
{
unsigned retVal = HID_STATUS_BAD_ID;
for( size_t elementIdx = 0U; elementIdx < HID_CONFIGURABLE_ELEMENT_COUNT; ++elementIdx ) {
USB_HID_Report_Element_t element = *hidConfigurableElements[ elementIdx ];
unsigned bBit = hidGetElementBitLocation( element.location );
unsigned bByte = hidGetElementByteLocation( element.location );
unsigned bId = hidGetElementReportId( element.location );
if( id == bId ) {
retVal = HID_STATUS_BAD_LOCATION;
if(( bit == bBit ) && ( byte == bByte )) {
*page = hidGetUsagePage( id );
*header = element.item.header;
for( size_t dataIdx = 0U; dataIdx < HID_REPORT_ITEM_MAX_SIZE; ++data, ++dataIdx ) {
*data = element.item.data[ dataIdx ];
}
retVal = HID_STATUS_GOOD;
break;
}
}
}
return retVal;
}
size_t hidGetReportLength( const unsigned id )
{
size_t retVal = 0U;
if( s_hidReportDescriptorPrepared ) {
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
retVal = hidGetElementReportLength( hidReports[ idx ]->location );
}
}
}
return retVal;
}
unsigned hidGetReportPeriod( const unsigned id )
{
unsigned retVal = 0U;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
retVal = s_hidCurrentPeriod[ idx ];
break;
}
}
return retVal;
}
unsigned hidGetReportTime( const unsigned id ) {
unsigned retVal = 0U;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
retVal = s_hidReportTime[ idx ];
}
}
return retVal;
}
static unsigned hidGetUsagePage( const unsigned id )
{
unsigned retVal = 0U;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
retVal = hidReports[ idx ]->item.data[ 0 ];
break;
}
}
return retVal;
}
unsigned hidIsChangePending( const unsigned id )
{
unsigned retVal = 0U;
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if( id == 0U && s_hidChangePending[ idx ] != 0U ) {
retVal = 1;
} else if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
retVal = ( s_hidChangePending[ idx ] != 0U );
break;
}
}
return retVal;
}
unsigned hidIsIdleActive( const unsigned id )
{
unsigned retVal = 0U;
if( 0U == id ) {
retVal = 1U;
}
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if( id == 0U ) {
retVal &= ( s_hidIdleActive[ idx ] != 0U );
} else if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
retVal = ( s_hidIdleActive[ idx ] != 0U );
break;
}
}
return retVal;
}
void hidPrepareReportDescriptor( void )
{
if( !s_hidReportDescriptorPrepared ) {
s_hidReportDescriptorLength = 0U;
unsigned char* ptr = s_hidReportDescriptor;
for( size_t idx = 0U; idx < HID_REPORT_DESCRIPTOR_ITEM_COUNT; ++idx ) {
s_hidReportDescriptorLength += hidTranslateItem( hidReportDescriptorItems[ idx ], &ptr );
}
s_hidReportDescriptorPrepared = 1U;
}
}
void hidReportInit( void )
{
for( unsigned idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
s_hidCurrentPeriod[ idx ] = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
}
memset( s_hidIdleActive, 0, sizeof( s_hidIdleActive ) );
memset( s_hidChangePending, 0, sizeof( s_hidChangePending ) );
}
void hidResetReportDescriptor( void )
{
s_hidReportDescriptorPrepared = 0U;
}
void hidSetChangePending( const unsigned id )
{
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
s_hidChangePending[ idx ] = 1U;
break;
}
}
}
void hidSetIdle( const unsigned id, const unsigned state )
{
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
s_hidIdleActive[ idx ] = ( state != 0U );
break;
}
}
}
void hidSetNextReportTime( const unsigned id, const unsigned time )
{
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx ) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
s_hidNextReportTime[ idx ] = time;
}
}
}
unsigned hidSetReportItem(
const unsigned id,
const unsigned byte,
const unsigned bit,
const unsigned char page,
const unsigned char header,
const unsigned char data[]
)
{
unsigned retVal = HID_STATUS_IN_USE;
if( !s_hidReportDescriptorPrepared ) {
retVal = HID_STATUS_BAD_ID;
unsigned bSize = hidGetItemSize( header );
unsigned bTag = hidGetItemTag ( header );
unsigned bType = hidGetItemType( header );
if(( HID_REPORT_ITEM_MAX_SIZE < bSize ) ||
( HID_REPORT_ITEM_USAGE_TAG != bTag ) ||
( HID_REPORT_ITEM_USAGE_TYPE != bType )) {
retVal = HID_STATUS_BAD_HEADER;
} else {
for( size_t elementIdx = 0U; elementIdx < HID_CONFIGURABLE_ELEMENT_COUNT; ++elementIdx ) {
USB_HID_Report_Element_t element = *hidConfigurableElements[ elementIdx ];
unsigned bBit = hidGetElementBitLocation( element.location );
unsigned bByte = hidGetElementByteLocation( element.location );
unsigned bId = hidGetElementReportId( element.location );
if( id == bId ) {
retVal = HID_STATUS_BAD_PAGE;
unsigned pg = hidGetUsagePage( id );
if( page == pg ) {
retVal = HID_STATUS_BAD_LOCATION;
if(( bit == bBit ) && ( byte == bByte )) {
element.item.header = header;
for( size_t dataIdx = 0U; dataIdx < bSize; ++dataIdx ) {
element.item.data[ dataIdx ] = data[ dataIdx ];
}
for( size_t dataIdx = bSize; dataIdx < HID_REPORT_ITEM_MAX_SIZE; ++dataIdx ) {
element.item.data[ dataIdx ] = 0U;
}
*hidConfigurableElements[ elementIdx ] = element;
retVal = HID_STATUS_GOOD;
break;
}
}
}
}
}
}
return retVal;
}
void hidSetReportPeriod( const unsigned id, const unsigned period )
{
for( size_t idx = 0U; idx < HID_REPORT_COUNT; ++idx) {
if( id == hidGetElementReportId( hidReports[ idx ]->location )) {
s_hidCurrentPeriod[ idx ] = period;
break;
}
}
}
static size_t hidTranslateItem( const USB_HID_Short_Item_t* inPtr, unsigned char** outPtrPtr )
{
size_t count = 0U;
*(*outPtrPtr)++ = inPtr->header;
++count;
unsigned dataLength = hidGetItemSize( inPtr->header );
for( size_t idx = 0U; idx < dataLength; ++idx ) {
*(*outPtrPtr)++ = inPtr->data[ idx ];
++count;
}
return count;
}
// hid_report_descriptor.h validation functions for development purposes
/**
* @brief Internal HID Report Descriptor validation state
*/
struct HID_validation_info {
int collectionOpenedCount; //!< Current count of open collections (to track that they are all closed)
int reportCount; //!< Current count of defined reports (to count them)
int currentReportIdx; //!< Index of current report in hidReports array
int currentConfigurableElementIdx; //!< Index of current configurable element in hidConfigurableElements array
unsigned char reportIds[HID_REPORT_COUNT]; // Array of report IDs (for general validation & duplication detection)
unsigned reportUsagePage[HID_REPORT_COUNT]; // Array of the usage page for each report (for general validation)
unsigned current_bit_size; // State tracker for the current set report bit width (todo: should technically be a stack)
unsigned current_bit_count; // State tracker for the current set report count (todo: should technically be a stack)
unsigned current_bit_offset; // Current bit offset into this report (for location validation)
};
/**
* @brief Validation step for hidReportValidate, checking the info struct to ensure correctness of Report IDs
*
* @param info The info struct that has been built by hidReportValidate to check
* @return unsigned HID_STATUS value
*/
static unsigned hidReportValidateInfoStructReportIDs( struct HID_validation_info *info ) {
if ( info->reportCount != HID_REPORT_COUNT) {
if ( !( info->reportCount == 0 && HID_REPORT_COUNT == 1 ) ) {
// (Only if report IDs are being used)
printf("Error: The number of actual reports does not match HID_REPORT_COUNT.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
}
for ( size_t idx1 = 0; idx1 < HID_REPORT_COUNT; ++idx1 ) {
for ( size_t idx2 = idx1 + 1; idx2 < HID_REPORT_COUNT; ++idx2 ) {
if ( info->reportIds[idx1] == info->reportIds[idx2] ) {
printf("Error: Duplicate report ID 0x%02x.\n", info->reportIds[idx1]);
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
}
}
for ( size_t idx = 0; idx < HID_REPORT_COUNT; ++idx ) {
if ( info->reportIds[idx] != hidGetElementReportId( hidReports[idx]->location ) ) {
printf("Error: Report ID in descriptor does not match report ID in hidReports.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
if ( info->reportCount && info->reportIds[idx] == 0 ) {
printf("Error: Report ID 0 is invalid.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
}
return HID_STATUS_GOOD;
}
/**
* @brief Validation step for hidReportValidate, checking reports are the correct length specified in their location field
*
* @param info The info struct that has been built by hidReportValidate to check
* @return unsigned HID_STATUS value
*/
static unsigned hidReportValidateInfoStructReportLength( struct HID_validation_info *info ) {
if ( info->current_bit_offset % 8 ) {
printf("Error: HID Report not byte aligned (%d bits).\n", info->current_bit_offset);
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
if ( ( info->current_bit_offset / 8 ) != hidGetElementReportLength( hidReports[info->currentReportIdx]->location ) ) {
printf("Error: Actual report length does not match value in location field %d != %d.\n",
( info->current_bit_offset / 8 ),
hidGetElementReportLength( hidReports[info->currentReportIdx]->location ));
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
return HID_STATUS_GOOD;
}
/**
* @brief Validation step for hidReportValidate, collections are correctly opened and closed
*
* @param info The info struct that has been built by hidReportValidate to check
* @return unsigned HID_STATUS value
*/
static unsigned hidReportValidateInfoStructCollections( struct HID_validation_info *info ) {
if ( info->collectionOpenedCount ) {
printf("Error: Collections not equally opened and closed.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
return HID_STATUS_GOOD;
}
/**
* @brief Validation step for hidReportValidate, High level - Checks the summarised information in the info struct by calling
* the subroutines for checking.
*
* @param info The info struct that has been built by hidReportValidate to check
* @return unsigned HID_STATUS value
*/
static unsigned hidReportValidateInfoStruct( struct HID_validation_info *info ) {
unsigned status = hidReportValidateInfoStructCollections( info );
if( status == HID_STATUS_GOOD ) {
status = hidReportValidateInfoStructReportIDs( info );
}
if( status == HID_STATUS_GOOD ) {
status = hidReportValidateInfoStructReportLength( info );
}
return status;
}
/**
* @brief Preparation step for hidReportValidate, Adds a report ID field into the information struct for validation
*
* @param info The info struct being built by hidReportValidate
* @param item The ReportId item being added
* @return unsigned HID_STATUS value
*/
static unsigned hidReportValidateAddReportId( struct HID_validation_info *info, const USB_HID_Short_Item_t *item ) {
if ( info->reportCount == 0 ) {
if ( info->current_bit_offset ) {
printf("Error: Some elements not associated with report ID.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
info->reportUsagePage[0] = 0;
} else {
unsigned status = hidReportValidateInfoStructReportLength( info );
if ( status ) {
return status;
}
}
if ( hidGetItemSize(item->header) != 1 ) {
printf("Error: ReportId field has invalid length %d (expected 1)\n", hidGetItemSize(item->header));
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
info->reportIds[info->reportCount] = item->data[0];
info->currentReportIdx = info->reportCount;
info->reportCount += 1;
info->current_bit_offset = 0;
if ( info->reportCount > HID_REPORT_COUNT ) {
printf("Error: HID_REPORT_COUNT does not match number of report IDs in descriptor.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
return HID_STATUS_GOOD;
}
/**
* @brief Preparation step for hidReportValidate, Adds a Usage Page field into the information struct for validation
*
* @param info The info struct being built by hidReportValidate
* @param item The UsagePage item being added
* @return unsigned HID_STATUS value
*/
static unsigned hidReportValidateAddUsagePageItem( struct HID_validation_info *info, const USB_HID_Short_Item_t *item ) {
if ( info->collectionOpenedCount == 0 ) {
return HID_STATUS_GOOD;
}
if ( info->reportUsagePage[info->currentReportIdx] ) {
printf("Error: Multiple usage pages per report ID not supported by this implementation.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
switch (hidGetItemSize(item->header)){
case 1:
info->reportUsagePage[info->currentReportIdx] = item->data[0];
break;
case 2:
info->reportUsagePage[info->currentReportIdx] = ((unsigned) item->data[1] << 8) + item->data[0];
break;
default:
printf("Error: Invalid size for UsagePage report descriptor item.\n");
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
return HID_STATUS_GOOD;
}
/**
* @brief Preparation step for hidReportValidate, Adds a Usage field into the information struct for validation
*
* @param info The info struct being built by hidReportValidate
* @param item The Usage item being added
* @return unsigned HID_STATUS value
*/
static unsigned hidReportValidateAddUsageItem( struct HID_validation_info *info, const USB_HID_Short_Item_t *item) {
if ( ( info->currentConfigurableElementIdx < HID_CONFIGURABLE_ELEMENT_COUNT ) &&
( &(hidConfigurableElements[info->currentConfigurableElementIdx]->item) == item ) ) {
USB_HID_Report_Element_t *element = hidConfigurableElements[info->currentConfigurableElementIdx];
unsigned bBit = hidGetElementBitLocation( element->location );
unsigned bByte = hidGetElementByteLocation( element->location );
unsigned bReportId = hidGetElementReportId( element->location );
if ( bBit != ( info->current_bit_offset % 8 ) || bByte != ( info->current_bit_offset / 8 ) ) {
printf("Error: Locator bit/byte setting incorrect for configurable element index %d.\n", info->currentConfigurableElementIdx);
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
if ( bReportId != info->reportIds[info->currentReportIdx] ) {
printf("Error: Locator report ID setting incorrect for configurable element index %d.\n", info->currentConfigurableElementIdx);
return HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
info->currentConfigurableElementIdx += 1;
}
return HID_STATUS_GOOD;
}
unsigned hidReportValidate( void )
{
struct HID_validation_info info = {};
unsigned status = HID_STATUS_GOOD;
// Fill in the validation info struct by iterating through the hid report items
for ( size_t idx = 0; idx < HID_REPORT_DESCRIPTOR_ITEM_COUNT; ++idx ) {
const USB_HID_Short_Item_t *item = hidReportDescriptorItems[idx];
unsigned bTag = hidGetItemTag ( item->header );
unsigned bType = hidGetItemType( item->header );
if ( bTag == HID_REPORT_ITEM_TAG_COLLECTION && bType == HID_REPORT_ITEM_TYPE_MAIN ) {
info.collectionOpenedCount += 1;
}
else if ( bTag == HID_REPORT_ITEM_TAG_END_COLLECTION && bType == HID_REPORT_ITEM_TYPE_MAIN ) {
info.collectionOpenedCount -= 1;
if ( info.collectionOpenedCount < 0 ) {
printf("Error: Collection closed while there is no collection open.\n");
status = HID_STATUS_BAD_REPORT_DESCRIPTOR;
}
}
else if ( bTag == HID_REPORT_ITEM_TAG_INPUT && bType == HID_REPORT_ITEM_TYPE_MAIN ) {
info.current_bit_offset += (info.current_bit_size * info.current_bit_count);
}
else if ( bTag == HID_REPORT_ITEM_TAG_REPORT_SIZE && bType == HID_REPORT_ITEM_TYPE_GLOBAL ) {
info.current_bit_size = item->data[0];
}
else if ( bTag == HID_REPORT_ITEM_TAG_REPORT_COUNT && bType == HID_REPORT_ITEM_TYPE_GLOBAL ) {
info.current_bit_count = item->data[0];
}
else if ( bTag == HID_REPORT_ITEM_TAG_REPORT_ID && bType == HID_REPORT_ITEM_TYPE_GLOBAL ) {
status = hidReportValidateAddReportId( &info, item );
}
else if ( bTag == HID_REPORT_ITEM_TAG_USAGE_PAGE && bType == HID_REPORT_ITEM_TYPE_GLOBAL ) {
status = hidReportValidateAddUsagePageItem( &info, item );
}
else if ( bTag == HID_REPORT_ITEM_TAG_USAGE && bType == HID_REPORT_ITEM_TYPE_LOCAL ) {
status = hidReportValidateAddUsageItem( &info, item );
}
if ( status ) {
break;
}
}
if(status) {
return status;
} else {
return hidReportValidateInfoStruct( &info );
}
}

View File

@@ -1,272 +0,0 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <assert.h>
#include <stddef.h>
#include <xs1.h>
#include "xua_hid_report_descriptor.h"
#include "hid_report_descriptor.h"
#include <stdio.h>
#define HID_REPORT_ITEM_LOCATION_SIZE ( 1 )
#define HID_REPORT_DESCRIPTOR_ITEM_COUNT ( sizeof hidReportDescriptorItems / sizeof ( USB_HID_Short_Item_t* ))
#define HID_REPORT_DESCRIPTOR_MAX_LENGTH ( HID_REPORT_DESCRIPTOR_ITEM_COUNT * \
( sizeof ( USB_HID_Short_Item_t ) - HID_REPORT_ITEM_LOCATION_SIZE ))
static unsigned char hidReportDescriptor[ HID_REPORT_DESCRIPTOR_MAX_LENGTH ];
static size_t hidReportDescriptorLength = 0;
static unsigned hidReportDescriptorPrepared = 0;
/**
* @brief Get the bit position from the location of an Item
*
* Parameters:
*
* @param[in] location The \c location field from a \c USB_HID_Short_Item
*
* @return The bit position of the Item
*/
static unsigned hidGetItemBitLocation( const unsigned char header );
/**
* @brief Get the byte position from the location of an Item
*
* Parameters:
*
* @param[in] location The \c location field from a \c USB_HID_Short_Item
*
* @return The byte position of the Item within the HID Report
*/
static unsigned hidGetItemByteLocation( const unsigned char header );
/**
* @brief Get the number of data bytes from the header of an Item
*
* Parameters:
*
* @param[in] header The \c header field from a \c USB_HID_Short_Item
*
* @return The amount of data for the Item
*/
static unsigned hidGetItemSize( const unsigned char header );
/**
* @brief Get the Tag from the header of an Item
*
* Parameters:
*
* @param[in] header The \c header field from a \c USB_HID_Short_Item
*
* @return The Tag of the Item
*/
static unsigned hidGetItemTag( const unsigned char header );
/**
* @brief Get the Type from the header of an Item
*
* Parameters:
*
* @param[in] header The \c header field from a \c USB_HID_Short_Item
*
* @return The Type of the Item
*/
static unsigned hidGetItemType( const unsigned char header );
/**
* @brief Get the Usage Page number for a given byte in the HID Report
*
* Parameters:
*
* @param[in] byte The byte location in the HID Report
*
* @return The USB HID Usage Page code or zero if the \a byte parameter is out-of-range
*/
static unsigned hidGetUsagePage( const unsigned byte );
/**
* @brief Translate an Item from the \c USB_HID_Short_Item format to raw bytes
*
* Parameters:
*
* @param[in] inPtr A pointer to a \c USB_HID_Short_Item
* @param[in,out] outPtrPtr A pointer to a pointer to the next available space in the raw
* byte buffer. Passed as a pointer to a pointer to allow this
* function to return the updated pointer to the raw byte buffer.
*
* @return The number of bytes placed in the raw byte buffer
*/
static size_t hidTranslateItem( const USB_HID_Short_Item_t* inPtr, unsigned char** outPtrPtr );
static unsigned hidGetItemBitLocation( const unsigned char location )
{
unsigned bBit = ( location & HID_REPORT_ITEM_LOC_BIT_MASK ) >> HID_REPORT_ITEM_LOC_BIT_SHIFT;
return bBit;
}
static unsigned hidGetItemByteLocation( const unsigned char location )
{
unsigned bByte = ( location & HID_REPORT_ITEM_LOC_BYTE_MASK ) >> HID_REPORT_ITEM_LOC_BYTE_SHIFT;
return bByte;
}
static unsigned hidGetItemSize( const unsigned char header )
{
unsigned bSize = ( header & HID_REPORT_ITEM_HDR_SIZE_MASK ) >> HID_REPORT_ITEM_HDR_SIZE_SHIFT;
return bSize;
}
static unsigned hidGetItemTag( const unsigned char header )
{
unsigned bTag = ( header & HID_REPORT_ITEM_HDR_TAG_MASK ) >> HID_REPORT_ITEM_HDR_TAG_SHIFT;
return bTag;
}
static unsigned hidGetItemType( const unsigned char header )
{
unsigned bType = ( header & HID_REPORT_ITEM_HDR_TYPE_MASK ) >> HID_REPORT_ITEM_HDR_TYPE_SHIFT;
return bType;
}
unsigned char* hidGetReportDescriptor( void )
{
unsigned char* retVal = NULL;
if( hidReportDescriptorPrepared ) {
retVal = hidReportDescriptor;
}
return retVal;
}
size_t hidGetReportDescriptorLength( void )
{
size_t retVal = ( hidReportDescriptorPrepared ) ? hidReportDescriptorLength : 0;
return retVal;
}
#define HID_CONFIGURABLE_ITEM_COUNT ( sizeof hidConfigurableItems / sizeof ( USB_HID_Short_Item_t* ))
unsigned hidGetReportItem(
const unsigned byte,
const unsigned bit,
unsigned char* const page,
unsigned char* const header,
unsigned char data[]
)
{
unsigned retVal = HID_STATUS_BAD_LOCATION;
for( unsigned itemIdx = 0; itemIdx < HID_CONFIGURABLE_ITEM_COUNT; ++itemIdx ) {
USB_HID_Short_Item_t item = *hidConfigurableItems[ itemIdx ];
unsigned bBit = hidGetItemBitLocation( item.location );
unsigned bByte = hidGetItemByteLocation( item.location );
if(( bit == bBit ) && ( byte == bByte )) {
*page = hidGetUsagePage( byte );
*header = item.header;
for( unsigned dataIdx = 0; dataIdx < HID_REPORT_ITEM_MAX_SIZE; ++data, ++dataIdx ) {
*data = item.data[ dataIdx ];
}
retVal = HID_STATUS_GOOD;
break;
}
}
return retVal;
}
size_t hidGetReportLength( void )
{
size_t retVal = ( hidReportDescriptorPrepared ) ? HID_REPORT_LENGTH : 0;
return retVal;
}
static unsigned hidGetUsagePage( const unsigned byte )
{
unsigned retVal = ( byte < HID_REPORT_LENGTH ) ? hidUsagePages[ byte ]->data[ 0 ] : 0;
return retVal;
}
void hidPrepareReportDescriptor( void )
{
if( !hidReportDescriptorPrepared ) {
hidReportDescriptorLength = 0;
unsigned char* ptr = hidReportDescriptor;
for( unsigned idx = 0; idx < HID_REPORT_DESCRIPTOR_ITEM_COUNT; ++idx ) {
hidReportDescriptorLength += hidTranslateItem( hidReportDescriptorItems[ idx ], &ptr );
}
hidReportDescriptorPrepared = 1;
}
}
void hidResetReportDescriptor( void )
{
hidReportDescriptorPrepared = 0;
}
unsigned hidSetReportItem(
const unsigned byte,
const unsigned bit,
const unsigned char page,
const unsigned char header,
const unsigned char data[]
)
{
unsigned retVal = HID_STATUS_IN_USE;
if( !hidReportDescriptorPrepared ) {
retVal = HID_STATUS_BAD_LOCATION;
unsigned bSize = hidGetItemSize( header );
unsigned bTag = hidGetItemTag ( header );
unsigned bType = hidGetItemType( header );
if(( HID_REPORT_ITEM_MAX_SIZE < bSize ) ||
( HID_REPORT_ITEM_USAGE_TAG != bTag ) ||
( HID_REPORT_ITEM_USAGE_TYPE != bType )) {
retVal = HID_STATUS_BAD_HEADER;
} else {
for( unsigned itemIdx = 0; itemIdx < HID_CONFIGURABLE_ITEM_COUNT; ++itemIdx ) {
USB_HID_Short_Item_t item = *hidConfigurableItems[ itemIdx ];
unsigned bBit = hidGetItemBitLocation( item.location );
unsigned bByte = hidGetItemByteLocation( item.location );
if(( bit == bBit ) && ( byte == bByte )) {
unsigned pg = hidGetUsagePage( byte );
if( page == pg ) {
item.header = header;
for( unsigned dataIdx = 0; dataIdx < bSize; ++dataIdx ) {
item.data[ dataIdx ] = data[ dataIdx ];
}
*hidConfigurableItems[ itemIdx ] = item;
retVal = HID_STATUS_GOOD;
} else {
retVal = HID_STATUS_BAD_PAGE;
}
break;
}
}
}
}
return retVal;
}
static size_t hidTranslateItem( const USB_HID_Short_Item_t* inPtr, unsigned char** outPtrPtr )
{
size_t count = 0;
*(*outPtrPtr)++ = inPtr->header;
++count;
unsigned dataLength = hidGetItemSize( inPtr->header );
for( unsigned idx = 0; idx < dataLength; ++idx ) {
*(*outPtrPtr)++ = inPtr->data[ idx ];
++count;
}
return count;
}

View File

@@ -1,6 +1,12 @@
// Copyright 2019-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
* @brief Human Interface Device (HID) Class Request functions
*
* Document section numbers refer to the HID Device Class Definition, version 1.11.
*/
#ifndef __XUA_HID_H__
#define __XUA_HID_H__
@@ -9,49 +15,11 @@
#include "xud.h"
#include "xud_std_requests.h"
/**
* \brief Calculate the next time to respond with a HID Report.
*
* If the USB Host has previously sent a valid HID Set_Idle request with
* a duration of zero or greater than the default reporting interval,
* the device sends HID Reports periodically or when the value of the
* payload has changed.
*
* This function calculates the time for sending the next periodic
* HID Report.
*/
void HidCalcNextReportTime( void );
/**
* \brief Capture the time of sending the current HID Report.
*
* If the USB Host has previously sent a valid HID Set_Idle request with
* a duration of zero or greater than the default reporting interval,
* the device sends HID Reports periodically or when the value of the
* payload has changed.
*
* This function captures the time when the HID Report was sent so that
* a subsequent call to HidCalNextReportTime() can calculate the time
* to send the next periodic HID Report.
*/
void HidCaptureReportTime( void );
XUD_Result_t HidInterfaceClassRequests(
XUD_ep c_ep0_out,
XUD_ep c_ep0_in,
REFERENCE_PARAM( USB_SetupPacket_t, sp ));
/**
* \brief Register that previously changed HID Report data has reported
* to the USB Host.
*/
void HidClearChangePending( void );
/**
* \brief Indicate if a change to the HID Report data has been received.
*/
unsigned HidIsChangePending( void );
/**
* \brief Indicate whether to send a HID Report based on elapsed time.
*
@@ -64,15 +32,15 @@ unsigned HidIsChangePending( void );
* whether or not the time to send the next periodic HID Report has
* elapsed.
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* \return A Boolean value indicating whether or not to send the HID Report.
* \retval 1 -- Do not send the HID Report
* \retval 0 -- Send the HID Report
*/
unsigned HidIsSetIdleSilenced( void );
/**
* \brief Register that a change to the HID Report data has been received.
*/
void HidSetChangePending( void );
unsigned HidIsSetIdleSilenced( const unsigned id );
#endif // __XUA_HID_H__

View File

@@ -0,0 +1,556 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
* @brief Human Interface Device (HID) Report descriptor
*
* This file defines the structure of the HID Report descriptor and declares
* functions for manipulating it.
* Because the Report descriptor defines the length of the HID Report, this file
* declares a function for obtaining the Report length as well.
* The using application has the responsibility to define the report descriptor
* structure and default contents in their hid_report_descriptor.h file.
* Document section numbers refer to the HID Device Class Definition, version 1.11.
*/
#ifndef _XUA_HID_REPORT_
#define _XUA_HID_REPORT_
#include <stddef.h>
#include "xua_hid_report_descriptor_constants.h"
#define HID_REPORT_ITEM_HDR_SIZE_MASK ( 0x03 )
#define HID_REPORT_ITEM_HDR_SIZE_SHIFT ( 0U )
#define HID_REPORT_ITEM_HDR_TAG_MASK ( 0xF0 )
#define HID_REPORT_ITEM_HDR_TAG_SHIFT ( 4U )
#define HID_REPORT_ITEM_HDR_TYPE_MASK ( 0x0C )
#define HID_REPORT_ITEM_HDR_TYPE_SHIFT ( 2U )
#define HID_REPORT_ELEMENT_LOC_BIT_MASK ( 0x0070 )
#define HID_REPORT_ELEMENT_LOC_BIT_SHIFT ( 4U )
#define HID_REPORT_ELEMENT_LOC_BYTE_MASK ( 0x000F )
#define HID_REPORT_ELEMENT_LOC_BYTE_SHIFT ( 0U )
#define HID_REPORT_ELEMENT_LOC_ID_MASK ( 0xF000 )
#define HID_REPORT_ELEMENT_LOC_ID_SHIFT ( 12U )
#define HID_REPORT_ELEMENT_LOC_LEN_MASK ( 0x0F00 )
#define HID_REPORT_ELEMENT_LOC_LEN_SHIFT ( 8U )
#define HID_REPORT_ITEM_MAX_SIZE ( 2U )
#define HID_REPORT_ITEM_USAGE_TAG ( 0U )
#define HID_REPORT_ITEM_USAGE_TYPE ( 2U )
/**
* @brief Helper macro to configure the location field of USB_HID_Report_Element_t.
*
* @param id The report ID that this element is within.
* @param len (only relevant for the usage_page elements in hidReports) The length
* of the report under this report ID.
* @param byte The byte location of this element in the report.
* @param bit The bit location (within the byte) of this element in the report.
*/
#define HID_REPORT_SET_LOC(id, len, byte, bit) (\
(( id << HID_REPORT_ELEMENT_LOC_ID_SHIFT ) & HID_REPORT_ELEMENT_LOC_ID_MASK ) | \
(( len << HID_REPORT_ELEMENT_LOC_LEN_SHIFT ) & HID_REPORT_ELEMENT_LOC_LEN_MASK ) | \
(( byte << HID_REPORT_ELEMENT_LOC_BYTE_SHIFT ) & HID_REPORT_ELEMENT_LOC_BYTE_MASK ) | \
(( bit << HID_REPORT_ELEMENT_LOC_BIT_SHIFT ) & HID_REPORT_ELEMENT_LOC_BIT_MASK ))
/**
* @brief Helper macro to configure the header field of USB_HID_Short_Item_t
*
* @param size The size of the report descriptor item (valid values: 0, 1, 2)
* @param type The type of the report descriptor item
* @param tag The tag
*/
#define HID_REPORT_SET_HEADER(size, type, tag) (\
(( size << HID_REPORT_ITEM_HDR_SIZE_SHIFT) & HID_REPORT_ITEM_HDR_SIZE_MASK ) |\
(( type << HID_REPORT_ITEM_HDR_TYPE_SHIFT) & HID_REPORT_ITEM_HDR_TYPE_MASK ) |\
(( tag << HID_REPORT_ITEM_HDR_TAG_SHIFT ) & HID_REPORT_ITEM_HDR_TAG_MASK ) )
#define HID_STATUS_GOOD ( 0U )
#define HID_STATUS_BAD_HEADER ( 1U )
#define HID_STATUS_BAD_ID ( 2U )
#define HID_STATUS_BAD_LOCATION ( 3U )
#define HID_STATUS_BAD_PAGE ( 4U )
#define HID_STATUS_IN_USE ( 5U )
#define HID_STATUS_BAD_REPORT_DESCRIPTOR ( 6U )
#define MS_IN_TICKS 100000U
/**
* @brief USB HID Report Descriptor Short Item
*
* @note
* To reduce memory use, this type does not support Short Items with 4 data bytes.
* See section 6.2.2.2
*
* Elements:
*
* header - the item prefix containing the size, type and tag fields (see 6.2.2.2)
* Format (bit range): bSize (0:1), bType (2:3), bTag (4:7)
* data - a two byte array for holding the item's data
* The bSize field indicates which data bytes are in use
* id - a non-standard extension identifying the HID Report ID associated with
* the item (see 5.6, 6.2.2.7, 8.1 and 8.2)
* location - a non-standard extension locating the item within the HID Report
* Format (bit range): iByte (0:3), iBit (4:6), Reserved (7)
*/
typedef struct
{
unsigned char header;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ];
} USB_HID_Short_Item_t;
typedef struct
{
USB_HID_Short_Item_t item;
unsigned short location;
} USB_HID_Report_Element_t;
/**
* \brief Register that a previously changed HID Report data has been sent
* to the USB Host.
*
* HID processing maintains a list of HID Reports with changed data not yet
* reported to the USB Host.
*
* Applications that have only one HID Report may or may not use a Report ID.
* Applications that have more than one HID Report must use Report IDs.
*
* For applications that do not use Report IDs, the list contains one element.
* That element tracks whether or not an unreported change has occurred in the
* HID data.
* For applications that use Report IDs, the list contains one element per
* Report ID.
* Each element tracks unreported changes for the corresponding Report ID.
*
* Calling this function for a given Report ID indicates that the changed
* HID data has been reported to the USB Host.
*
* \warning This function will fail silently if given an id that is not
* either the value zero, or a Report ID that is in use.
*
* \param[in] id A HID Report ID.
* Zero clears the pending status of all Report IDs.
* Use zero if the application does not use Report IDs.
*/
void hidClearChangePending( const unsigned id );
/**
* @brief Indicate if the HID Report descriptor has been prepared
*
* \returns A Boolean indicating whether the HID Report descriptor has been prepared.
* \retval True The HID Report descriptor has been prepared.
* \retval False The HID Report descriptor has not been prepared.
*/
unsigned hidIsReportDescriptorPrepared( void );
/**
* @brief Get the HID Report descriptor
*
* This function returns a pointer to the USB HID Report descriptor.
* It returns NULL if the Report descriptor has not been prepared,
* i.e., no one has called \c hidPrepareReportDescriptor().
*
* @note An XC-callable version of this function has not been provided.
* XC requires explicit declaration of the kind of pointer returned,
* hence an XC implementation of the function.
*
* @return A pointer to a list of unsigned char containing the Report descriptor
*/
#if !defined(__XC__)
unsigned char* hidGetReportDescriptor( void );
#endif
/**
* @brief Get the length of the HID Report descriptor
*
* This function returns the length of the USB HID Report descriptor.
* It returns zero if the Report descriptor has not been prepared,
* i.e., no one has called \c hidPrepareReportDescriptor().
*
* @return The length of the Report descriptor in bytes
*/
size_t hidGetReportDescriptorLength( void );
/**
* \brief Get the upper limit of HID Report identifiers
*
* This function returns the upper limit of the HID Report identifiers.
* The upper limit has a value one greater than the maximum HID Report identifier.
* In the case that HID Report identifiers are not in use, this function returns the value 1.
*
* \returns The upper limit of HID Report identifiers
*/
unsigned hidGetReportIdLimit ( void );
/**
* @brief Does the application use Report IDs?
*
* If the application is not using Report IDs, then the id value that is passed around
* everywhere can just be zero. Otherwise zero is an invalid ID that has a special meaning
* in some cases (read the documentation for each function).
*
* @return Boolean
* @retval 1 Report IDs are in use
* @retval 0 Report IDs are not in use
*/
unsigned hidIsReportIdInUse ( void );
/**
* @brief Is the provided report ID valid for passing to other functions.
*
* e.g If Report IDs are not in use, then only 0 will return true.
* e.g If Report IDs are in use, then 0 will return false and the report IDs that
* are in use will return true when passed to thsi function.
*
* @param id The ID to check
* @return boolean
* @retval 0 The report ID is not valid, other functions may fail silently
* @retval 1 The report ID is valid and can be used as the argument to other functions
*/
unsigned hidIsReportIdValid ( unsigned id );
/**
* @brief Get the next valid report ID - iterator style.
*
* This function will loop around and start returning the first report ID again once it has
* returned all valid report IDs.
*
* @param idPrev The previous returned id, or 0 if this is the first call
* @return unsigned The next valid report ID.
*/
unsigned hidGetNextValidReportId ( unsigned idPrev );
/**
* @brief Get a HID Report descriptor item
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2).
* A value of zero means the application does not use Report IDs.
* @param[in] byte The byte position of the control within the HID Report
* @param[in] bit The bit position of the control within the \a byte
* @param[out] page The USB HID Usage Page code for the Item (see 5.5)
* @param[out] header The LSB of the Item containing the bSize, bType and bTag fields (see 6.2.2.2)
* @param[out] data A two element array containing data bytes for the Item
*
* @return A status value
* @retval \c HID_STATUS_GOOD Item successfully returned
* @retval \c HID_STATUS_BAD_ID The \a id argument specifies a non-existant HID Report
* @retval \c HID_STATUS_BAD_LOCATION The \a bit or \a byte arguments specify a location outside
* of the HID Report
*/
#if defined(__XC__)
unsigned hidGetReportItem(
const unsigned id,
const unsigned byte,
const unsigned bit,
unsigned char* unsafe const page,
unsigned char* unsafe const header,
unsigned char* unsafe const data);
#else
unsigned hidGetReportItem(
const unsigned id,
const unsigned byte,
const unsigned bit,
unsigned char* const page,
unsigned char* const header,
unsigned char data[]);
#endif
/**
* \brief Calculate the next time to respond with a HID Report.
*
* If the USB Host has previously sent a valid HID Set_Idle request with
* a duration of zero or greater than the default reporting interval,
* the device sends HID Reports periodically or when the value of the
* payload has changed.
*
* This function calculates the time for sending the next periodic
* HID Report.
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*/
void hidCalcNextReportTime( const unsigned id );
/**
* \brief Capture the time of sending the current HID Report.
*
* If the USB Host has previously sent a valid HID Set_Idle request with
* a duration of zero or greater than the default reporting interval,
* the device sends HID Reports periodically or when the value of the
* payload has changed.
*
* This function captures the time when the HID Report was sent so that
* a subsequent call to HidCalNextReportTime() can calculate the time
* to send the next periodic HID Report.
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @param[in] time The time when the HID Report for the given \a id was sent.
*/
void hidCaptureReportTime( const unsigned id, const unsigned time );
/**
* @brief Get the time to send the next HID Report for the given \a id
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @returns The time at which to send the next HID Report for the given \a id
*/
unsigned hidGetNextReportTime( const unsigned id );
/**
* @brief Get the length of the HID Report
*
* This function returns the length of the USB HID Report.
* It returns zero if the Report descriptor has not been prepared,
* i.e., no one has called \c hidPrepareReportDescriptor(),
* or if the \a id argument specifies a non-existent HID Report
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @return The length of the Report in bytes
*/
size_t hidGetReportLength( const unsigned id );
/**
* @brief Get the HID Report period for the given \a id
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @returns The period for the given HID Report \a id in units of ms.
* The value zero means the period is indefinite.
*/
unsigned hidGetReportPeriod( const unsigned id );
/**
* @brief Get the HID Report time for the given \a id
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @returns The time of the last call to \c hidCaptureReportTime()
*/
unsigned hidGetReportTime( const unsigned id );
/**
* \brief Indicate if a change to the HID Report data has been received.
*
* HID processing maintains a list of HID Reports with changed data not yet
* reported to the USB Host.
*
* Applications that have only one HID Report may or may not use a Report ID.
* Applications that have more than one HID Report must use Report IDs.
*
* For applications that do not use Report IDs, the list contains one element.
* That element tracks whether or not an unreported change has occurred in the
* HID data.
* For applications that use Report IDs, the list contains one element per
* Report ID.
* Each element tracks unreported changes for the corresponding Report ID.
*
* Calling this function with a given Report ID returns an indication of
* whether unreported HID data exists for that Report ID.
*
* \warning This function will return zero if given an id that is not
* either the value zero, or a Report ID that is in use.
*
* \param[in] id A HID Report ID.
* Zero reports the pending status of all Report IDs.
* Use zero if the application does not use Report IDs.
*
* \returns A Boolean indicating whether the given \a id has a changed
* HID Report not yet sent to the USB Host.
* \retval True The given \a id has changed HID Report data.
* For an \a id of zero, some HID Report has changed data.
* \retval False The given \a id does not have changed HID Report data.
* For an \a id of zero, no HID Report has changed data.
*/
unsigned hidIsChangePending( const unsigned id );
/**
* @brief Indicate if the HID report for the given \a id is idle
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero returns the collective Idle state.
*
* \returns A Boolean indicating whether the HID Report for the given \a id is idle.
* \retval True The HID Report is idle.
* For an \a id of zero, all HID Reports are idle.
* \retval False The HID Report is not idle.
* For an \a id of zero, at least one HID Report is not idle.
*/
unsigned hidIsIdleActive( const unsigned id );
/**
* @brief Prepare the USB HID Report descriptor
*
* After preparation, \c hidGetReportDescriptor() returns a list suitable for transmission over USB.
* Call this function after altering one or more Report Items using \c hidSetReportItem().
*/
void hidPrepareReportDescriptor( void );
/**
* @brief Initialise the USB HID Report functionality
*
* Call this function before using any other functions in this API.
*/
void hidReportInit( void );
/**
* @brief Reset the USB HID Report descriptor
*
* After reset, \c hidGetReportDescriptor() returns NULL until a subsequent call to
* \c hidPrepareReportDescriptor() occurs.
* Call this function before altering one or more Report Items using \c hidSetReportItem().
*/
void hidResetReportDescriptor( void );
/**
* \brief Register that a change to the HID Report data has been received.
*
* HID processing maintains a list of HID Reports with changed data not yet
* reported to the USB Host.
*
* Applications that have only one HID Report may or may not use a Report ID.
* Applications that have more than one HID Report must use Report IDs.
*
* For applications that do not use Report IDs, the list contains one element.
* That element tracks whether or not an unreported change has occurred in the
* HID data.
* For applications that use Report IDs, the list contains one element per
* Report ID.
* Each element tracks unreported changes for the corresponding Report ID.
*
* Calling this function with a given Report ID indicates that the HID data
* for that Report ID has changed and has not yet been reported to the USB
* Host.
*
* \warning This function will fail silently if given an id that is not
* either the value zero, or a Report ID that is in use.
*
* \param[in] id A HID Report ID.
* Use zero if the application does not use Report IDs.
*/
void hidSetChangePending( const unsigned id );
/**
* @brief Set the HID Report Idle state for the given \a id
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @param[in] state A Boolean indicating the Idle state
* If true, the HID Report for the given \a id is Idle, otherwise it
* is not Idle.
*/
void hidSetIdle( const unsigned id, const unsigned state );
/**
* @brief Set the time to send the HID Report for the given \a id
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @param[in] time The time to send the HID Report for the given \a id.
*/
void hidSetNextReportTime( const unsigned id, const unsigned time );
/**
* @brief Modify a HID Report descriptor item
*
* @warning This function does not check that the length of the \a data array matches the value of
* the bSize field in the \a header. For safe operation use a \a data array of at least
* \c HID_REPORT_ITEM_MAX_SIZE bytes in length.
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
* @param[in] byte The byte position of the control within the HID Report
* @param[in] bit The bit position of the control within the \a byte
* @param[in] page The USB HID Usage Page code for the Item (see 5.5)
* @param[in] header The LSB of the Item containing the bSize, bType and bTag fields (see 6.2.2.2)
* @param[in] data An array containing data bytes or NULL for an Item with no data
*
* @return A status value
* @retval \c HID_STATUS_GOOD Item successfully updated
* @retval \c HID_STATUS_BAD_HEADER The Item header specified a data size greater than 2 or
* a Tag or Type inconsistent with a Usage Item
* @retval \c HID_STATUS_BAD_ID The \a id argument specifies a non-existent HID Report
* @retval \c HID_STATUS_BAD_LOCATION The \a bit or \a byte arguments specify a location outside
* of the HID Report
* @retval \c HID_STATUS_BAD_PAGE The \a byte argument specifies a location for controls from
* a Usage Page other than the one given by the \a page parameter
* @retval \c HID_STATUS_IN_USE The Report descriptor is in use
*/
unsigned hidSetReportItem(
const unsigned id,
const unsigned byte,
const unsigned bit,
const unsigned char page,
const unsigned char header,
const unsigned char data[]);
/**
* @brief Set the HID Report period for the given \a id
*
* Parameters:
*
* @param[in] id The identifier for the HID Report (see 5.6, 6.2.2.7, 8.1 and 8.2)
* A value of zero means the application does not use Report IDs.
*
* @param[in] period The period for sending the HID Report in units of ms.
* This period must be a multiple of 4 ms.
* Use zero to indicate an indefinite period.
*/
void hidSetReportPeriod( const unsigned id, const unsigned period );
/**
* @brief Development function: Validate the contents of hid_report_descriptor.h for common errors, printing
* error messages if any issues were found.
*
* This function is intended for use when developing the contents of hid_report_descriptor.h, which is static,
* so shouldn't be required for use in a production application.
*
* @return Validation result
* @retval HID_STATUS_GOOD The validation found no issues with the data structures defined
* in hid_report_descriptor.h
* @retval HID_STATUS_BAD_REPORT_DESCRIPTOR The validation encountered an issue with the data structures
* defined in hid_report_descriptor.h . More information is
* provided in the printed messages.
*/
unsigned hidReportValidate( void );
#endif // _XUA_HID_REPORT_

View File

@@ -1,175 +0,0 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
* @brief Human Interface Device (HID) Report descriptor
*
* This file defines the structure of the HID Report descriptor and declares
* functions for manipulating it.
* Because the Report descriptor defines the length of the HID Report, this file
* declares a function for obtaining the Report length as well.
* The using application has the responsibility to define the report descriptor
* structure and default contents in their hid_report_descriptor.h file.
* Document section numbers refer to the HID Device Class Definition, version 1.11.
*/
#ifndef _HID_REPORT_DESCRIPTOR_
#define _HID_REPORT_DESCRIPTOR_
#include <stddef.h>
#define HID_REPORT_ITEM_HDR_SIZE_MASK ( 0x03 )
#define HID_REPORT_ITEM_HDR_SIZE_SHIFT ( 0 )
#define HID_REPORT_ITEM_HDR_TAG_MASK ( 0xF0 )
#define HID_REPORT_ITEM_HDR_TAG_SHIFT ( 4 )
#define HID_REPORT_ITEM_HDR_TYPE_MASK ( 0x0C )
#define HID_REPORT_ITEM_HDR_TYPE_SHIFT ( 2 )
#define HID_REPORT_ITEM_LOC_BIT_MASK ( 0x70 )
#define HID_REPORT_ITEM_LOC_BIT_SHIFT ( 4 )
#define HID_REPORT_ITEM_LOC_BYTE_MASK ( 0x0F )
#define HID_REPORT_ITEM_LOC_BYTE_SHIFT ( 0 )
#define HID_REPORT_ITEM_MAX_SIZE ( 2 )
#define HID_REPORT_ITEM_USAGE_TAG ( 0 )
#define HID_REPORT_ITEM_USAGE_TYPE ( 2 )
#define HID_STATUS_GOOD ( 0 )
#define HID_STATUS_BAD_HEADER ( 1 )
#define HID_STATUS_BAD_LOCATION ( 2 )
#define HID_STATUS_BAD_PAGE ( 3 )
#define HID_STATUS_IN_USE ( 4 )
/**
* @brief USB HID Report Descriptor. Short Item
*
* @note
* To reduce memory use, this type does not support Short Items with 4 data bytes.
* See section 6.2.2.2
*
* Elements:
*
* header - the item prefix containing the size, type and tag fields (see 6.2.2.2)
* Format (bit range): bSize (0:1), bType (2:3), bTag (4:7)
* data - a two byte array for holding the item's data
* The bSize field indicates which data bytes are in use
* location - a non-standard extension locating the item within the HID Report
* Format (bit range): iByte (0:3), iBit (4:6), Reserved (7)
*/
typedef struct
{
unsigned char header;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ];
unsigned char location;
} USB_HID_Short_Item_t;
/**
* @brief Get the HID Report descriptor
*
* This function returns a pointer to the USB HID Report descriptor.
* It returns NULL if the Report descriptor has not been prepared,
* i.e., no one has called \c hidPrepareReportDescriptor().
*
* @note An XC-callable version of this function has not been provided.
* XC requires explicit declaration of the kind of pointer returned,
* hence an XC implementation of the function.
*
* @return A pointer to a list of unsigned char containing the Report descriptor
*/
#if !defined(__XC__)
unsigned char* hidGetReportDescriptor( void );
#endif
/**
* @brief Get the length of the HID Report descriptor
*
* This function returns the length of the USB HID Report descriptor.
* It returns zero if the Report descriptor has not been prepared,
* i.e., no one has called \c hidPrepareReportDescriptor().
*
* @return The length of the Report descriptor in bytes
*/
size_t hidGetReportDescriptorLength( void );
/**
* @brief Get a HID Report descriptor item
*
* Parameters:
*
* @param[in] byte The byte position of the control within the HID Report
* @param[in] bit The bit position of the control within the \a byte
* @param[out] page The USB HID Usage Page code for the Item (see 5.5)
* @param[out] header The LSB of the Item containing the bSize, bType and bTag fields (see 6.2.2.2)
* @param[out] data A two element array containing data bytes for the Item
*
* @return A status value
* @retval \c HID_STATUS_GOOD Item successfully returned
* @retval \c HID_STATUS_BAD_LOCATION The \a bit or \a byte arguments specify a location outside
* of the HID Report
*/
#if defined(__XC__)
unsigned hidGetReportItem( const unsigned byte, const unsigned bit, unsigned char* unsafe const page, unsigned char* unsafe const header, unsigned char* unsafe const data);
#else
unsigned hidGetReportItem( const unsigned byte, const unsigned bit, unsigned char* const page, unsigned char* const header, unsigned char data[]);
#endif
/**
* @brief Get the length of the HID Report
*
* This function returns the length of the USB HID Report.
* It returns zero if the Report descriptor has not been prepared,
* i.e., no one has called \c hidPrepareReportDescriptor().
*
* @return The length of the Report in bytes
*/
size_t hidGetReportLength( void );
/**
* @brief Prepare the USB HID Report descriptor
*
* After preparation, \c hidGetReportDescriptor() returns a list suitable for transmission over USB.
* Call this function after altering one or more Report Items using \c hidSetReportItem().
*/
void hidPrepareReportDescriptor( void );
/**
* @brief Reset the USB HID Report descriptor
*
* After reset, \c hidGetReportDescriptor() returns NULL until a subsequent call to
* \c hidPrepareReportDescriptor() occurs.
* Call this function before altering one or more Report Items using \c hidSetReportItem().
*/
void hidResetReportDescriptor( void );
/**
* @brief Modify a HID Report descriptor item
*
* @warning This function does not check that the length of the \a data array matches the value of
* the bSize field in the \a header. For safe operation use a \a data array of at least
* \c HID_REPORT_ITEM_MAX_SIZE bytes in length.
*
* Parameters:
*
* @param[in] byte The byte position of the control within the HID Report
* @param[in] bit The bit position of the control within the \a byte
* @param[in] page The USB HID Usage Page code for the Item (see 5.5)
* @param[in] header The LSB of the Item containing the bSize, bType and bTag fields (see 6.2.2.2)
* @param[in] data An array containing data bytes or NULL for an Item with no data
*
* @return A status value
* @retval \c HID_STATUS_GOOD Item successfully updated
* @retval \c HID_STATUS_BAD_HEADER The Item header specified a data size greater than 2 or
* a Tag or Type inconsistent with a Usage Item
* @retval \c HID_STATUS_BAD_LOCATION The \a bit or \a byte arguments specify a location outside
* of the HID Report
* @retval \c HID_STATUS_BAD_PAGE The \a byte argument specifies a location for controls from
* a Usage Page other than the one given by the \a page parameter
* @retval \c HID_STATUS_IN_USE The Report descriptor is in use
*/
unsigned hidSetReportItem( const unsigned byte, const unsigned bit, const unsigned char page, const unsigned char header, const unsigned char data[]);
#endif // _HID_REPORT_DESCRIPTOR_

View File

@@ -0,0 +1,66 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
/**
* @brief Human Interface Device (HID) Report descriptor constants
*
* This file defines a collection of constants from the USB HID documents.
* This includes constants from:
* - Device Class Definition for Human Interface Devices, version 1.11
* - HID Usage Tables for Universal Serial Bus, version 1.22
*
* This file is incomplete, but can be expanded with new constants as necessary.
*/
#ifndef _XUA_HID_REPORT_DESCRIPTOR_CONSTANTS_
#define _XUA_HID_REPORT_DESCRIPTOR_CONSTANTS_
// Constants from the USB Device Class Definition for HID for type
#define HID_REPORT_ITEM_TYPE_MAIN ( 0x00 )
#define HID_REPORT_ITEM_TYPE_GLOBAL ( 0x01 )
#define HID_REPORT_ITEM_TYPE_LOCAL ( 0x02 )
#define HID_REPORT_ITEM_TYPE_RESERVED ( 0x03 )
// Constants from the USB Device Class Definition for HID for tag
// Main items
#define HID_REPORT_ITEM_TAG_INPUT ( 0x08 )
#define HID_REPORT_ITEM_TAG_OUTPUT ( 0x09 )
#define HID_REPORT_ITEM_TAG_FEATURE ( 0x0B )
#define HID_REPORT_ITEM_TAG_COLLECTION ( 0x0A )
#define HID_REPORT_ITEM_TAG_END_COLLECTION ( 0x0C )
// Global items
#define HID_REPORT_ITEM_TAG_USAGE_PAGE ( 0x00 )
#define HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM ( 0x01 )
#define HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM ( 0x02 )
#define HID_REPORT_ITEM_TAG_PHYSICAL_MINIMUM ( 0x03 )
#define HID_REPORT_ITEM_TAG_PHYSICAL_MAXIMUM ( 0x04 )
#define HID_REPORT_ITEM_TAG_UNIT_EXPONENT ( 0x05 )
#define HID_REPORT_ITEM_TAG_UNIT ( 0x06 )
#define HID_REPORT_ITEM_TAG_REPORT_SIZE ( 0x07 )
#define HID_REPORT_ITEM_TAG_REPORT_ID ( 0x08 )
#define HID_REPORT_ITEM_TAG_REPORT_COUNT ( 0x09 )
#define HID_REPORT_ITEM_TAG_PUSH ( 0x0A )
#define HID_REPORT_ITEM_TAG_POP ( 0x0B )
// Local items
#define HID_REPORT_ITEM_TAG_USAGE ( 0x00 )
#define HID_REPORT_ITEM_TAG_USAGE_MINIMUM ( 0x01 )
#define HID_REPORT_ITEM_TAG_USAGE_MAXIMUM ( 0x02 )
#define HID_REPORT_ITEM_TAG_DESIGNATOR_INDEX ( 0x03 )
#define HID_REPORT_ITEM_TAG_DESIGNATOR_MINIMUM ( 0x04 )
#define HID_REPORT_ITEM_TAG_DESIGNATOR_MAXIMUM ( 0x05 )
#define HID_REPORT_ITEM_TAG_STRING_INDEX ( 0x07 )
#define HID_REPORT_ITEM_TAG_STRING_MINIMUM ( 0x08 )
#define HID_REPORT_ITEM_TAG_STRING_MAXIMUM ( 0x09 )
#define HID_REPORT_ITEM_TAG_DELIMITER ( 0x0A )
// Constants from HID Usage Tables
// Usage page IDs (incomplete)
#define USB_HID_USAGE_PAGE_ID_GENERIC_DESKTOP ( 0x01 )
#define USB_HID_USAGE_PAGE_ID_KEYBOARD ( 0x07 )
#define USB_HID_USAGE_PAGE_ID_TELEPHONY_DEVICE ( 0x0B )
#define USB_HID_USAGE_PAGE_ID_CONSUMER ( 0x0C )
#endif // _XUA_HID_REPORT_DESCRIPTOR_CONSTANTS_

View File

@@ -79,12 +79,10 @@ foreach( testsourcefile ${APP_SOURCES} )
set_target_properties(${ITEM_NAME} PROPERTIES OUTPUT_NAME ${ITEM_NAME}.xe)
target_compile_options(${ITEM_NAME} PRIVATE ${APP_COMPILER_FLAGS})
target_include_directories(${ITEM_NAME}
PRIVATE ${APP_INCLUDES}
PRIVATE ${XUA_INCLUDES_ALL}
)
target_include_directories(${ITEM_NAME}
PRIVATE ${APP_INCLUDES}
PRIVATE ${XUA_INCLUDES_ALL}
)
target_sources(${ITEM_NAME}
PRIVATE ${APP_SRCS}

View File

@@ -1,102 +0,0 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__
#include "xua_hid_report_descriptor.h"
#define MAX_VALID_BIT ( 7 )
#define MAX_VALID_BYTE ( 1 )
#define MIN_VALID_BIT ( 0 )
#define MIN_VALID_BYTE ( 0 )
/*
* Define non-configurable items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t hidCollectionApplication = { .header = 0xA1, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionEnd = { .header = 0xC0, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidCollectionLogical = { .header = 0xA1, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputConstArray = { .header = 0x81, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidInputDataVar = { .header = 0x81, .data = { 0x02, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = { .header = 0x25, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = { .header = 0x25, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = { .header = 0x15, .data = { 0x00, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount1 = { .header = 0x95, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount6 = { .header = 0x95, .data = { 0x06, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportCount7 = { .header = 0x95, .data = { 0x07, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidReportSize1 = { .header = 0x75, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidUsageConsumerControl = { .header = 0x09, .data = { 0x01, 0x00 }, .location = 0x00 };
static const USB_HID_Short_Item_t hidUsagePageConsumer = { .header = 0x05, .data = { 0x0C, 0x00 }, .location = 0x00 };
/*
* Define configurable items in the HID Report descriptor.
*/
static USB_HID_Short_Item_t hidUsageByte0Bit0 = { .header = 0x09, .data = { 0xE2, 0x00 }, .location = 0x00 }; // Mute
static USB_HID_Short_Item_t hidUsageByte1Bit7 = { .header = 0x09, .data = { 0xEA, 0x00 }, .location = 0x71 }; // Vol-
static USB_HID_Short_Item_t hidUsageByte1Bit0 = { .header = 0x09, .data = { 0xE9, 0x00 }, .location = 0x01 }; // Vol+
/*
* List the configurable items in the HID Report descriptor.
*/
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
&hidUsageByte0Bit0,
&hidUsageByte1Bit0,
&hidUsageByte1Bit7
};
/*
* List Usage pages in the HID Report descriptor, one per byte.
*/
static const USB_HID_Short_Item_t* const hidUsagePages[] = {
&hidUsagePageConsumer,
&hidUsagePageConsumer
};
/*
* List all items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
&hidUsagePageConsumer,
&hidUsageConsumerControl,
&hidCollectionApplication,
&hidReportSize1,
&hidLogicalMinimum0,
&hidCollectionLogical, // Byte 0
&hidLogicalMaximum1,
&hidReportCount1,
&hidUsageByte0Bit0,
&hidInputDataVar,
&hidLogicalMaximum0,
&hidReportCount7,
&hidInputConstArray,
&hidCollectionEnd,
&hidCollectionLogical, // Byte 1
&hidLogicalMaximum1,
&hidReportCount1,
&hidUsageByte1Bit0,
&hidInputDataVar,
&hidLogicalMaximum0,
&hidReportCount6,
&hidInputConstArray,
&hidLogicalMaximum1,
&hidUsageByte1Bit7,
&hidInputDataVar,
&hidCollectionEnd,
&hidCollectionEnd
};
/*
* Define the length of the HID Report.
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
*/
#define HID_REPORT_LENGTH ( 2 )
#endif // __hid_report_descriptor_h__

View File

@@ -0,0 +1,296 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__
#include "xua_hid_report.h"
#define USB_HID_REPORT_ID_KEYBOARD ( 0x01 )
#define USB_HID_REPORT_ID_CONSUMER ( 0x02 )
#define USB_HID_REPORT_ID_TELEPHONY ( 0x03 )
/*
* Define non-configurable items in the HID Report descriptor.
* (These are short items as the location field isn't relevant for them)
*/
static const USB_HID_Short_Item_t hidCollectionApplication = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionEnd = {
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidInputConstArray = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidInputDataVar = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount4 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x04, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount6 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x06, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount7 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x07, 0x00 } };
static const USB_HID_Short_Item_t hidReportSize1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsagePageGenericDesktop = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.data = { USB_HID_USAGE_PAGE_ID_GENERIC_DESKTOP, 0x00 }};
static const USB_HID_Short_Item_t hidUsagePageConsumerControl = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 }};
static const USB_HID_Short_Item_t hidUsagePageTelephony = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.data = { USB_HID_USAGE_PAGE_ID_TELEPHONY_DEVICE, 0x00 }};
static const USB_HID_Short_Item_t hidUsageKeyboard = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x06, 0x00 }};
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x01, 0x00 }};
static const USB_HID_Short_Item_t hidUsageTelephonyHeadset = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x05, 0x00 }};
/*
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
*/
static const USB_HID_Short_Item_t hidReportId1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_ID),
.data = { USB_HID_REPORT_ID_KEYBOARD, 0x00 } };
static const USB_HID_Short_Item_t hidReportId2 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_ID),
.data = { USB_HID_REPORT_ID_CONSUMER, 0x00 } };
static const USB_HID_Short_Item_t hidReportId3 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_ID),
.data = { USB_HID_REPORT_ID_TELEPHONY, 0x00 } };
static const USB_HID_Report_Element_t hidReportKeyboard = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_KEYBOARD, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_KEYBOARD, 1, 0, 0 )
};
static const USB_HID_Report_Element_t hidReportConsumer = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 2, 0, 0 )
};
static const USB_HID_Report_Element_t hidReportTelephony = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_TELEPHONY_DEVICE, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_TELEPHONY, 1, 0, 0 )
};
/*
* Define configurable elements in the HID Report descriptor.
*/
static USB_HID_Report_Element_t hidUsageReport1Byte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0x17, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_KEYBOARD, 0, 0, 0 )
}; // 't'
static USB_HID_Report_Element_t hidUsageReport1Byte0Bit2 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0x72, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_KEYBOARD, 0, 0, 2 )
}; // F23
static USB_HID_Report_Element_t hidUsageReport1Byte0Bit3 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0x73, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_KEYBOARD, 0, 0, 3 )
}; // F24
static USB_HID_Report_Element_t hidUsageReport2Byte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(2, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0x26, 0x02 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 0, 0, 0 )
}; // AC Stop
static USB_HID_Report_Element_t hidUsageReport2Byte0Bit1 = {
.item.header = HID_REPORT_SET_HEADER(2, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0x21, 0x02 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 0, 0, 1 )
}; // AC Search
static USB_HID_Report_Element_t hidUsageReport2Byte0Bit2 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE2, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 0, 0, 2 )
}; // Mute
static USB_HID_Report_Element_t hidUsageReport2Byte0Bit4 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xCF, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 0, 0, 4 )
}; // Voice Command
static USB_HID_Report_Element_t hidUsageReport2Byte0Bit6 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE9, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 0, 0, 6 )
}; // Vol+
static USB_HID_Report_Element_t hidUsageReport2Byte0Bit7 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xEA, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 0, 0, 7 )
}; // Vol-
static USB_HID_Report_Element_t hidUsageReport2Byte1Bit7 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE5, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_CONSUMER, 0, 1, 7 )
}; // Bass boost
static USB_HID_Report_Element_t hidUsageReport3Byte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0x20, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_TELEPHONY, 0, 0, 0 )
}; // Hook Switch
static USB_HID_Report_Element_t hidUsageReport3Byte0Bit1 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0x2F, 0x00 },
.location = HID_REPORT_SET_LOC( USB_HID_REPORT_ID_TELEPHONY, 0, 0, 1 )
}; // Phone Mute
/*
* List the configurable elements in the HID Report.
*/
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
&hidUsageReport1Byte0Bit0,
&hidUsageReport1Byte0Bit2,
&hidUsageReport1Byte0Bit3,
&hidUsageReport2Byte0Bit0,
&hidUsageReport2Byte0Bit1,
&hidUsageReport2Byte0Bit2,
&hidUsageReport2Byte0Bit4,
&hidUsageReport2Byte0Bit6,
&hidUsageReport2Byte0Bit7,
&hidUsageReport2Byte1Bit7,
&hidUsageReport3Byte0Bit0,
&hidUsageReport3Byte0Bit1
};
/*
* List HID Reports, one per Report ID. This should be a usage page item with the locator filled out with ID and size
* If not using report IDs - still have one with report ID 0
*/
static const USB_HID_Report_Element_t* const hidReports[] = {
&hidReportKeyboard,
&hidReportConsumer,
&hidReportTelephony
};
/*
* List all items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
&hidUsagePageGenericDesktop,
&hidUsageKeyboard,
&hidReportSize1,
&hidLogicalMinimum0,
&hidCollectionApplication, // Report 1
&hidReportId1,
&(hidReportKeyboard.item),
&hidLogicalMaximum1,
&hidReportCount1,
&(hidUsageReport1Byte0Bit0.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidInputConstArray,
&hidLogicalMaximum1,
&(hidUsageReport1Byte0Bit2.item),
&hidInputDataVar,
&(hidUsageReport1Byte0Bit3.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidReportCount4,
&hidInputConstArray,
&hidCollectionEnd,
&hidUsagePageConsumerControl,
&hidUsageConsumerControl,
&hidCollectionApplication, // Report 2
&hidReportId2,
&(hidReportConsumer.item),
&hidLogicalMaximum1,
&hidReportCount1,
&(hidUsageReport2Byte0Bit0.item),
&hidInputDataVar,
&(hidUsageReport2Byte0Bit1.item),
&hidInputDataVar,
&(hidUsageReport2Byte0Bit2.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidInputConstArray,
&hidLogicalMaximum1,
&(hidUsageReport2Byte0Bit4.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidInputConstArray,
&hidLogicalMaximum1,
&(hidUsageReport2Byte0Bit6.item),
&hidInputDataVar,
&(hidUsageReport2Byte0Bit7.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidReportCount7,
&hidInputConstArray,
&hidLogicalMaximum1,
&hidReportCount1,
&(hidUsageReport2Byte1Bit7.item),
&hidInputDataVar,
&hidCollectionEnd,
&hidUsagePageTelephony,
&hidUsageTelephonyHeadset,
&hidCollectionApplication, // Report 3
&hidReportId3,
&(hidReportTelephony.item),
&(hidUsageReport3Byte0Bit0.item),
&hidInputDataVar,
&(hidUsageReport3Byte0Bit1.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidReportCount6,
&hidInputConstArray,
&hidCollectionEnd,
};
/*
* Define the number of HID Reports
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
*/
#define HID_REPORT_COUNT ( 3 )
#endif // __hid_report_descriptor_h__

View File

@@ -0,0 +1,915 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stddef.h>
#include <stdio.h>
#include "xua_unit_tests.h"
#include "xua_hid_report.h"
// Test constants related to the report descriptor defined in hid_report_descriptor.h
#define REPORT1_MAX_VALID_BIT ( 3 )
#define REPORT1_MAX_VALID_BYTE ( 0 )
#define REPORT1_MIN_VALID_BIT ( 0 )
#define REPORT1_MIN_VALID_BYTE ( 0 )
#define REPORT2_MAX_VALID_BIT ( 7 )
#define REPORT2_MAX_VALID_BYTE ( 1 )
#define REPORT2_MIN_VALID_BIT ( 0 )
#define REPORT2_MIN_VALID_BYTE ( 0 )
#define REPORT3_MAX_VALID_BIT ( 1 )
#define REPORT3_MAX_VALID_BYTE ( 0 )
#define REPORT3_MIN_VALID_BIT ( 0 )
#define REPORT3_MIN_VALID_BYTE ( 0 )
#define HID_REPORT_LENGTH ( 3 )
#define HID_REPORT_COUNT ( 3 )
#define HID_REPORTID_LIMIT ( 4 )
// Constants from USB HID Usage Tables
#define KEYBOARD_PAGE ( 0x07 )
#define CONSUMER_PAGE ( 0x0C )
#define TELEPHONY_DEVICE_PAGE ( 0x0B )
#define LOUDNESS_CONTROL ( 0xE7 )
#define PHONE_KEY_9 ( 0xB9 )
#define KEYBOARD_X ( 0x1B )
#define PHONE_HOST_HOLD ( 0x010A )
static unsigned construct_usage_header( unsigned size )
{
unsigned header = 0x00;
header |= ( HID_REPORT_ITEM_USAGE_TAG << HID_REPORT_ITEM_HDR_TAG_SHIFT ) & HID_REPORT_ITEM_HDR_TAG_MASK;
header |= ( HID_REPORT_ITEM_USAGE_TYPE << HID_REPORT_ITEM_HDR_TYPE_SHIFT ) & HID_REPORT_ITEM_HDR_TYPE_MASK;
header |= ( size << HID_REPORT_ITEM_HDR_SIZE_SHIFT ) & HID_REPORT_ITEM_HDR_SIZE_MASK;
return header;
}
void setUp( void )
{
hidReportInit();
hidResetReportDescriptor();
}
void test_validate_report( void ) {
unsigned retVal = hidReportValidate();
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_reportid_in_use( void ) {
unsigned reportIdInUse = hidIsReportIdInUse();
TEST_ASSERT_EQUAL_UINT( 1, reportIdInUse );
}
void test_get_next_valid_report_id( void ) {
unsigned reportId = 0U;
reportId = hidGetNextValidReportId(reportId);
TEST_ASSERT_EQUAL_UINT( 1, reportId );
reportId = hidGetNextValidReportId(reportId);
TEST_ASSERT_EQUAL_UINT( 2, reportId );
reportId = hidGetNextValidReportId(reportId);
TEST_ASSERT_EQUAL_UINT( 3, reportId );
reportId = hidGetNextValidReportId(reportId);
TEST_ASSERT_EQUAL_UINT( 1, reportId );
}
void test_is_report_id_valid( void ) {
unsigned isValid = 0;
unsigned reportId = 0;
isValid = hidIsReportIdValid( reportId );
TEST_ASSERT_EQUAL_UINT( 0, isValid );
reportId = 1;
isValid = hidIsReportIdValid( reportId );
TEST_ASSERT_EQUAL_UINT( 1, isValid );
reportId = 2;
isValid = hidIsReportIdValid( reportId );
TEST_ASSERT_EQUAL_UINT( 1, isValid );
reportId = 3;
isValid = hidIsReportIdValid( reportId );
TEST_ASSERT_EQUAL_UINT( 1, isValid );
reportId = 4;
isValid = hidIsReportIdValid( reportId );
TEST_ASSERT_EQUAL_UINT( 0, isValid );
}
// Basic report descriptor tests
void test_unprepared_hidGetReportDescriptor( void )
{
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NULL( reportDescPtr );
for (unsigned reportId = 1; reportId <= HID_REPORT_COUNT; reportId++)
{
unsigned reportLength = hidGetReportLength( reportId );
TEST_ASSERT_EQUAL_UINT( 0, reportLength );
}
}
void test_prepared_hidGetReportDescriptor( void )
{
hidPrepareReportDescriptor();
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NOT_NULL( reportDescPtr );
unsigned reportId = 1;
unsigned reportLength = hidGetReportLength( reportId );
TEST_ASSERT_EQUAL_UINT( 1, reportLength );
reportId = 2;
reportLength = hidGetReportLength( reportId );
TEST_ASSERT_EQUAL_UINT( 2, reportLength );
reportId = 3;
reportLength = hidGetReportLength( reportId );
TEST_ASSERT_EQUAL_UINT( 1, reportLength );
}
void test_reset_unprepared_hidGetReportDescriptor( void )
{
hidPrepareReportDescriptor();
hidResetReportDescriptor();
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NULL( reportDescPtr );
}
void test_reset_prepared_hidGetReportDescriptor( void )
{
hidPrepareReportDescriptor();
hidResetReportDescriptor();
hidPrepareReportDescriptor();
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NOT_NULL( reportDescPtr );
}
void test_report_id_limit( void )
{
unsigned reportIdLimit = hidGetReportIdLimit();
TEST_ASSERT_EQUAL_UINT( HID_REPORTID_LIMIT, reportIdLimit );
}
// Basic item tests
void test_max_loc_hidGetReportItem( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ];
unsigned char header;
unsigned char page;
unsigned reportId = 1;
unsigned bit = REPORT1_MAX_VALID_BIT;
unsigned byte = REPORT1_MAX_VALID_BYTE;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( KEYBOARD_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
TEST_ASSERT_EQUAL_UINT( 0x73, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x00, data[ 1 ]);
reportId = 2;
bit = REPORT2_MAX_VALID_BIT;
byte = REPORT2_MAX_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( CONSUMER_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
TEST_ASSERT_EQUAL_UINT( 0xE5, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x00, data[ 1 ]);
reportId = 3;
bit = REPORT3_MAX_VALID_BIT;
byte = REPORT3_MAX_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( TELEPHONY_DEVICE_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
TEST_ASSERT_EQUAL_UINT( 0x2F, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x00, data[ 1 ]);
}
void test_min_loc_hidGetReportItem( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ];
unsigned char header;
unsigned char page;
unsigned reportId = 1;
unsigned bit = REPORT1_MIN_VALID_BIT;
unsigned byte = REPORT1_MIN_VALID_BYTE;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( KEYBOARD_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
TEST_ASSERT_EQUAL_UINT( 0x17, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x00, data[ 1 ]);
reportId = 2;
bit = REPORT2_MIN_VALID_BIT;
byte = REPORT2_MIN_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( CONSUMER_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x0A, header );
TEST_ASSERT_EQUAL_UINT( 0x26, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x02, data[ 1 ]);
reportId = 3;
bit = REPORT3_MIN_VALID_BIT;
byte = REPORT3_MIN_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( TELEPHONY_DEVICE_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
TEST_ASSERT_EQUAL_UINT( 0x20, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x00, data[ 1 ]);
}
void test_invalid_report_id( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD2 };
unsigned char header = 0x33;
unsigned char page = 0x44;
unsigned reportId = 0;
unsigned bit = REPORT1_MIN_VALID_BIT;
unsigned byte = REPORT1_MIN_VALID_BYTE;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_ID, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0x33, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD2, data[ 1 ]);
}
void test_unused_report_id( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD2 };
unsigned char header = 0x33;
unsigned char page = 0x44;
unsigned reportId = 8;
unsigned bit = REPORT1_MIN_VALID_BIT;
unsigned byte = REPORT1_MIN_VALID_BYTE;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_ID, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0x33, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD2, data[ 1 ]);
}
void test_overflow_bit_hidGetReportItem( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned reportId = 1;
unsigned bit = REPORT1_MAX_VALID_BIT + 1;
unsigned byte = REPORT1_MAX_VALID_BYTE;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 2;
bit = REPORT2_MAX_VALID_BIT + 1;
byte = REPORT2_MAX_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 3;
bit = REPORT3_MAX_VALID_BIT + 1;
byte = REPORT3_MAX_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
}
void test_overflow_byte_hidGetReportItem( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned reportId = 1;
unsigned bit = REPORT1_MAX_VALID_BIT;
unsigned byte = REPORT1_MAX_VALID_BYTE + 1;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 2;
bit = REPORT2_MAX_VALID_BIT;
byte = REPORT2_MAX_VALID_BYTE + 1;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 3;
bit = REPORT3_MAX_VALID_BIT;
byte = REPORT3_MAX_VALID_BYTE + 1;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
}
void test_underflow_bit_hidGetReportItem( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned reportId = 1;
unsigned bit = REPORT1_MIN_VALID_BIT - 1;
unsigned byte = REPORT1_MIN_VALID_BYTE;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 2;
bit = REPORT2_MIN_VALID_BIT - 1;
byte = REPORT2_MIN_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 3;
bit = REPORT3_MIN_VALID_BIT - 1;
byte = REPORT3_MIN_VALID_BYTE;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
}
void test_underflow_byte_hidGetReportItem( void )
{
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned reportId = 1;
unsigned bit = REPORT1_MIN_VALID_BIT;
unsigned byte = REPORT1_MIN_VALID_BYTE - 1;
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 2;
bit = REPORT2_MIN_VALID_BIT;
byte = REPORT2_MIN_VALID_BYTE - 1;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
reportId = 3;
bit = REPORT3_MIN_VALID_BIT;
byte = REPORT3_MIN_VALID_BYTE - 1;
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
TEST_ASSERT_EQUAL_UINT( 0xBA, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0xD1, data[ 1 ]);
}
// Configurable and non-configurable item tests
void test_configurable_item_hidSetReportItem( void )
{
const unsigned reportId = 1;
const unsigned bit = REPORT1_MIN_VALID_BIT;
const unsigned byte = REPORT1_MIN_VALID_BYTE;
unsigned char data[ 1 ] = { KEYBOARD_X };
unsigned char header = construct_usage_header( sizeof( data ) / sizeof( unsigned char ));
unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( KEYBOARD_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
TEST_ASSERT_EQUAL_UINT( KEYBOARD_X, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x00, data[ 1 ]);
}
// Testing that the high byte of the report gets correctly cleared
void test_configurable_item_hidSetReportItem_multibyte_orig( void )
{
const unsigned reportId = 2;
const unsigned bit = 1; // This byte&bit combo is originally set be 2 bytes long in the header
const unsigned byte = 0;
unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
unsigned char header = construct_usage_header( sizeof( data ) / sizeof( unsigned char ));
unsigned char page = CONSUMER_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( CONSUMER_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
TEST_ASSERT_EQUAL_UINT( LOUDNESS_CONTROL, data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0x00, data[ 1 ]);
}
void test_nonconfigurable_item_hidSetReportItem( void )
{
const unsigned reportId = 1;
const unsigned bit = 1; // This bit and byte combination should not appear in the
const unsigned byte = 0; // hidConfigurableElements list in hid_report_descriptors.c.
const unsigned char data[ 1 ] = { KEYBOARD_X };
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
const unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
// Bit range tests
void test_max_bit_hidSetReportItem( void )
{
const unsigned char header = construct_usage_header( 0 );
unsigned reportId = 1;
unsigned bit = REPORT1_MAX_VALID_BIT; // See the hidConfigurableElements list in hid_report_descriptors.c.
unsigned byte = REPORT1_MAX_VALID_BYTE;
unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
reportId = 2;
bit = REPORT2_MAX_VALID_BIT;
byte = REPORT2_MAX_VALID_BYTE;
page = CONSUMER_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
reportId = 3;
bit = REPORT3_MAX_VALID_BIT;
byte = REPORT3_MAX_VALID_BYTE;
page = TELEPHONY_DEVICE_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_min_bit_hidSetReportItem( void )
{
const unsigned char header = construct_usage_header( 0 );
unsigned reportId = 1;
unsigned bit = REPORT1_MIN_VALID_BIT; // See the hidConfigurableElements list in hid_report_descriptors.c.
unsigned byte = REPORT1_MIN_VALID_BYTE;
unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
reportId = 2;
bit = REPORT2_MIN_VALID_BIT;
byte = REPORT2_MIN_VALID_BYTE;
page = CONSUMER_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
reportId = 3;
bit = REPORT3_MIN_VALID_BIT;
byte = REPORT3_MIN_VALID_BYTE;
page = TELEPHONY_DEVICE_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_overflow_bit_hidSetReportItem( void )
{
const unsigned char header = construct_usage_header( 0 );
unsigned reportId = 1;
unsigned bit = REPORT1_MAX_VALID_BIT + 1; // See the hidConfigurableElements list in hid_report_descriptors.c.
unsigned byte = REPORT1_MAX_VALID_BYTE;
unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 2;
bit = REPORT2_MAX_VALID_BIT + 1;
byte = REPORT2_MAX_VALID_BYTE;
page = CONSUMER_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 3;
bit = REPORT3_MAX_VALID_BIT + 1;
byte = REPORT3_MAX_VALID_BYTE;
page = TELEPHONY_DEVICE_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
void test_underflow_bit_hidSetReportItem( void )
{
const unsigned char header = construct_usage_header( 0 );
unsigned reportId = 1;
unsigned bit = REPORT1_MIN_VALID_BIT - 1; // See the hidConfigurableElements list in hid_report_descriptors.c.
unsigned byte = REPORT1_MIN_VALID_BYTE;
unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 2;
bit = REPORT2_MIN_VALID_BIT - 1;
byte = REPORT2_MIN_VALID_BYTE;
page = CONSUMER_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 3;
bit = REPORT3_MIN_VALID_BIT - 1;
byte = REPORT3_MIN_VALID_BYTE;
page = TELEPHONY_DEVICE_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
void test_overflow_byte_hidSetReportItem( void )
{
const unsigned char header = construct_usage_header( 0 );
unsigned reportId = 1;
unsigned bit = REPORT1_MAX_VALID_BIT; // See the hidConfigurableElements list in hid_report_descriptors.c.
unsigned byte = REPORT1_MAX_VALID_BYTE + 1;
unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 2;
bit = REPORT2_MAX_VALID_BIT;
byte = REPORT2_MAX_VALID_BYTE + 1;
page = CONSUMER_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 3;
bit = REPORT3_MAX_VALID_BIT;
byte = REPORT3_MAX_VALID_BYTE + 1;
page = TELEPHONY_DEVICE_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
void test_underflow_byte_hidSetReportItem( void )
{
const unsigned char header = construct_usage_header( 0 );
unsigned reportId = 1;
unsigned bit = REPORT1_MIN_VALID_BIT; // See the hidConfigurableElements list in hid_report_descriptors.c.
unsigned byte = REPORT1_MIN_VALID_BYTE - 1;
unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 2;
bit = REPORT2_MIN_VALID_BIT;
byte = REPORT2_MIN_VALID_BYTE - 1;
page = CONSUMER_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
reportId = 3;
bit = REPORT3_MIN_VALID_BIT;
byte = REPORT3_MIN_VALID_BYTE - 1;
page = TELEPHONY_DEVICE_PAGE;
retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
// Size range tests
void test_max_size_hidSetReportItem( void )
{
const unsigned reportId = 1;
const unsigned bit = REPORT1_MIN_VALID_BIT;
const unsigned byte = REPORT1_MIN_VALID_BYTE;
const unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0x00 };
const unsigned char header = construct_usage_header( HID_REPORT_ITEM_MAX_SIZE );
const unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_min_size_hidSetReportItem( void )
{
const unsigned reportId = 1;
const unsigned bit = REPORT1_MIN_VALID_BIT;
const unsigned byte = REPORT1_MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0x00 );
const unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_unsupported_size_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = REPORT1_MIN_VALID_BIT;
const unsigned byte = REPORT1_MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0x03 );
const unsigned char page = KEYBOARD_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
}
// Combined function tests
void test_initial_modification_without_subsequent_preparation( void )
{
const unsigned reportId = 2;
const unsigned bit = REPORT2_MIN_VALID_BIT;
const unsigned byte = REPORT2_MIN_VALID_BYTE;
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
const unsigned char page = CONSUMER_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NULL( reportDescPtr );
}
void test_initial_modification_with_subsequent_preparation( void )
{
const unsigned reportId = 2;
const unsigned bit = REPORT2_MIN_VALID_BIT;
const unsigned byte = REPORT2_MIN_VALID_BYTE;
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
const unsigned char page = CONSUMER_PAGE;
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
hidPrepareReportDescriptor();
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NOT_NULL( reportDescPtr );
}
void test_initial_modification_with_subsequent_verification_1( void )
{
const unsigned reportId = 2;
const unsigned bit = REPORT2_MIN_VALID_BIT;
const unsigned byte = REPORT2_MIN_VALID_BYTE;
unsigned char get_data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xFF, 0xFF };
unsigned char get_header = 0xFF;
unsigned char get_page = 0xFF;
const unsigned char set_data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char set_header = construct_usage_header( sizeof set_data / sizeof( unsigned char ));
const unsigned char set_page = CONSUMER_PAGE;
unsigned setRetVal = hidSetReportItem( reportId, byte, bit, set_page, set_header, set_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, setRetVal );
unsigned getRetVal = hidGetReportItem( reportId, byte, bit, &get_page, &get_header, get_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, getRetVal );
TEST_ASSERT_EQUAL_UINT( set_page, get_page );
TEST_ASSERT_EQUAL_UINT( set_header, get_header );
TEST_ASSERT_EQUAL_UINT( set_data[ 0 ], get_data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0, get_data[ 1 ]); // Should be MSB of data from hidUsageByte0Bit0 in hid_report_descriptor.h
}
void test_initial_modification_with_subsequent_verification_2( void )
{
const unsigned reportId = 3;
const unsigned bit = REPORT3_MIN_VALID_BIT;
const unsigned byte = REPORT3_MIN_VALID_BYTE;
{
unsigned char get_data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xFF, 0xFF };
unsigned char get_header = 0xFF;
unsigned char get_page = 0xFF;
const unsigned char set_data[ 2 ] = {( PHONE_HOST_HOLD & 0x00FF ), (( PHONE_HOST_HOLD & 0xFF00 ) >> 8 )};
const unsigned char set_header = construct_usage_header( sizeof set_data / sizeof( unsigned char ));
const unsigned char set_page = TELEPHONY_DEVICE_PAGE;
unsigned setRetVal = hidSetReportItem( reportId, byte, bit, set_page, set_header, set_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, setRetVal );
unsigned getRetVal = hidGetReportItem( reportId, byte, bit, &get_page, &get_header, get_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, getRetVal );
TEST_ASSERT_EQUAL_UINT( set_page, get_page );
TEST_ASSERT_EQUAL_UINT( set_header, get_header );
TEST_ASSERT_EQUAL_UINT( set_data[ 0 ], get_data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( set_data[ 1 ], get_data[ 1 ]);
}
{
unsigned char get_data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xFF, 0xFF };
unsigned char get_header = 0xFF;
unsigned char get_page = 0xFF;
const unsigned char set_data[ 1 ] = { PHONE_KEY_9 };
const unsigned char set_header = construct_usage_header( sizeof set_data / sizeof( unsigned char ));
const unsigned char set_page = TELEPHONY_DEVICE_PAGE;
unsigned setRetVal = hidSetReportItem( reportId, byte, bit, set_page, set_header, set_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, setRetVal );
unsigned getRetVal = hidGetReportItem( reportId, byte, bit, &get_page, &get_header, get_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, getRetVal );
TEST_ASSERT_EQUAL_UINT( set_page, get_page );
TEST_ASSERT_EQUAL_UINT( set_header, get_header );
TEST_ASSERT_EQUAL_UINT( set_data[ 0 ], get_data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0, get_data[ 1 ]); // The call to hidSetReportItem with size 1 in the header should return the MSB to zero
}
}
//setIdle and associated timing functionality tests
void test_set_idle( void )
{
unsigned reportIdAll = 0;
unsigned reportId = 1;
unsigned reportId2 = 2;
unsigned setIdle = hidIsIdleActive( reportId );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
setIdle = hidIsIdleActive( reportId2 );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
setIdle = hidIsIdleActive( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
hidSetIdle( reportId, 1 );
setIdle = hidIsIdleActive( reportId );
TEST_ASSERT_EQUAL_UINT( 1, setIdle );
setIdle = hidIsIdleActive( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
setIdle = hidIsIdleActive( reportId2 );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
}
void test_set_all_idle( void )
{
unsigned reportIdAll = 0;
unsigned reportId = 1;
unsigned reportId2 = 2;
unsigned setIdle = hidIsIdleActive( reportId );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
setIdle = hidIsIdleActive( reportId2 );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
setIdle = hidIsIdleActive( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
for ( reportId = 1; reportId <= HID_REPORT_COUNT; ++reportId ) {
hidSetIdle( reportId, 1 );
setIdle = hidIsIdleActive( reportId );
TEST_ASSERT_EQUAL_UINT( 1, setIdle );
}
setIdle = hidIsIdleActive( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 1, setIdle );
}
void test_change_pending( void )
{
unsigned reportIdAll = 0;
unsigned reportId = 1;
unsigned reportId2 = 2;
unsigned changePending = hidIsChangePending( reportId );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
changePending = hidIsChangePending( reportId2 );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
changePending = hidIsChangePending( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
hidSetChangePending( reportId );
changePending = hidIsChangePending( reportId );
TEST_ASSERT_EQUAL_UINT( 1, changePending );
changePending = hidIsChangePending( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 1, changePending );
changePending = hidIsChangePending( reportId2 );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
}
void test_change_pending_all( void )
{
unsigned reportIdAll = 0;
unsigned reportId = 1;
unsigned changePending = hidIsChangePending( reportId );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
changePending = hidIsChangePending( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
for ( reportId = 1; reportId <= HID_REPORT_COUNT; ++reportId ) {
hidSetChangePending( reportId );
changePending = hidIsChangePending( reportId );
TEST_ASSERT_EQUAL_UINT( 1, changePending );
}
changePending = hidIsChangePending( reportIdAll );
TEST_ASSERT_EQUAL_UINT( 1, changePending );
}
void test_report_time( void )
{
unsigned reportTime1 = 123;
unsigned reportTime2 = 456;
hidCaptureReportTime(1, reportTime1);
hidCaptureReportTime(2, reportTime2);
reportTime1 = hidGetReportTime(1);
reportTime2 = hidGetReportTime(2);
TEST_ASSERT_EQUAL_UINT(123, reportTime1);
TEST_ASSERT_EQUAL_UINT(456, reportTime2);
}
void test_report_time_calc( void )
{
unsigned reportTime1 = 123;
unsigned reportTime2 = 456;
unsigned reportPeriod1 = 10;
unsigned reportPeriod2 = 5;
hidCaptureReportTime(1, reportTime1);
hidCaptureReportTime(2, reportTime2);
hidSetReportPeriod(1, reportPeriod1);
hidSetReportPeriod(2, reportPeriod2);
reportTime1 = hidGetReportTime(1);
reportTime2 = hidGetReportTime(2);
reportPeriod1 = hidGetReportPeriod(1);
reportPeriod2 = hidGetReportPeriod(2);
TEST_ASSERT_EQUAL_UINT(123, reportTime1);
TEST_ASSERT_EQUAL_UINT(456, reportTime2);
TEST_ASSERT_EQUAL_UINT(10, reportPeriod1);
TEST_ASSERT_EQUAL_UINT(5, reportPeriod2);
hidCalcNextReportTime(1);
hidCalcNextReportTime(2);
unsigned nextReportTime1 = hidGetNextReportTime(1);
unsigned nextReportTime2 = hidGetNextReportTime(2);
TEST_ASSERT_EQUAL_UINT( reportTime1 + reportPeriod1, nextReportTime1 );
TEST_ASSERT_EQUAL_UINT( reportTime2 + reportPeriod2, nextReportTime2 );
}

View File

@@ -0,0 +1,145 @@
// Copyright 2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef __hid_report_descriptor_h__
#define __hid_report_descriptor_h__
#include "xua_hid_report.h"
/*
* Define non-configurable items in the HID Report descriptor.
* (These are short items as the location field isn't relevant for them)
*/
static const USB_HID_Short_Item_t hidCollectionApplication = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionEnd = {
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidCollectionLogical = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidInputConstArray = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidInputDataVar = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
.data = { 0x02, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
.data = { 0x00, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount6 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x06, 0x00 } };
static const USB_HID_Short_Item_t hidReportCount7 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
.data = { 0x07, 0x00 } };
static const USB_HID_Short_Item_t hidReportSize1 = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
.data = { 0x01, 0x00 } };
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.data = { 0x01, 0x00 } };
/*
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
*/
static const USB_HID_Report_Element_t hidReportPageConsumer = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
.location = HID_REPORT_SET_LOC( 0, 2, 0, 0 )
};
/*
* Define configurable items in the HID Report descriptor.
*/
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE2, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 0, 0)
}; // Mute
static USB_HID_Report_Element_t hidUsageByte1Bit7 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xEA, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 1, 7)
}; // Vol-
static USB_HID_Report_Element_t hidUsageByte1Bit0 = {
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
.item.data = { 0xE9, 0x00 },
.location = HID_REPORT_SET_LOC(0, 0, 1, 0)
}; // Vol+
/*
* List the configurable elements in the HID Report descriptor.
*/
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
&hidUsageByte0Bit0,
&hidUsageByte1Bit0,
&hidUsageByte1Bit7
};
/*
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
* If not using report IDs - still have one with report ID 0
*/
static const USB_HID_Report_Element_t* const hidReports[] = {
&hidReportPageConsumer
};
/*
* List all items in the HID Report descriptor.
*/
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
&(hidReportPageConsumer.item),
&hidUsageConsumerControl,
&hidCollectionApplication,
&hidReportSize1,
&hidLogicalMinimum0,
&hidCollectionLogical, // Byte 0
&hidLogicalMaximum1,
&hidReportCount1,
&(hidUsageByte0Bit0.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidReportCount7,
&hidInputConstArray,
&hidCollectionEnd,
&hidCollectionLogical, // Byte 1
&hidLogicalMaximum1,
&hidReportCount1,
&(hidUsageByte1Bit0.item),
&hidInputDataVar,
&hidLogicalMaximum0,
&hidReportCount6,
&hidInputConstArray,
&hidReportCount1,
&hidLogicalMaximum1,
&(hidUsageByte1Bit7.item),
&hidInputDataVar,
&hidCollectionEnd,
&hidCollectionEnd
};
/*
* Define the number of HID Reports
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
*/
#define HID_REPORT_COUNT ( 1 )
#endif // __hid_report_descriptor_h__

View File

@@ -4,16 +4,23 @@
#include <stdio.h>
#include "xua_unit_tests.h"
#include "xua_hid_report_descriptor.h"
#include "hid_report_descriptor.h"
#include "xua_hid_report.h"
#define HID_REPORT_ITEM_TYPE_GLOBAL ( 0x01 )
#define HID_REPORT_ITEM_TYPE_LOCAL ( 0x02 )
#define HID_REPORT_ITEM_TYPE_MAIN ( 0x00 )
#define HID_REPORT_ITEM_TYPE_RESERVED ( 0x03 )
// Test constants related to the report descriptor defined in hid_report_descriptor.h
#define MAX_VALID_BIT ( 7 )
#define MAX_VALID_BYTE ( 1 )
#define MIN_VALID_BIT ( 0 )
#define MIN_VALID_BYTE ( 0 )
#define HID_REPORT_LENGTH ( 2 )
#define HID_REPORT_COUNT ( 1 )
#define HID_REPORTID_LIMIT ( 1 )
// Constants from the USB HID Usage Tables
#define CONSUMER_CONTROL_PAGE ( 0x0C )
#define LOUDNESS_CONTROL ( 0xE7 )
#define AL_CONTROL_PANEL ( 0x019F )
static unsigned construct_usage_header( unsigned size )
{
@@ -29,26 +36,62 @@ static unsigned construct_usage_header( unsigned size )
void setUp( void )
{
hidReportInit();
hidResetReportDescriptor();
}
void test_validate_report( void ) {
unsigned retVal = hidReportValidate();
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_reportid_in_use( void ) {
unsigned reportIdInUse = hidIsReportIdInUse();
TEST_ASSERT_EQUAL_UINT( 0, reportIdInUse );
}
void test_get_next_valid_report_id( void ) {
unsigned reportId = 0U;
reportId = hidGetNextValidReportId(reportId);
TEST_ASSERT_EQUAL_UINT( 0, reportId );
reportId = hidGetNextValidReportId(reportId);
TEST_ASSERT_EQUAL_UINT( 0, reportId );
}
void test_is_report_id_valid( void ) {
unsigned isValid = 0;
unsigned reportId = 0;
isValid = hidIsReportIdValid( reportId );
TEST_ASSERT_EQUAL_UINT( 1, isValid );
reportId = 1;
isValid = hidIsReportIdValid( reportId );
TEST_ASSERT_EQUAL_UINT( 0, isValid );
}
// Basic report descriptor tests
void test_unprepared_hidGetReportDescriptor( void )
{
const unsigned reportId = 0;
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NULL( reportDescPtr );
unsigned reportLength = hidGetReportLength();
unsigned reportLength = hidGetReportLength( reportId );
TEST_ASSERT_EQUAL_UINT( 0, reportLength );
}
void test_prepared_hidGetReportDescriptor( void )
{
const unsigned reportId = 0;
hidPrepareReportDescriptor();
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NOT_NULL( reportDescPtr );
unsigned reportLength = hidGetReportLength();
unsigned reportLength = hidGetReportLength( reportId );
TEST_ASSERT_EQUAL_UINT( HID_REPORT_LENGTH, reportLength );
}
@@ -69,16 +112,23 @@ void test_reset_prepared_hidGetReportDescriptor( void )
TEST_ASSERT_NOT_NULL( reportDescPtr );
}
void test_report_id_limit( void )
{
unsigned reportIdLimit = hidGetReportIdLimit();
TEST_ASSERT_EQUAL_UINT( HID_REPORTID_LIMIT, reportIdLimit );
}
// Basic item tests
void test_max_loc_hidGetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MAX_VALID_BIT;
const unsigned byte = MAX_VALID_BYTE;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ];
unsigned char header;
unsigned char page;
unsigned retVal = hidGetReportItem( byte, bit, &page, &header, data );
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( CONSUMER_CONTROL_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
@@ -88,13 +138,14 @@ void test_max_loc_hidGetReportItem( void )
void test_min_loc_hidGetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ];
unsigned char header;
unsigned char page;
unsigned retVal = hidGetReportItem( byte, bit, &page, &header, data );
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
TEST_ASSERT_EQUAL_UINT( CONSUMER_CONTROL_PAGE, page );
TEST_ASSERT_EQUAL_UINT( 0x09, header );
@@ -104,13 +155,14 @@ void test_min_loc_hidGetReportItem( void )
void test_overflow_bit_hidGetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MAX_VALID_BIT + 1;
const unsigned byte = MAX_VALID_BYTE;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned retVal = hidGetReportItem( byte, bit, &page, &header, data );
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
@@ -120,13 +172,14 @@ void test_overflow_bit_hidGetReportItem( void )
void test_overflow_byte_hidGetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MAX_VALID_BIT;
const unsigned byte = MAX_VALID_BYTE + 1;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned retVal = hidGetReportItem( byte, bit, &page, &header, data );
unsigned retVal = hidGetReportItem( reportId, byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
@@ -136,13 +189,14 @@ void test_overflow_byte_hidGetReportItem( void )
void test_underflow_bit_hidGetReportItem( void )
{
const int bit = MIN_VALID_BIT - 1;
const unsigned reportId = 0;
const int bit = MIN_VALID_BIT - 1;
const unsigned byte = MIN_VALID_BYTE;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned retVal = hidGetReportItem( byte, ( unsigned ) bit, &page, &header, data );
unsigned retVal = hidGetReportItem( reportId, byte, ( unsigned ) bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
@@ -152,13 +206,14 @@ void test_underflow_bit_hidGetReportItem( void )
void test_underflow_byte_hidGetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const int byte = MIN_VALID_BYTE - 1;
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xBA, 0xD1 };
unsigned char header = 0xAA;
unsigned char page = 0x44;
unsigned retVal = hidGetReportItem(( unsigned ) byte, bit, &page, &header, data );
unsigned retVal = hidGetReportItem( reportId, ( unsigned ) byte, bit, &page, &header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
TEST_ASSERT_EQUAL_UINT( 0x44, page );
TEST_ASSERT_EQUAL_UINT( 0xAA, header );
@@ -169,226 +224,245 @@ void test_underflow_byte_hidGetReportItem( void )
// Configurable and non-configurable item tests
void test_configurable_item_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, data );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_nonconfigurable_item_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MAX_VALID_BIT; // This bit and byte combination should not appear in the
const unsigned byte = MIN_VALID_BYTE; // hidConfigurableItems list in hid_report_descriptors.c.
const unsigned byte = MIN_VALID_BYTE; // hidConfigurableElements list in hid_report_descriptors.c.
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, data );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
// Bit range tests
void test_max_bit_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MAX_VALID_BIT; // Only byte 1 has bit 7 not reserved, See the
const unsigned byte = MAX_VALID_BYTE; // hidConfigurableItems list in hid_report_descriptors.c.
const unsigned byte = MAX_VALID_BYTE; // hidConfigurableElements list in hid_report_descriptors.c.
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_min_bit_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_overflow_bit_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MAX_VALID_BIT + 1;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
void test_underflow_bit_hidSetReportItem( void )
{
const unsigned reportId = 0;
const int bit = MIN_VALID_BIT - 1;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, ( unsigned ) bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, ( unsigned ) bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
// Byte range tests
void test_max_byte_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MAX_VALID_BYTE;
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_min_byte_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_overflow_byte_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MAX_VALID_BYTE + 1;
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
void test_underflow_byte_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const int byte = MIN_VALID_BYTE - 1;
const unsigned char header = construct_usage_header( 0 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( ( unsigned ) byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, ( unsigned ) byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
}
// Size range tests
void test_max_size_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0x00 };
const unsigned char header = construct_usage_header( HID_REPORT_ITEM_MAX_SIZE );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, data );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_min_size_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0x00 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_unsupported_size_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = construct_usage_header( 0x03 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
}
// Header tag and type tests
void test_bad_tag_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char good_header = construct_usage_header( 0x00 );
const unsigned char page = CONSUMER_CONTROL_PAGE;
for( unsigned tag = 0x01; tag <= 0x0F; ++tag ) {
unsigned char bad_header = good_header | (( 0x0F << HID_REPORT_ITEM_HDR_TAG_SHIFT ) & HID_REPORT_ITEM_HDR_TAG_MASK );
unsigned retVal = hidSetReportItem( byte, bit, page, bad_header, NULL );
unsigned char bad_header = good_header | (( tag << HID_REPORT_ITEM_HDR_TAG_SHIFT ) & HID_REPORT_ITEM_HDR_TAG_MASK );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, bad_header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
}
}
void test_global_type_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = ( construct_usage_header( 0x00 ) & ~HID_REPORT_ITEM_HDR_TYPE_MASK ) |
(( HID_REPORT_ITEM_TYPE_GLOBAL << HID_REPORT_ITEM_HDR_TYPE_SHIFT ) & HID_REPORT_ITEM_HDR_TYPE_MASK );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
}
void test_local_type_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = ( construct_usage_header( 0x00 ) & ~HID_REPORT_ITEM_HDR_TYPE_MASK ) |
(( HID_REPORT_ITEM_TYPE_LOCAL << HID_REPORT_ITEM_HDR_TYPE_SHIFT ) & HID_REPORT_ITEM_HDR_TYPE_MASK );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
}
void test_main_type_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = ( construct_usage_header( 0x00 ) & ~HID_REPORT_ITEM_HDR_TYPE_MASK ) |
(( HID_REPORT_ITEM_TYPE_MAIN << HID_REPORT_ITEM_HDR_TYPE_SHIFT ) & HID_REPORT_ITEM_HDR_TYPE_MASK );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
}
void test_reserved_type_hidSetReportItem( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char header = ( construct_usage_header( 0x00 ) & ~HID_REPORT_ITEM_HDR_TYPE_MASK ) |
(( HID_REPORT_ITEM_TYPE_RESERVED << HID_REPORT_ITEM_HDR_TYPE_SHIFT ) & HID_REPORT_ITEM_HDR_TYPE_MASK );
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, NULL );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, NULL );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
}
// Combined function tests
void test_initial_modification_without_subsequent_preparation( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, data );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
unsigned char* reportDescPtr = hidGetReportDescriptor();
@@ -397,13 +471,14 @@ void test_initial_modification_without_subsequent_preparation( void )
void test_initial_modification_with_subsequent_preparation( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
const unsigned char page = CONSUMER_CONTROL_PAGE;
unsigned retVal = hidSetReportItem( byte, bit, page, header, data );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
hidPrepareReportDescriptor();
@@ -411,8 +486,9 @@ void test_initial_modification_with_subsequent_preparation( void )
TEST_ASSERT_NOT_NULL( reportDescPtr );
}
void test_initial_modification_with_subsequent_verification( void )
void test_initial_modification_with_subsequent_verification_1( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
@@ -424,15 +500,62 @@ void test_initial_modification_with_subsequent_verification( void )
const unsigned char set_header = construct_usage_header( sizeof set_data / sizeof( unsigned char ));
const unsigned char set_page = CONSUMER_CONTROL_PAGE;
unsigned setRetVal = hidSetReportItem( byte, bit, set_page, set_header, set_data );
unsigned setRetVal = hidSetReportItem( reportId, byte, bit, set_page, set_header, set_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, setRetVal );
unsigned getRetVal = hidGetReportItem( byte, bit, &get_page, &get_header, get_data );
unsigned getRetVal = hidGetReportItem( reportId, byte, bit, &get_page, &get_header, get_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, getRetVal );
TEST_ASSERT_EQUAL_UINT( get_page, set_page );
TEST_ASSERT_EQUAL_UINT( get_header, set_header );
TEST_ASSERT_EQUAL_UINT( get_data[ 0 ], set_data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( get_data[ 1 ], set_data[ 1 ]);
TEST_ASSERT_EQUAL_UINT( set_page, get_page );
TEST_ASSERT_EQUAL_UINT( set_header, get_header );
TEST_ASSERT_EQUAL_UINT( set_data[ 0 ], get_data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0, get_data[ 1 ]); // Should be MSB of data from hidUsageByte0Bit0 in hid_report_descriptor.h
}
void test_initial_modification_with_subsequent_verification_2( void )
{
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
{
unsigned char get_data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xFF, 0xFF };
unsigned char get_header = 0xFF;
unsigned char get_page = 0xFF;
const unsigned char set_data[ 2 ] = {( AL_CONTROL_PANEL & 0x00FF ), (( AL_CONTROL_PANEL & 0xFF00 ) >> 8 )};
const unsigned char set_header = construct_usage_header( sizeof set_data / sizeof( unsigned char ));
const unsigned char set_page = CONSUMER_CONTROL_PAGE;
unsigned setRetVal = hidSetReportItem( reportId, byte, bit, set_page, set_header, set_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, setRetVal );
unsigned getRetVal = hidGetReportItem( reportId, byte, bit, &get_page, &get_header, get_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, getRetVal );
TEST_ASSERT_EQUAL_UINT( set_page, get_page );
TEST_ASSERT_EQUAL_UINT( set_header, get_header );
TEST_ASSERT_EQUAL_UINT( set_data[ 0 ], get_data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( set_data[ 1 ], get_data[ 1 ]);
}
{
unsigned char get_data[ HID_REPORT_ITEM_MAX_SIZE ] = { 0xFF, 0xFF };
unsigned char get_header = 0xFF;
unsigned char get_page = 0xFF;
const unsigned char set_data[ 1 ] = { LOUDNESS_CONTROL };
const unsigned char set_header = construct_usage_header( sizeof set_data / sizeof( unsigned char ));
const unsigned char set_page = CONSUMER_CONTROL_PAGE;
unsigned setRetVal = hidSetReportItem( reportId, byte, bit, set_page, set_header, set_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, setRetVal );
unsigned getRetVal = hidGetReportItem( reportId, byte, bit, &get_page, &get_header, get_data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, getRetVal );
TEST_ASSERT_EQUAL_UINT( set_page, get_page );
TEST_ASSERT_EQUAL_UINT( set_header, get_header );
TEST_ASSERT_EQUAL_UINT( set_data[ 0 ], get_data[ 0 ]);
TEST_ASSERT_EQUAL_UINT( 0, get_data[ 1 ]); // The call to hidSetReportItem with size 1 in the header should return the MSB to zero
}
}
void test_modification_without_subsequent_preparation( void )
@@ -441,6 +564,7 @@ void test_modification_without_subsequent_preparation( void )
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NOT_NULL( reportDescPtr );
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
@@ -448,7 +572,7 @@ void test_modification_without_subsequent_preparation( void )
const unsigned char page = CONSUMER_CONTROL_PAGE;
hidResetReportDescriptor();
unsigned retVal = hidSetReportItem( byte, bit, page, header, data );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
reportDescPtr = hidGetReportDescriptor();
@@ -461,6 +585,7 @@ void test_modification_with_subsequent_preparation( void )
unsigned char* reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NOT_NULL( reportDescPtr );
const unsigned reportId = 0;
const unsigned bit = MIN_VALID_BIT;
const unsigned byte = MIN_VALID_BYTE;
const unsigned char data[ 1 ] = { LOUDNESS_CONTROL };
@@ -468,10 +593,58 @@ void test_modification_with_subsequent_preparation( void )
const unsigned char page = CONSUMER_CONTROL_PAGE;
hidResetReportDescriptor();
unsigned retVal = hidSetReportItem( byte, bit, page, header, data );
unsigned retVal = hidSetReportItem( reportId, byte, bit, page, header, data );
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
hidPrepareReportDescriptor();
reportDescPtr = hidGetReportDescriptor();
TEST_ASSERT_NOT_NULL( reportDescPtr );
}
//setIdle functionality tests
void test_set_idle( void )
{
unsigned reportId = 0;
unsigned setIdle = hidIsIdleActive( reportId );
TEST_ASSERT_EQUAL_UINT( 0, setIdle );
hidSetIdle( reportId, 1 );
setIdle = hidIsIdleActive( reportId );
TEST_ASSERT_EQUAL_UINT( 1, setIdle );
}
void test_change_pending( void )
{
unsigned reportId = 0;
unsigned changePending = hidIsChangePending( reportId );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
hidSetChangePending( reportId );
changePending = hidIsChangePending( reportId );
TEST_ASSERT_EQUAL_UINT( 1, changePending );
hidClearChangePending( reportId );
changePending = hidIsChangePending( reportId );
TEST_ASSERT_EQUAL_UINT( 0, changePending );
}
void test_report_time( void )
{
unsigned reportTime = 123;
unsigned reportPeriod = 10;
hidSetReportPeriod(0, reportPeriod);
hidCaptureReportTime(0, reportTime);
reportTime = hidGetReportTime(0);
reportPeriod = hidGetReportPeriod(0);
TEST_ASSERT_EQUAL_UINT(123, reportTime);
TEST_ASSERT_EQUAL_UINT(10, reportPeriod);
hidCalcNextReportTime(0);
unsigned nextReportTime = hidGetNextReportTime(0);
TEST_ASSERT_EQUAL_UINT(133, nextReportTime);
}

View File

@@ -13,7 +13,7 @@ in port p_mclk_in = XS1_PORT_1D;
/* Clock-block declarations */
clock clk_audio_bclk = on tile[0]: XS1_CLKBLK_1; /* Bit clock */
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_4; /* Master clock */
clock clk_audio_mclk = on tile[0]: XS1_CLKBLK_2; /* Master clock */
// Supply missing but unused function
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)

View File

@@ -95,6 +95,7 @@ def add_unity_runner_build_config(waf_conf, project_root_path, unity_test_path,
def prepare_unity_test_for_build(waf_conf, project_root_path, unity_test_path,
unity_runner_dir, unity_runner_suffix, target):
print("unity_test_path: " + str(unity_test_path))
generate_unity_runner(project_root_path, unity_test_path,
unity_runner_dir, unity_runner_suffix)
runner_build_flags = '' # Could extract flags from the test name
@@ -107,7 +108,12 @@ def find_unity_test_paths(unity_test_dir, unity_test_prefix):
Return a list of all file paths with the unity_test_prefix found in the
unity_test_dir.
"""
return glob.glob(os.path.join(unity_test_dir, unity_test_prefix+'*'))
file_list = []
for root, dirs, files in os.walk(unity_test_dir):
for f in files:
if f.startswith(unity_test_prefix):
file_list.append(os.path.join(root,f))
return file_list
def find_unity_tests(unity_test_dir, unity_test_prefix):
@@ -116,7 +122,7 @@ def find_unity_tests(unity_test_dir, unity_test_prefix):
unity_test_prefix found in the unity_test_dir.
"""
unity_test_paths = find_unity_test_paths(unity_test_dir, unity_test_prefix)
return {get_test_name(path): get_file_type(path)
return {get_test_name(path): {"language": get_file_type(path), "dir": os.path.dirname(path)}
for path in unity_test_paths}
@@ -139,8 +145,8 @@ def generate_all_unity_runners(waf_conf, project_root_path,
# TODO: can the xwaf boilerplate help here?
def create_waf_contexts(configs):
for trgt in TARGETS:
for test_name, test_language in configs.items():
print(f"test_name {test_name}, test_language {test_language}")
for test_name, params in configs.items():
print(f"test_name {test_name}, test_language {params['language']}")
for ctx in (BuildContext, CleanContext):
raw_context = ctx.__name__.replace('Context', '').lower()
@@ -149,9 +155,10 @@ def create_waf_contexts(configs):
variant = test_name + '_' + trgt
#cmd = raw_context + '_' + test_name
#variant = test_name
language = test_language
language = params["language"]
target = trgt
runner = test_name
directory = params["dir"]
print(f"cmd {cmd}, variant {variant}, language {language}")
@@ -161,6 +168,8 @@ UNITY_RUNNER_DIR = 'runners'
UNITY_RUNNER_SUFFIX = '_Runner'
UNITY_TESTS = find_unity_tests(UNITY_TEST_DIR, UNITY_TEST_PREFIX)
print("UNITY_TESTS: " + str(UNITY_TESTS))
create_waf_contexts(UNITY_TESTS)
def options(opt):
@@ -175,7 +184,6 @@ def configure(conf):
UNITY_RUNNER_DIR, UNITY_RUNNER_SUFFIX)
conf.load('xwaf.xcommon')
def build(bld):
if not bld.variant:
print('Adding test runners to build queue')
@@ -204,7 +212,7 @@ def build(bld):
'Unity']
makefile_opts = {}
makefile_opts['SOURCE_DIRS'] = ['src', os.path.join('runners',bld.runner)]
makefile_opts['SOURCE_DIRS'] = ['src', bld.directory, os.path.join('runners',bld.runner)]
if(bld.target == 'xcoreai'):
print('TARGET XCOREAI')
makefile_opts['TARGET'] = ['XCORE-AI-EXPLORER']
@@ -213,6 +221,7 @@ def build(bld):
makefile_opts['TARGET'] = ['XCORE-200-EXPLORER']
makefile_opts['INCLUDE_DIRS'] = ['src',
bld.directory,
'../../lib_xua/api',
'../../lib_xua/src/core/pdm_mics',
'../../lib_xua/src/hid',