Merge pull request #191 from mbanth/feature/configurable_hid
Create a configurable HID report
This commit is contained in:
@@ -7,6 +7,9 @@ lib_xua Change Log
|
|||||||
* CHANGED: Move HID descriptors to ease maintenance
|
* CHANGED: Move HID descriptors to ease maintenance
|
||||||
* CHANGED: Move legacy tests to separate directory
|
* CHANGED: Move legacy tests to separate directory
|
||||||
* CHANGED: Replace unused GPI-specific HID event names with generic ones
|
* CHANGED: Replace unused GPI-specific HID event names with generic ones
|
||||||
|
* ADDED: Build default HID Report descriptor at boot-time
|
||||||
|
* ADDED: Function to return length of HID Report
|
||||||
|
* CHANGED: HID Report to return multiple bytes
|
||||||
|
|
||||||
1.2.0
|
1.2.0
|
||||||
-----
|
-----
|
||||||
|
|||||||
56
Jenkinsfile
vendored
56
Jenkinsfile
vendored
@@ -27,7 +27,7 @@ pipeline {
|
|||||||
xcoreLibraryChecks("${REPO}")
|
xcoreLibraryChecks("${REPO}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Tests') {
|
stage('XS2 Tests') {
|
||||||
failFast true
|
failFast true
|
||||||
parallel {
|
parallel {
|
||||||
stage('Legacy tests') {
|
stage('Legacy tests') {
|
||||||
@@ -35,8 +35,62 @@ pipeline {
|
|||||||
runXmostest("${REPO}", 'legacy_tests')
|
runXmostest("${REPO}", 'legacy_tests')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stage('Unit tests') {
|
||||||
|
steps {
|
||||||
|
dir("${REPO}") {
|
||||||
|
dir('tests') {
|
||||||
|
dir('xua_unit_tests') {
|
||||||
|
withVenv {
|
||||||
|
runWaf('.', "configure clean build --target=xcore200")
|
||||||
|
// runWaf('.', "configure clean build --target=xcoreai")
|
||||||
|
// stash name: 'xua_unit_tests', includes: 'bin/*xcoreai.xe, '
|
||||||
|
viewEnv() {
|
||||||
|
runPython("TARGET=XCORE200 pytest -n 1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// stage('xcore.ai Verification') {
|
||||||
|
// agent {
|
||||||
|
// label 'xcore.ai-explorer'
|
||||||
|
// }
|
||||||
|
// options {
|
||||||
|
// skipDefaultCheckout()
|
||||||
|
// }
|
||||||
|
// stages{
|
||||||
|
// stage('Get View') {
|
||||||
|
// steps {
|
||||||
|
// xcorePrepareSandbox("${VIEW}", "${REPO}")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// stage('Unit tests') {
|
||||||
|
// steps {
|
||||||
|
// dir("${REPO}") {
|
||||||
|
// dir('tests') {
|
||||||
|
// dir('xua_unit_tests') {
|
||||||
|
// withVenv {
|
||||||
|
// unstash 'xua_unit_tests'
|
||||||
|
// viewEnv() {
|
||||||
|
// runPython("TARGET=XCOREAI pytest -s")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } // stages
|
||||||
|
// post {
|
||||||
|
// cleanup {
|
||||||
|
// cleanWs()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
stage('xCORE builds') {
|
stage('xCORE builds') {
|
||||||
steps {
|
steps {
|
||||||
dir("${REPO}") {
|
dir("${REPO}") {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ APP_NAME = app_xua_simple
|
|||||||
TARGET = xk-audio-216-mc.xn
|
TARGET = xk-audio-216-mc.xn
|
||||||
|
|
||||||
# The flags passed to xcc when building the application
|
# The flags passed to xcc when building the application
|
||||||
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -fsubword-select -save-temps \
|
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -save-temps \
|
||||||
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES -DUSB_TILE=tile[1] -fxscope
|
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES -DUSB_TILE=tile[1] -fxscope
|
||||||
|
|
||||||
#-DSDA_HIGH=2 -DSCL_HIGH=1 -fxscope
|
#-DSDA_HIGH=2 -DSCL_HIGH=1 -fxscope
|
||||||
|
|||||||
105
examples/AN00246_xua_example/src/hid_report_descriptor.h
Normal file
105
examples/AN00246_xua_example/src/hid_report_descriptor.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Existing static report descriptor kept for reference */
|
||||||
|
unsigned char hidReportDescriptor[] =
|
||||||
|
{
|
||||||
|
0x05, 0x0c, /* Usage Page (Consumer Device) */
|
||||||
|
0x09, 0x01, /* Usage (Consumer Control) */
|
||||||
|
0xa1, 0x01, /* Collection (Application) */
|
||||||
|
0x15, 0x00, /* Logical Minimum (0) */
|
||||||
|
0x25, 0x01, /* Logical Maximum (1) */
|
||||||
|
0x09, 0xb0, /* Usage (Play) */
|
||||||
|
0x09, 0xb5, /* Usage (Scan Next Track) */
|
||||||
|
0x09, 0xb6, /* Usage (Scan Previous Track) */
|
||||||
|
0x09, 0xe9, /* Usage (Volume Up) */
|
||||||
|
0x09, 0xea, /* Usage (Volume Down) */
|
||||||
|
0x09, 0xe2, /* Usage (Mute) */
|
||||||
|
0x75, 0x01, /* Report Size (1) */
|
||||||
|
0x95, 0x06, /* Report Count (6) */
|
||||||
|
0x81, 0x02, /* Input (Data, Var, Abs) */
|
||||||
|
0x95, 0x02, /* Report Count (2) */
|
||||||
|
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
|
||||||
|
0xc0 /* End collection */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 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 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 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 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List the configurable items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List all items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||||
|
&hidUsagePageConsumer,
|
||||||
|
&hidUsageConsumerControl,
|
||||||
|
&hidCollectionApplication,
|
||||||
|
&hidLogicalMinimum0,
|
||||||
|
&hidLogicalMaximum1,
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5,
|
||||||
|
&hidReportSize1,
|
||||||
|
&hidReportCount6,
|
||||||
|
&hidInputDataVar,
|
||||||
|
&hidLogicalMaximum0,
|
||||||
|
&hidReportCount2,
|
||||||
|
&hidInputConstArray,
|
||||||
|
&hidCollectionEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the length of the HID Report.
|
||||||
|
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
|
||||||
|
*/
|
||||||
|
#define HID_REPORT_LENGTH ( 1 )
|
||||||
|
|
||||||
|
#endif // __hid_report_descriptor_h__
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</Links>
|
</Links>
|
||||||
<ExternalDevices>
|
<ExternalDevices>
|
||||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K">
|
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ APP_NAME = app_xua_simple
|
|||||||
TARGET = xk-audio-216-mc.xn
|
TARGET = xk-audio-216-mc.xn
|
||||||
|
|
||||||
# The flags passed to xcc when building the application
|
# The flags passed to xcc when building the application
|
||||||
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -fsubword-select -save-temps \
|
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -save-temps \
|
||||||
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES -DUSB_TILE=tile[1] \
|
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES -DUSB_TILE=tile[1] \
|
||||||
-DSDA_HIGH=2 -DSCL_HIGH=1 -fxscope
|
-DSDA_HIGH=2 -DSCL_HIGH=1 -fxscope
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Existing static report descriptor kept for reference */
|
||||||
|
unsigned char hidReportDescriptor[] =
|
||||||
|
{
|
||||||
|
0x05, 0x0c, /* Usage Page (Consumer Device) */
|
||||||
|
0x09, 0x01, /* Usage (Consumer Control) */
|
||||||
|
0xa1, 0x01, /* Collection (Application) */
|
||||||
|
0x15, 0x00, /* Logical Minimum (0) */
|
||||||
|
0x25, 0x01, /* Logical Maximum (1) */
|
||||||
|
0x09, 0xb0, /* Usage (Play) */
|
||||||
|
0x09, 0xb5, /* Usage (Scan Next Track) */
|
||||||
|
0x09, 0xb6, /* Usage (Scan Previous Track) */
|
||||||
|
0x09, 0xe9, /* Usage (Volume Up) */
|
||||||
|
0x09, 0xea, /* Usage (Volume Down) */
|
||||||
|
0x09, 0xe2, /* Usage (Mute) */
|
||||||
|
0x75, 0x01, /* Report Size (1) */
|
||||||
|
0x95, 0x06, /* Report Count (6) */
|
||||||
|
0x81, 0x02, /* Input (Data, Var, Abs) */
|
||||||
|
0x95, 0x02, /* Report Count (2) */
|
||||||
|
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
|
||||||
|
0xc0 /* End collection */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 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 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 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 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List the configurable items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List all items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||||
|
&hidUsagePageConsumer,
|
||||||
|
&hidUsageConsumerControl,
|
||||||
|
&hidCollectionApplication,
|
||||||
|
&hidLogicalMinimum0,
|
||||||
|
&hidLogicalMaximum1,
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5,
|
||||||
|
&hidReportSize1,
|
||||||
|
&hidReportCount6,
|
||||||
|
&hidInputDataVar,
|
||||||
|
&hidLogicalMaximum0,
|
||||||
|
&hidReportCount2,
|
||||||
|
&hidInputConstArray,
|
||||||
|
&hidCollectionEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the length of the HID Report.
|
||||||
|
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
|
||||||
|
*/
|
||||||
|
#define HID_REPORT_LENGTH ( 1 )
|
||||||
|
|
||||||
|
#endif // __hid_report_descriptor_h__
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</Links>
|
</Links>
|
||||||
<ExternalDevices>
|
<ExternalDevices>
|
||||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K">
|
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ APP_NAME = app_xua_simple
|
|||||||
TARGET = mic_array_ref.xn
|
TARGET = mic_array_ref.xn
|
||||||
|
|
||||||
# The flags passed to xcc when building the application
|
# The flags passed to xcc when building the application
|
||||||
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -fsubword-select -save-temps \
|
XCC_FLAGS = -fcomment-asm -Xmapper --map -Xmapper MAPFILE -O3 -report -save-temps \
|
||||||
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES -DUSB_TILE=tile[1] \
|
-g -Wno-unused-function -Wno-timing -DXUD_SERIES_SUPPORT=XUD_X200_SERIES -DUSB_TILE=tile[1] \
|
||||||
-DSDA_HIGH=2 -DSCL_HIGH=1 -fxscope
|
-DSDA_HIGH=2 -DSCL_HIGH=1 -fxscope
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Existing static report descriptor kept for reference */
|
||||||
|
unsigned char hidReportDescriptor[] =
|
||||||
|
{
|
||||||
|
0x05, 0x0c, /* Usage Page (Consumer Device) */
|
||||||
|
0x09, 0x01, /* Usage (Consumer Control) */
|
||||||
|
0xa1, 0x01, /* Collection (Application) */
|
||||||
|
0x15, 0x00, /* Logical Minimum (0) */
|
||||||
|
0x25, 0x01, /* Logical Maximum (1) */
|
||||||
|
0x09, 0xb0, /* Usage (Play) */
|
||||||
|
0x09, 0xb5, /* Usage (Scan Next Track) */
|
||||||
|
0x09, 0xb6, /* Usage (Scan Previous Track) */
|
||||||
|
0x09, 0xe9, /* Usage (Volume Up) */
|
||||||
|
0x09, 0xea, /* Usage (Volume Down) */
|
||||||
|
0x09, 0xe2, /* Usage (Mute) */
|
||||||
|
0x75, 0x01, /* Report Size (1) */
|
||||||
|
0x95, 0x06, /* Report Count (6) */
|
||||||
|
0x81, 0x02, /* Input (Data, Var, Abs) */
|
||||||
|
0x95, 0x02, /* Report Count (2) */
|
||||||
|
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
|
||||||
|
0xc0 /* End collection */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 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 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 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 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List the configurable items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List all items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||||
|
&hidUsagePageConsumer,
|
||||||
|
&hidUsageConsumerControl,
|
||||||
|
&hidCollectionApplication,
|
||||||
|
&hidLogicalMinimum0,
|
||||||
|
&hidLogicalMaximum1,
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5,
|
||||||
|
&hidReportSize1,
|
||||||
|
&hidReportCount6,
|
||||||
|
&hidInputDataVar,
|
||||||
|
&hidLogicalMaximum0,
|
||||||
|
&hidReportCount2,
|
||||||
|
&hidInputConstArray,
|
||||||
|
&hidCollectionEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the length of the HID Report.
|
||||||
|
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
|
||||||
|
*/
|
||||||
|
#define HID_REPORT_LENGTH ( 1 )
|
||||||
|
|
||||||
|
#endif // __hid_report_descriptor_h__
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</Links>
|
</Links>
|
||||||
<ExternalDevices>
|
<ExternalDevices>
|
||||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K">
|
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||||
|
|||||||
105
legacy_tests/app_test_i2s_loopback/hid_report_descriptor.h
Normal file
105
legacy_tests/app_test_i2s_loopback/hid_report_descriptor.h
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Existing static report descriptor kept for reference */
|
||||||
|
unsigned char hidReportDescriptor[] =
|
||||||
|
{
|
||||||
|
0x05, 0x0c, /* Usage Page (Consumer Device) */
|
||||||
|
0x09, 0x01, /* Usage (Consumer Control) */
|
||||||
|
0xa1, 0x01, /* Collection (Application) */
|
||||||
|
0x15, 0x00, /* Logical Minimum (0) */
|
||||||
|
0x25, 0x01, /* Logical Maximum (1) */
|
||||||
|
0x09, 0xb0, /* Usage (Play) */
|
||||||
|
0x09, 0xb5, /* Usage (Scan Next Track) */
|
||||||
|
0x09, 0xb6, /* Usage (Scan Previous Track) */
|
||||||
|
0x09, 0xe9, /* Usage (Volume Up) */
|
||||||
|
0x09, 0xea, /* Usage (Volume Down) */
|
||||||
|
0x09, 0xe2, /* Usage (Mute) */
|
||||||
|
0x75, 0x01, /* Report Size (1) */
|
||||||
|
0x95, 0x06, /* Report Count (6) */
|
||||||
|
0x81, 0x02, /* Input (Data, Var, Abs) */
|
||||||
|
0x95, 0x02, /* Report Count (2) */
|
||||||
|
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
|
||||||
|
0xc0 /* End collection */
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 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 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 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 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List the configurable items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List all items in the HID Report descriptor.
|
||||||
|
*/
|
||||||
|
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||||
|
&hidUsagePageConsumer,
|
||||||
|
&hidUsageConsumerControl,
|
||||||
|
&hidCollectionApplication,
|
||||||
|
&hidLogicalMinimum0,
|
||||||
|
&hidLogicalMaximum1,
|
||||||
|
&hidUsageByte0Bit0,
|
||||||
|
&hidUsageByte0Bit1,
|
||||||
|
&hidUsageByte0Bit2,
|
||||||
|
&hidUsageByte0Bit3,
|
||||||
|
&hidUsageByte0Bit4,
|
||||||
|
&hidUsageByte0Bit5,
|
||||||
|
&hidReportSize1,
|
||||||
|
&hidReportCount6,
|
||||||
|
&hidInputDataVar,
|
||||||
|
&hidLogicalMaximum0,
|
||||||
|
&hidReportCount2,
|
||||||
|
&hidInputConstArray,
|
||||||
|
&hidCollectionEnd
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the length of the HID Report.
|
||||||
|
* This value must match the number of Report bytes defined by hidReportDescriptorItems.
|
||||||
|
*/
|
||||||
|
#define HID_REPORT_LENGTH ( 1 )
|
||||||
|
|
||||||
|
#endif // __hid_report_descriptor_h__
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
</Links>
|
</Links>
|
||||||
<ExternalDevices>
|
<ExternalDevices>
|
||||||
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25LQ016B" PageSize="256" SectorSize="4096" NumPages="8192">
|
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
|
||||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
|
||||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
|
||||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#define __custom_defines_h__
|
#define __custom_defines_h__
|
||||||
|
|
||||||
#define EXCLUDE_USB_AUDIO_MAIN
|
#define EXCLUDE_USB_AUDIO_MAIN
|
||||||
#define NUM_PDM_MICS 0
|
#define XUA_NUM_PDM_MICS 0
|
||||||
#define XUD_TILE 1
|
#define XUD_TILE 1
|
||||||
#define AUDIO_IO_TILE 0
|
#define AUDIO_IO_TILE 0
|
||||||
#define MIXER 0
|
#define MIXER 0
|
||||||
|
|||||||
@@ -21,8 +21,9 @@
|
|||||||
#include "testct_byref.h"
|
#include "testct_byref.h"
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if( 0 < HID_CONTROLS )
|
||||||
|
#include "xua_hid_report_descriptor.h"
|
||||||
#include "user_hid.h"
|
#include "user_hid.h"
|
||||||
unsigned char g_hidData[HID_DATA_BYTES] = {0};
|
unsigned char g_hidData[HID_MAX_DATA_BYTES] = {0};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void GetADCCounts(unsigned samFreq, int &min, int &mid, int &max);
|
void GetADCCounts(unsigned samFreq, int &min, int &mid, int &max);
|
||||||
@@ -371,7 +372,10 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if( 0 < HID_CONTROLS )
|
||||||
XUD_SetReady_In(ep_hid, g_hidData, 1);
|
{
|
||||||
|
int hidDataLength = hidGetReportLength();
|
||||||
|
XUD_SetReady_In(ep_hid, g_hidData, hidDataLength);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (AUDIO_CLASS == 1)
|
#if (AUDIO_CLASS == 1)
|
||||||
@@ -885,9 +889,9 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
|
|||||||
/* HID Report Data */
|
/* HID Report Data */
|
||||||
case XUD_SetData_Select(c_hid, ep_hid, result):
|
case XUD_SetData_Select(c_hid, ep_hid, result):
|
||||||
{
|
{
|
||||||
g_hidData[0]=0;
|
int hidDataLength = hidGetReportLength();
|
||||||
UserHIDGetData(g_hidData);
|
UserHIDGetData(g_hidData);
|
||||||
XUD_SetReady_In(ep_hid, g_hidData, 1);
|
XUD_SetReady_In(ep_hid, g_hidData, hidDataLength);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,18 +23,24 @@
|
|||||||
#include "vendorrequests.h"
|
#include "vendorrequests.h"
|
||||||
#include "xc_ptr.h"
|
#include "xc_ptr.h"
|
||||||
#include "xua_ep0_uacreqs.h"
|
#include "xua_ep0_uacreqs.h"
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if( 0 < HID_CONTROLS )
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
|
#include "xua_hid.h"
|
||||||
|
#include "xua_hid_report_descriptor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DSD_CHANS_DAC > 0
|
#if DSD_CHANS_DAC > 0
|
||||||
#include "dsd_support.h"
|
#include "dsd_support.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DEBUG_UNIT XUA_EP0
|
#define DEBUG_UNIT XUA_EP0
|
||||||
|
|
||||||
#ifndef DEBUG_PRINT_ENABLE_XUA_EP0
|
#ifndef DEBUG_PRINT_ENABLE_XUA_EP0
|
||||||
#define DEBUG_PRINT_ENABLE_XUA_EP0 0
|
#define DEBUG_PRINT_ENABLE_XUA_EP0 0
|
||||||
#endif // DEBUG_PRINT_ENABLE_XUA_EP0
|
#endif // DEBUG_PRINT_ENABLE_XUA_EP0
|
||||||
#include "debug_print.h"
|
|
||||||
|
|
||||||
|
#include "debug_print.h"
|
||||||
#include "xua_usb_params_funcs.h"
|
#include "xua_usb_params_funcs.h"
|
||||||
|
|
||||||
#ifndef __XC__
|
#ifndef __XC__
|
||||||
@@ -51,7 +57,7 @@
|
|||||||
#if ((AUDIO_CLASS == 1) || (AUDIO_CLASS_FALLBACK)) && defined(DFU)
|
#if ((AUDIO_CLASS == 1) || (AUDIO_CLASS_FALLBACK)) && defined(DFU)
|
||||||
#warning DFU will not be enabled in AUDIO 1.0 mode due to Windows requesting driver
|
#warning DFU will not be enabled in AUDIO 1.0 mode due to Windows requesting driver
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif // FORCE_UAC1_DFU
|
||||||
|
|
||||||
/* MIDI not supported in Audio 1.0 mode */
|
/* MIDI not supported in Audio 1.0 mode */
|
||||||
#if ((AUDIO_CLASS == 1) || (AUDIO_CLASS_FALLBACK)) && defined(MIDI)
|
#if ((AUDIO_CLASS == 1) || (AUDIO_CLASS_FALLBACK)) && defined(MIDI)
|
||||||
@@ -85,9 +91,6 @@ extern void device_reboot(void);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
|
||||||
#include "xua_hid.h"
|
|
||||||
#endif
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
#endif
|
#endif
|
||||||
@@ -518,6 +521,22 @@ void XUA_Endpoint0_init(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioCont
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if( 0 < HID_CONTROLS )
|
||||||
|
hidPrepareReportDescriptor();
|
||||||
|
|
||||||
|
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
|
||||||
|
unsigned char hidReportDescriptorLengthLo = hidReportDescriptorLength & 0xFF;
|
||||||
|
unsigned char hidReportDescriptorLengthHi = (hidReportDescriptorLength & 0xFF00) >> 8;
|
||||||
|
|
||||||
|
#if( AUDIO_CLASS == 1 )
|
||||||
|
cfgDesc_Audio1[USB_HID_DESCRIPTOR_OFFSET + HID_DESCRIPTOR_LENGTH_FIELD_OFFSET ] = hidReportDescriptorLengthLo;
|
||||||
|
cfgDesc_Audio1[USB_HID_DESCRIPTOR_OFFSET + HID_DESCRIPTOR_LENGTH_FIELD_OFFSET + 1] = hidReportDescriptorLengthHi;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET ] = hidReportDescriptorLengthLo;
|
||||||
|
hidDescriptor[HID_DESCRIPTOR_LENGTH_FIELD_OFFSET + 1] = hidReportDescriptorLengthHi;
|
||||||
|
#endif // 0 < HID_CONTROLS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
|
void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl,
|
||||||
@@ -729,15 +748,22 @@ void XUA_Endpoint0_loop(XUD_Result_t result, USB_SetupPacket_t sp, chanend c_ep0
|
|||||||
switch (descriptorType)
|
switch (descriptorType)
|
||||||
{
|
{
|
||||||
case HID_HID:
|
case HID_HID:
|
||||||
/* Return HID Descriptor */
|
{
|
||||||
result = XUD_DoGetRequest(ep0_out, ep0_in, hidDescriptor,
|
/* Return HID Descriptor */
|
||||||
sizeof(hidDescriptor), sp.wLength);
|
result = XUD_DoGetRequest(ep0_out, ep0_in, hidDescriptor,
|
||||||
|
sizeof(hidDescriptor), sp.wLength);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case HID_REPORT:
|
case HID_REPORT:
|
||||||
/* Return HID report descriptor */
|
{
|
||||||
result = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptor,
|
/* Return HID report descriptor */
|
||||||
sizeof(hidReportDescriptor), sp.wLength);
|
unsigned char* hidReportDescriptorPtr;
|
||||||
break;
|
hidReportDescriptorPtr = hidGetReportDescriptor();
|
||||||
|
size_t hidReportDescriptorLength = hidGetReportDescriptorLength();
|
||||||
|
result = XUD_DoGetRequest(ep0_out, ep0_in, hidReportDescriptorPtr,
|
||||||
|
hidReportDescriptorLength, sp.wLength);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -580,33 +580,6 @@ unsigned char devQualDesc_Null[] =
|
|||||||
#define MIXER_LENGTH (0)
|
#define MIXER_LENGTH (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
|
||||||
unsigned char hidReportDescriptor[] =
|
|
||||||
{
|
|
||||||
0x05, 0x01, /* Usage Page (Generic Desktop) */
|
|
||||||
0x09, 0x06, /* Usage (Keyboard) */
|
|
||||||
0xa1, 0x01, /* Collection (Application) */
|
|
||||||
0x75, 0x01, /* Report Size (1) */
|
|
||||||
0x95, 0x04, /* Report Count (4) */
|
|
||||||
0x15, 0x00, /* Logical Minimum (0) */
|
|
||||||
0x25, 0x00, /* Logical Maximum (0) */
|
|
||||||
0x81, 0x01, /* Input (Cnst, Ary, Abs, No Wrap, Lin, Pref, No Nul) */
|
|
||||||
0x95, 0x01, /* Report Count (1) */
|
|
||||||
0x25, 0x01, /* Logical Maximum (1) */
|
|
||||||
0x05, 0x0C, /* Usage Page (Consumer) */
|
|
||||||
0x0a, 0x21, 0x02, /* Usage (AC Search) */
|
|
||||||
0x81, 0x02, /* Input (Data, Var, Abs, No Wrap, Lin, Pref, No Nul) */
|
|
||||||
0x0a, 0x26, 0x02, /* Usage (AC Stop) */
|
|
||||||
0x81, 0x02, /* Input (Data, Var, Abs, No Wrap, Lin, Pref, No Nul) */
|
|
||||||
0x95, 0x02, /* Report Count (2) */
|
|
||||||
0x05, 0x07, /* Usage Page (Key Codes) */
|
|
||||||
0x19, 0x72, /* Usage Minimum (Keyboard F23) */
|
|
||||||
0x29, 0x73, /* Usage Maximum (Keyboard F24) */
|
|
||||||
0x81, 0x02, /* Input (Data, Var, Abs, No Wrap, Lin, Pref, No Nul) */
|
|
||||||
0xc0 /* End collection (Application) */
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Max packet sizes:
|
/* Max packet sizes:
|
||||||
* Samples per channel. e.g (192000+7999/8000) = 24
|
* Samples per channel. e.g (192000+7999/8000) = 24
|
||||||
* Must allow 1 sample extra per chan (24 + 1) = 25
|
* Must allow 1 sample extra per chan (24 + 1) = 25
|
||||||
@@ -2373,6 +2346,10 @@ const unsigned num_freqs_a1 = MAX(3, (0
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if( 0 < HID_CONTROLS )
|
||||||
|
#define USB_HID_DESCRIPTOR_OFFSET (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + INTERFACE_DESCRIPTOR_BYTES)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CHARIFY_SR(x) (x & 0xff),((x & 0xff00)>> 8),((x & 0xff0000)>> 16)
|
#define CHARIFY_SR(x) (x & 0xff),((x & 0xff00)>> 8),((x & 0xff0000)>> 16)
|
||||||
|
|
||||||
#if (MIN_FREQ_FS < 12000) && (MAX_FREQ_FS > 48000)
|
#if (MIN_FREQ_FS < 12000) && (MAX_FREQ_FS > 48000)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ typedef enum hidEventId_t {
|
|||||||
HID_EVENT_ID_INVALID = 0xffffffff,
|
HID_EVENT_ID_INVALID = 0xffffffff,
|
||||||
} hidEventId_t;
|
} hidEventId_t;
|
||||||
|
|
||||||
#define HID_DATA_BYTES 4
|
#define HID_MAX_DATA_BYTES 4
|
||||||
|
|
||||||
#if( 0 < HID_CONTROLS )
|
#if( 0 < HID_CONTROLS )
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ typedef enum hidEventId_t {
|
|||||||
*
|
*
|
||||||
* \param{out} hidData The HID data
|
* \param{out} hidData The HID data
|
||||||
*/
|
*/
|
||||||
void UserHIDGetData( unsigned char hidData[ HID_DATA_BYTES ]);
|
void UserHIDGetData( unsigned char hidData[ HID_MAX_DATA_BYTES ]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initialize HID processing
|
* \brief Initialize HID processing
|
||||||
@@ -70,17 +70,15 @@ void UserHIDInit( void );
|
|||||||
/**
|
/**
|
||||||
* \brief Record that a HID event has occurred
|
* \brief Record that a HID event has occurred
|
||||||
*
|
*
|
||||||
* \param{in} hidEventId The identifier of an event which has occurred
|
* \param{in} hidEventId The identifier of an event which has occurred.
|
||||||
* \param{in} hidEventData A list of data associated with the event
|
* Each event corresponds to bit in the HID Report:
|
||||||
* \param{in} hidEventDataSize The length of the event data list
|
* Events 0- 7 to bits 0-7 of byte 0,
|
||||||
*
|
* Events 8-15 to bits 0-7 of byte 1, etc.
|
||||||
* \note At present, this function only takes a single element of event data, i.e.
|
* \param{in} hidEventData A Boolean indicating the state of the event:
|
||||||
* hidEventDataSize must equal 1.
|
* Zero = deasserted,
|
||||||
*
|
* Any other value = asserted.
|
||||||
* \note At present, this function treats the event data as a Boolean flag.
|
|
||||||
* Zero means False; all other values mean True.
|
|
||||||
*/
|
*/
|
||||||
void UserHIDRecordEvent( const hidEventId_t hidEventId, const int * hidEventData, const unsigned hidEventDataSize );
|
void UserHIDRecordEvent( const hidEventId_t hidEventId, const unsigned hidEventData );
|
||||||
|
|
||||||
#endif /* ( 0 < HID_CONTROLS ) */
|
#endif /* ( 0 < HID_CONTROLS ) */
|
||||||
#endif /* __USER_HID_H__ */
|
#endif /* __USER_HID_H__ */
|
||||||
|
|||||||
212
lib_xua/src/hid/hid_report_descriptor.c
Normal file
212
lib_xua/src/hid/hid_report_descriptor.c
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
// 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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hidGetReportLength( void )
|
||||||
|
{
|
||||||
|
size_t retVal = ( hidReportDescriptorPrepared ) ? HID_REPORT_LENGTH : 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HID_CONFIGURABLE_ITEM_COUNT ( sizeof hidConfigurableItems / sizeof ( USB_HID_Short_Item_t* ))
|
||||||
|
unsigned hidSetReportItem( const unsigned byte, const unsigned bit, 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 )) {
|
||||||
|
item.header = header;
|
||||||
|
|
||||||
|
for( unsigned dataIdx = 0; dataIdx < bSize; ++dataIdx ) {
|
||||||
|
item.data[ dataIdx ] = data[ dataIdx ];
|
||||||
|
}
|
||||||
|
|
||||||
|
*hidConfigurableItems[ itemIdx ] = item;
|
||||||
|
retVal = HID_STATUS_GOOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
#ifndef _HID_DESCRIPTOR_
|
#ifndef _HID_DESCRIPTOR_
|
||||||
#define _HID_DESCRIPTOR_
|
#define _HID_DESCRIPTOR_
|
||||||
|
|
||||||
|
#define HID_DESCRIPTOR_LENGTH_FIELD_OFFSET ( 7 )
|
||||||
|
|
||||||
/* USB HID Descriptor (section 6.2.1) */
|
/* USB HID Descriptor (section 6.2.1) */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
|
|
||||||
#include "xua_hid_descriptor.h"
|
#include "xua_hid_descriptor.h"
|
||||||
|
|
||||||
#define HID_DESCRIPTOR_LENGTH_0 0x09 /* Size of descriptor in Bytes */
|
#define HID_DESCRIPTOR_LENGTH_0 ( 0x09 ) /* Size of descriptor in Bytes */
|
||||||
#define HID_DESCRIPTOR_TYPE_0 0x21 /* HID 0x21 */
|
#define HID_DESCRIPTOR_TYPE_0 ( 0x21 ) /* HID 0x21 */
|
||||||
#define HID_BCD_VERSION_LO 0x10 /* HID class specification release */
|
#define HID_BCD_VERSION_LO ( 0x10 ) /* HID class specification release */
|
||||||
#define HID_BCD_VERSION_HI 0x01
|
#define HID_BCD_VERSION_HI ( 0x01 )
|
||||||
#define HID_COUNTRY_CODE 0x00 /* Country code of localized hardware */
|
#define HID_COUNTRY_CODE ( 0x00 ) /* Country code of localized hardware */
|
||||||
#define HID_NUM_DESCRIPTORS 0x01 /* Number of class descriptors */
|
#define HID_NUM_DESCRIPTORS ( 0x01 ) /* Number of class descriptors */
|
||||||
#define HID_DESCRIPTOR_TYPE_1 0x22 /* Type of 1st class descriptor, Report 0x22 */
|
#define HID_DESCRIPTOR_TYPE_1 ( 0x22 ) /* Type of 1st class descriptor, Report 0x22 */
|
||||||
#define HID_DESCRIPTOR_LENGTH_1_LO sizeof(hidReportDescriptor) & 0xff
|
#define HID_DESCRIPTOR_LENGTH_1_LO ( 0x00 ) /* Length of 1st class descriptor, set to zero */
|
||||||
#define HID_DESCRIPTOR_LENGTH_1_HI sizeof(hidReportDescriptor) >> 8
|
#define HID_DESCRIPTOR_LENGTH_1_HI ( 0x00 ) /* since only pre-processor directives allowed here */
|
||||||
|
|
||||||
#endif // _HID_DESCRIPTOR_CONTENTS_
|
#endif // _HID_DESCRIPTOR_CONTENTS_
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,11 @@
|
|||||||
|
|
||||||
#include "descriptor_defs.h"
|
#include "descriptor_defs.h"
|
||||||
|
|
||||||
#define HID_ENDPOINT_DESCRIPTOR_LENGTH 0x07 /* Size of descriptor in Bytes */
|
#define HID_ENDPOINT_DESCRIPTOR_LENGTH ( 0x07 ) /* Size of descriptor in Bytes */
|
||||||
#define HID_ENDPOINT_DESCRIPTOR_TYPE 0x05 /* Endpoint 0x05 */
|
#define HID_ENDPOINT_DESCRIPTOR_TYPE ( 0x05 ) /* Endpoint 0x05 */
|
||||||
#define HID_ENDPOINT_ATTRIBUTES 0x03 /* Interrupt */
|
#define HID_ENDPOINT_ATTRIBUTES ( 0x03 ) /* Interrupt */
|
||||||
#define HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_LO 0x40
|
#define HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_LO ( 0x40 )
|
||||||
#define HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_HI 0x00
|
#define HID_ENDPOINT_DESCRIPTOR_PACKET_SIZE_HI ( 0x00 )
|
||||||
|
|
||||||
#endif // _HID_ENDPOINT_DESCRIPTOR_CONTENTS_
|
#endif // _HID_ENDPOINT_DESCRIPTOR_CONTENTS_
|
||||||
|
|
||||||
|
|||||||
@@ -12,14 +12,14 @@
|
|||||||
|
|
||||||
#include "descriptor_defs.h"
|
#include "descriptor_defs.h"
|
||||||
|
|
||||||
#define HID_INTERFACE_DESCRIPTOR_LENGTH 0x09 /* Size of descriptor in Bytes */
|
#define HID_INTERFACE_DESCRIPTOR_LENGTH ( 0x09 ) /* Size of descriptor in Bytes */
|
||||||
#define HID_INTERFACE_DESCRIPTOR_TYPE 0x04 /* Interface 0x04 */
|
#define HID_INTERFACE_DESCRIPTOR_TYPE ( 0x04 ) /* Interface 0x04 */
|
||||||
#define HID_INTERFACE_ALTERNATE_SETTING 0x00 /* Value used alternate interfaces using SetInterface Request */
|
#define HID_INTERFACE_ALTERNATE_SETTING ( 0x00 ) /* Value used alternate interfaces using SetInterface Request */
|
||||||
#define HID_INTERFACE_NUMBER_OF_ENDPOINTS 0x01 /* Number of endpoitns for this interface (excluding 0) */
|
#define HID_INTERFACE_NUMBER_OF_ENDPOINTS ( 0x01 ) /* Number of endpoitns for this interface (excluding 0) */
|
||||||
#define HID_INTERFACE_CLASS 0x03
|
#define HID_INTERFACE_CLASS ( 0x03 )
|
||||||
#define HID_INTERFACE_SUBCLASS 0x00 /* No boot device */
|
#define HID_INTERFACE_SUBCLASS ( 0x00 ) /* No boot device */
|
||||||
#define HID_INTERFACE_PROTOCOL 0x00
|
#define HID_INTERFACE_PROTOCOL ( 0x00 )
|
||||||
#define HID_INTERFACE_STRING_DESCRIPTOR_INDEX 0x00
|
#define HID_INTERFACE_STRING_DESCRIPTOR_INDEX ( 0x00 )
|
||||||
|
|
||||||
#endif // _HID_INTERFACE_DESCRIPTOR_CONTENTS_
|
#endif // _HID_INTERFACE_DESCRIPTOR_CONTENTS_
|
||||||
|
|
||||||
|
|||||||
147
lib_xua/src/hid/xua_hid_report_descriptor.h
Normal file
147
lib_xua/src/hid/xua_hid_report_descriptor.h
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
// 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_
|
||||||
|
|
||||||
|
#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_IN_USE ( 3 )
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 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] 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_IN_USE The Report descriptor is in use
|
||||||
|
*/
|
||||||
|
unsigned hidSetReportItem( const unsigned byte, const unsigned bit, const unsigned char header, const unsigned char data[] );
|
||||||
|
|
||||||
|
#endif // _HID_REPORT_DESCRIPTOR_
|
||||||
@@ -14,6 +14,8 @@ setuptools.setup(
|
|||||||
packages=setuptools.find_packages(),
|
packages=setuptools.find_packages(),
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'flake8~=3.8',
|
'flake8~=3.8',
|
||||||
|
'pytest~=6.0',
|
||||||
|
'pytest-xdist~=1.34',
|
||||||
],
|
],
|
||||||
dependency_links=[
|
dependency_links=[
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
# same modules should appear in the setup.py list as given below.
|
# same modules should appear in the setup.py list as given below.
|
||||||
|
|
||||||
flake8==3.8.3
|
flake8==3.8.3
|
||||||
|
pytest==6.0.0
|
||||||
|
pytest-xdist==1.34.0
|
||||||
|
|
||||||
# Development dependencies
|
# Development dependencies
|
||||||
#
|
#
|
||||||
|
|||||||
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
|
*/runners/*
|
||||||
test_results.csv
|
test_results.csv
|
||||||
|
|||||||
23
tests/xua_unit_tests/config.xscope
Normal file
23
tests/xua_unit_tests/config.xscope
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<!-- ======================================================= -->
|
||||||
|
<!-- The 'ioMode' attribute on the xSCOPEconfig -->
|
||||||
|
<!-- element can take the following values: -->
|
||||||
|
<!-- "none", "basic", "timed" -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- The 'type' attribute on Probe -->
|
||||||
|
<!-- elements can take the following values: -->
|
||||||
|
<!-- "STARTSTOP", "CONTINUOUS", "DISCRETE", "STATEMACHINE" -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- The 'datatype' attribute on Probe -->
|
||||||
|
<!-- elements can take the following values: -->
|
||||||
|
<!-- "NONE", "UINT", "INT", "FLOAT" -->
|
||||||
|
<!-- ======================================================= -->
|
||||||
|
|
||||||
|
<xSCOPEconfig ioMode="none" enabled="false">
|
||||||
|
|
||||||
|
<!-- For example: -->
|
||||||
|
<!-- <Probe name="Probe Name" type="CONTINUOUS" datatype="UINT" units="Value" enabled="true"/> -->
|
||||||
|
<!-- From the target code, call: xscope_int(PROBE_NAME, value); -->
|
||||||
|
|
||||||
|
</xSCOPEconfig>
|
||||||
115
tests/xua_unit_tests/conftest.py
Normal file
115
tests/xua_unit_tests/conftest.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
# Copyright 2021 XMOS LIMITED.
|
||||||
|
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
from __future__ import print_function
|
||||||
|
from builtins import str
|
||||||
|
import os.path
|
||||||
|
import pytest
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
target = os.environ.get('TARGET', 'all_possible')
|
||||||
|
print("target = ", target)
|
||||||
|
|
||||||
|
def pytest_collect_file(parent, path):
|
||||||
|
if(path.ext == ".xe"):
|
||||||
|
if(target == 'all_possible'):
|
||||||
|
return UnityTestSource.from_parent(parent, fspath=path)
|
||||||
|
if(target == 'XCOREAI' and ('xcoreai' in path.basename)):
|
||||||
|
return UnityTestSource.from_parent(parent, fspath=path)
|
||||||
|
if(target == 'XCORE200' and ('xcore200' in path.basename)):
|
||||||
|
return UnityTestSource.from_parent(parent, fspath=path)
|
||||||
|
|
||||||
|
|
||||||
|
class UnityTestSource(pytest.File):
|
||||||
|
def collect(self):
|
||||||
|
# Find the binary built from the runner for this test file
|
||||||
|
#
|
||||||
|
# Assume the following directory layout:
|
||||||
|
# unit_tests/ <- Test root directory
|
||||||
|
# |-- bin/ <- Compiled binaries of the test runners
|
||||||
|
# |-- conftest.py <- This file
|
||||||
|
# |-- runners/ <- Auto-generated buildable source of test binaries
|
||||||
|
# |-- src/ <- Unity test functions
|
||||||
|
# `-- wscript <- Build system file used to generate/build runners
|
||||||
|
xe_name = ((os.path.basename(self.name)).split("."))[0] + ".xe"
|
||||||
|
test_bin_path = os.path.join('bin', xe_name)
|
||||||
|
|
||||||
|
yield UnityTestExecutable.from_parent(self, name=self.name)
|
||||||
|
|
||||||
|
|
||||||
|
class UnityTestExecutable(pytest.Item):
|
||||||
|
def __init__(self, name, parent):
|
||||||
|
super(UnityTestExecutable, self).__init__(name, parent)
|
||||||
|
self._nodeid = self.name # Override the naming to suit C better
|
||||||
|
|
||||||
|
def runtest(self):
|
||||||
|
# Run the binary in the simulator
|
||||||
|
simulator_fail = False
|
||||||
|
test_output = None
|
||||||
|
try:
|
||||||
|
if('xcore200' in self.name):
|
||||||
|
print("run axe for executable ", self.name)
|
||||||
|
test_output = subprocess.check_output(['axe', self.name], text=True)
|
||||||
|
else:
|
||||||
|
print("run xrun for executable ", self.name)
|
||||||
|
test_output = subprocess.check_output(['xrun', '--io', '--id', '0', self.name], text=True, stderr=subprocess.STDOUT)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
# Unity exits non-zero if an assertion fails
|
||||||
|
simulator_fail = True
|
||||||
|
test_output = e.output
|
||||||
|
|
||||||
|
# Parse the Unity output
|
||||||
|
unity_pass = False
|
||||||
|
test_output = test_output.split('\n')
|
||||||
|
for line in test_output:
|
||||||
|
if 'test' in line:
|
||||||
|
test_report = line.split(':')
|
||||||
|
# Unity output is as follows:
|
||||||
|
# <test_source>:<line_number>:<test_case>:PASS
|
||||||
|
# <test_source>:<line_number>:<test_case>:FAIL:<failure_reason>
|
||||||
|
test_source = test_report[0]
|
||||||
|
line_number = test_report[1]
|
||||||
|
test_case = test_report[2]
|
||||||
|
result = test_report[3]
|
||||||
|
failure_reason = None
|
||||||
|
print(('\n {}()'.format(test_case)), end=' ')
|
||||||
|
if result == 'PASS':
|
||||||
|
unity_pass = True
|
||||||
|
continue
|
||||||
|
if result == 'FAIL':
|
||||||
|
failure_reason = test_report[4]
|
||||||
|
print('') # Insert line break after test_case print
|
||||||
|
raise UnityTestException(self, {'test_source': test_source,
|
||||||
|
'line_number': line_number,
|
||||||
|
'test_case': test_case,
|
||||||
|
'failure_reason':
|
||||||
|
failure_reason})
|
||||||
|
|
||||||
|
if simulator_fail:
|
||||||
|
raise Exception(self, "Simulation failed.")
|
||||||
|
if not unity_pass:
|
||||||
|
raise Exception(self, "Unity test output not found.")
|
||||||
|
print('') # Insert line break after final test_case which passed
|
||||||
|
|
||||||
|
def repr_failure(self, excinfo):
|
||||||
|
if isinstance(excinfo.value, UnityTestException):
|
||||||
|
return '\n'.join([str(self.parent).strip('<>'),
|
||||||
|
'{}:{}:{}()'.format(
|
||||||
|
excinfo.value[1]['test_source'],
|
||||||
|
excinfo.value[1]['line_number'],
|
||||||
|
excinfo.value[1]['test_case']),
|
||||||
|
'Failure reason:',
|
||||||
|
excinfo.value[1]['failure_reason']])
|
||||||
|
else:
|
||||||
|
return str(excinfo.value)
|
||||||
|
|
||||||
|
def reportinfo(self):
|
||||||
|
# It's not possible to give sensible line number info for an executable
|
||||||
|
# so we return it as 0.
|
||||||
|
#
|
||||||
|
# The source line number will instead be recovered from the Unity print
|
||||||
|
# statements.
|
||||||
|
return self.fspath, 0, self.name
|
||||||
|
|
||||||
|
|
||||||
|
class UnityTestException(Exception):
|
||||||
|
pass
|
||||||
120
tests/xua_unit_tests/generate_unity_runners.py
Normal file
120
tests/xua_unit_tests/generate_unity_runners.py
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# Copyright 2021 XMOS LIMITED.
|
||||||
|
# This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
import glob
|
||||||
|
import os.path
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
UNITY_TEST_DIR = 'src'
|
||||||
|
UNITY_TEST_PREFIX = 'test_'
|
||||||
|
UNITY_RUNNER_DIR = 'runners'
|
||||||
|
UNITY_RUNNER_SUFFIX = '_Runner'
|
||||||
|
project_root = os.path.join('..', '..', '..')
|
||||||
|
|
||||||
|
def get_ruby():
|
||||||
|
"""
|
||||||
|
Check ruby is avaliable and return the command to invoke it.
|
||||||
|
"""
|
||||||
|
interpreter_name = 'ruby'
|
||||||
|
try:
|
||||||
|
dev_null = open(os.devnull, 'w')
|
||||||
|
# Call the version command to check the interpreter can be run
|
||||||
|
subprocess.check_call([interpreter_name, '--version'],
|
||||||
|
stdout=dev_null,
|
||||||
|
close_fds=True)
|
||||||
|
except OSError as e:
|
||||||
|
print("Failed to run Ruby interpreter: {}".format(e), file=sys.stderr)
|
||||||
|
exit(1) # TODO: Check this is the correct way to kill xwaf on error
|
||||||
|
|
||||||
|
return interpreter_name
|
||||||
|
|
||||||
|
def get_unity_runner_generator(project_root_path):
|
||||||
|
"""
|
||||||
|
Check the Unity generate_test_runner script is avaliable, and return the
|
||||||
|
path to it.
|
||||||
|
"""
|
||||||
|
unity_runner_generator = os.path.join(
|
||||||
|
project_root_path, 'Unity', 'auto', 'generate_test_runner.rb')
|
||||||
|
if not os.path.exists(unity_runner_generator):
|
||||||
|
print("Unity repo not found in workspace", file=sys.stderr)
|
||||||
|
exit(1) # TODO: Check this is the correct way to kill xwaf on error
|
||||||
|
return unity_runner_generator
|
||||||
|
|
||||||
|
|
||||||
|
def get_test_name(test_path):
|
||||||
|
"""
|
||||||
|
Return the test name by removing the extension from the filename.
|
||||||
|
"""
|
||||||
|
return os.path.splitext(os.path.basename(test_path))[0]
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_type(filename):
|
||||||
|
"""
|
||||||
|
Return the extension from the filename.
|
||||||
|
"""
|
||||||
|
return filename.rsplit('.')[-1:][0]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_unity_runner(project_root_path, unity_test_path, unity_runner_dir,
|
||||||
|
unity_runner_suffix):
|
||||||
|
"""
|
||||||
|
Invoke the Unity runner generation script for the given test file, and
|
||||||
|
return the path to the generated file. The output directory will be created
|
||||||
|
if it does not already exist.
|
||||||
|
"""
|
||||||
|
runner_path = os.path.join(os.path.join(unity_runner_dir, get_test_name(unity_test_path)))
|
||||||
|
if not os.path.exists(runner_path):
|
||||||
|
os.makedirs(runner_path)
|
||||||
|
|
||||||
|
unity_runner_path = os.path.join(
|
||||||
|
runner_path, get_test_name(unity_test_path) + unity_runner_suffix
|
||||||
|
+ '.' + 'c')
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.check_call([get_ruby(),
|
||||||
|
get_unity_runner_generator(project_root_path),
|
||||||
|
unity_test_path,
|
||||||
|
unity_runner_path])
|
||||||
|
except OSError as e:
|
||||||
|
print("Ruby generator failed for {}\n\t{}".format(unity_test_path, e),
|
||||||
|
file=sys.stderr)
|
||||||
|
exit(1) # TODO: Check this is the correct way to kill xwaf on error
|
||||||
|
|
||||||
|
|
||||||
|
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+'*'))
|
||||||
|
|
||||||
|
|
||||||
|
def find_unity_tests(unity_test_dir, unity_test_prefix):
|
||||||
|
"""
|
||||||
|
Return a dictionary of all {test names, test language} pairs with the
|
||||||
|
unity_test_prefix found in the unity_test_dir.
|
||||||
|
"""
|
||||||
|
unity_test_paths = find_unity_test_paths(unity_test_dir, unity_test_prefix)
|
||||||
|
print('unity_test_paths = ', unity_test_paths)
|
||||||
|
return {get_test_name(path): get_file_type(path)
|
||||||
|
for path in unity_test_paths}
|
||||||
|
|
||||||
|
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+'*'))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_runners():
|
||||||
|
UNITY_TESTS = find_unity_tests(UNITY_TEST_DIR, UNITY_TEST_PREFIX)
|
||||||
|
print('UNITY_TESTS = ',UNITY_TESTS)
|
||||||
|
unity_test_paths = find_unity_test_paths(UNITY_TEST_DIR, UNITY_TEST_PREFIX)
|
||||||
|
print('unity_test_paths = ',unity_test_paths)
|
||||||
|
for unity_test_path in unity_test_paths:
|
||||||
|
generate_unity_runner(project_root, unity_test_path, UNITY_RUNNER_DIR, UNITY_RUNNER_SUFFIX)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
generate_runners()
|
||||||
94
tests/xua_unit_tests/src/hid_report_descriptor.h
Normal file
94
tests/xua_unit_tests/src/hid_report_descriptor.h
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// 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 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__
|
||||||
333
tests/xua_unit_tests/src/test_hid.c
Normal file
333
tests/xua_unit_tests/src/test_hid.c
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
// 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_descriptor.h"
|
||||||
|
#include "hid_report_descriptor.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 )
|
||||||
|
|
||||||
|
#define LOUDNESS_CONTROL ( 0xE7 )
|
||||||
|
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
hidResetReportDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic report descriptor tests
|
||||||
|
void test_unprepared_hidGetReportDescriptor( void )
|
||||||
|
{
|
||||||
|
unsigned char* reportDescPtr = hidGetReportDescriptor();
|
||||||
|
TEST_ASSERT_NULL( reportDescPtr );
|
||||||
|
|
||||||
|
unsigned reportLength = hidGetReportLength();
|
||||||
|
TEST_ASSERT_EQUAL_UINT( 0, reportLength );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_prepared_hidGetReportDescriptor( void )
|
||||||
|
{
|
||||||
|
hidPrepareReportDescriptor();
|
||||||
|
unsigned char* reportDescPtr = hidGetReportDescriptor();
|
||||||
|
TEST_ASSERT_NOT_NULL( reportDescPtr );
|
||||||
|
|
||||||
|
unsigned reportLength = hidGetReportLength();
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_REPORT_LENGTH, 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configurable and non-configurable item tests
|
||||||
|
void test_configurable_item_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 ));
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, data );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_nonconfigurable_item_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 char data[ 1 ] = { LOUDNESS_CONTROL };
|
||||||
|
const unsigned char header = construct_usage_header( sizeof data / sizeof( unsigned char ));
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, data );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit range tests
|
||||||
|
void test_max_bit_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_min_bit_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const unsigned byte = MIN_VALID_BYTE;
|
||||||
|
const unsigned char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_overflow_bit_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MAX_VALID_BIT + 1;
|
||||||
|
const unsigned byte = MIN_VALID_BYTE;
|
||||||
|
const unsigned char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_underflow_bit_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const int bit = MIN_VALID_BIT - 1;
|
||||||
|
const unsigned byte = MIN_VALID_BYTE;
|
||||||
|
const unsigned char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, ( unsigned ) bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte range tests
|
||||||
|
void test_max_byte_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const unsigned byte = MAX_VALID_BYTE;
|
||||||
|
const unsigned char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_min_byte_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const unsigned byte = MIN_VALID_BYTE;
|
||||||
|
const unsigned char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_overflow_byte_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const unsigned byte = MAX_VALID_BYTE + 1;
|
||||||
|
const unsigned char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_underflow_byte_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const int byte = MIN_VALID_BYTE - 1;
|
||||||
|
const unsigned char header = construct_usage_header( 0 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( ( unsigned ) byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_LOCATION, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size range tests
|
||||||
|
void test_max_size_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, data );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_min_size_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const unsigned byte = MIN_VALID_BYTE;
|
||||||
|
const unsigned char header = construct_usage_header( 0x00 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_unsupported_size_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const unsigned byte = MIN_VALID_BYTE;
|
||||||
|
const unsigned char header = construct_usage_header( 0x03 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Header tag and type tests
|
||||||
|
void test_bad_tag_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
const unsigned bit = MIN_VALID_BIT;
|
||||||
|
const unsigned byte = MIN_VALID_BYTE;
|
||||||
|
const unsigned char good_header = construct_usage_header( 0x00 );
|
||||||
|
|
||||||
|
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, bad_header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_global_type_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_local_type_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_main_type_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_reserved_type_hidSetReportItem( void )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, NULL );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_BAD_HEADER, retVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combined function tests
|
||||||
|
void test_initial_modification_without_subsequent_preparation( void )
|
||||||
|
{
|
||||||
|
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 ));
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, 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 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 ));
|
||||||
|
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, data );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
|
||||||
|
hidPrepareReportDescriptor();
|
||||||
|
unsigned char* reportDescPtr = hidGetReportDescriptor();
|
||||||
|
TEST_ASSERT_NOT_NULL( reportDescPtr );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_modification_without_subsequent_preparation( void )
|
||||||
|
{
|
||||||
|
hidPrepareReportDescriptor();
|
||||||
|
unsigned char* reportDescPtr = hidGetReportDescriptor();
|
||||||
|
TEST_ASSERT_NOT_NULL( reportDescPtr );
|
||||||
|
|
||||||
|
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 ));
|
||||||
|
|
||||||
|
hidResetReportDescriptor();
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, data );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
|
||||||
|
reportDescPtr = hidGetReportDescriptor();
|
||||||
|
TEST_ASSERT_NULL( reportDescPtr );
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_modification_with_subsequent_preparation( void )
|
||||||
|
{
|
||||||
|
hidPrepareReportDescriptor();
|
||||||
|
unsigned char* reportDescPtr = hidGetReportDescriptor();
|
||||||
|
TEST_ASSERT_NOT_NULL( reportDescPtr );
|
||||||
|
|
||||||
|
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 ));
|
||||||
|
|
||||||
|
hidResetReportDescriptor();
|
||||||
|
unsigned retVal = hidSetReportItem( byte, bit, header, data );
|
||||||
|
TEST_ASSERT_EQUAL_UINT( HID_STATUS_GOOD, retVal );
|
||||||
|
|
||||||
|
hidPrepareReportDescriptor();
|
||||||
|
reportDescPtr = hidGetReportDescriptor();
|
||||||
|
TEST_ASSERT_NOT_NULL( reportDescPtr );
|
||||||
|
}
|
||||||
37
tests/xua_unit_tests/src/xua_conf.h
Normal file
37
tests/xua_unit_tests/src/xua_conf.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright 2017-2021 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
|
||||||
|
#define NUM_USB_CHAN_OUT 2
|
||||||
|
#define NUM_USB_CHAN_IN 2
|
||||||
|
#define I2S_CHANS_DAC 2
|
||||||
|
#define I2S_CHANS_ADC 2
|
||||||
|
#define MCLK_441 (512 * 44100)
|
||||||
|
#define MCLK_48 (512 * 48000)
|
||||||
|
#define MIN_FREQ 48000
|
||||||
|
#define MAX_FREQ 48000
|
||||||
|
|
||||||
|
#define EXCLUDE_USB_AUDIO_MAIN
|
||||||
|
#define XUA_NUM_PDM_MICS 0
|
||||||
|
|
||||||
|
#define PDM_TILE 2
|
||||||
|
#define XUD_TILE 1
|
||||||
|
#define AUDIO_IO_TILE 1
|
||||||
|
|
||||||
|
#define MIXER 0
|
||||||
|
|
||||||
|
#define SPDIF_TX_INDEX 0
|
||||||
|
#define VENDOR_STR "XMOS"
|
||||||
|
#define VENDOR_ID 0x20B1
|
||||||
|
#define PRODUCT_STR_A2 "XMOS USB Audio Class"
|
||||||
|
#define PRODUCT_STR_A1 "XMOS USB Audio Class"
|
||||||
|
#define PID_AUDIO_1 1
|
||||||
|
#define PID_AUDIO_2 2
|
||||||
|
#define AUDIO_CLASS 2
|
||||||
|
#define AUDIO_CLASS_FALLBACK 0
|
||||||
|
#define BCD_DEVICE 0x1234
|
||||||
|
#define XUA_DFU_EN 0
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
#define XUA_DFU XUA_DFU_EN
|
||||||
|
|
||||||
|
#define FB_USE_REF_CLOCK 1
|
||||||
28
tests/xua_unit_tests/src/xua_unit_test_helper.xc
Normal file
28
tests/xua_unit_tests/src/xua_unit_test_helper.xc
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright 2021 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
#ifdef __XC__
|
||||||
|
|
||||||
|
#include <xs1.h>
|
||||||
|
#include <platform.h>
|
||||||
|
#include <xclib.h>
|
||||||
|
|
||||||
|
#endif // __XC__
|
||||||
|
|
||||||
|
|
||||||
|
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_3; /* Master clock */
|
||||||
|
|
||||||
|
// Supply missing but unused function
|
||||||
|
void AudioHwConfig(unsigned samFreq, unsigned mClk, unsigned dsdMode, unsigned sampRes_DAC, unsigned sampRes_ADC)
|
||||||
|
{
|
||||||
|
; // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supply missing but unused function
|
||||||
|
void AudioHwInit()
|
||||||
|
{
|
||||||
|
; // nothing
|
||||||
|
}
|
||||||
9
tests/xua_unit_tests/src/xua_unit_tests.h
Normal file
9
tests/xua_unit_tests/src/xua_unit_tests.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright 2021 XMOS LIMITED.
|
||||||
|
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||||
|
#ifndef XUA_UNIT_TESTS_H_
|
||||||
|
#define XUA_UNIT_TESTS_H_
|
||||||
|
|
||||||
|
#include "unity.h"
|
||||||
|
#include "xua_conf.h"
|
||||||
|
|
||||||
|
#endif /* XUA_UNIT_TESTS_H_ */
|
||||||
250
tests/xua_unit_tests/wscript
Normal file
250
tests/xua_unit_tests/wscript
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
import glob
|
||||||
|
import os.path
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from waflib import Options
|
||||||
|
from waflib.Build import BuildContext, CleanContext
|
||||||
|
|
||||||
|
TARGETS = ['xcore200', 'xcoreai']
|
||||||
|
|
||||||
|
def get_ruby():
|
||||||
|
"""
|
||||||
|
Check ruby is avaliable and return the command to invoke it.
|
||||||
|
"""
|
||||||
|
interpreter_name = 'ruby'
|
||||||
|
try:
|
||||||
|
dev_null = open(os.devnull, 'w')
|
||||||
|
# Call the version command to check the interpreter can be run
|
||||||
|
subprocess.check_call([interpreter_name, '--version'],
|
||||||
|
stdout=dev_null,
|
||||||
|
close_fds=True)
|
||||||
|
except OSError as e:
|
||||||
|
print("Failed to run Ruby interpreter: {}".format(e), file=sys.stderr)
|
||||||
|
exit(1) # TODO: Check this is the correct way to kill xwaf on error
|
||||||
|
|
||||||
|
return interpreter_name
|
||||||
|
|
||||||
|
|
||||||
|
def get_unity_runner_generator(project_root_path):
|
||||||
|
"""
|
||||||
|
Check the Unity generate_test_runner script is avaliable, and return the
|
||||||
|
path to it.
|
||||||
|
"""
|
||||||
|
unity_runner_generator = os.path.join(
|
||||||
|
project_root_path, 'Unity', 'auto', 'generate_test_runner.rb')
|
||||||
|
if not os.path.exists(unity_runner_generator):
|
||||||
|
print("Unity repo not found in workspace", file=sys.stderr)
|
||||||
|
exit(1) # TODO: Check this is the correct way to kill xwaf on error
|
||||||
|
return unity_runner_generator
|
||||||
|
|
||||||
|
|
||||||
|
def get_test_name(test_path):
|
||||||
|
"""
|
||||||
|
Return the test name by removing the extension from the filename.
|
||||||
|
"""
|
||||||
|
return os.path.splitext(os.path.basename(test_path))[0]
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_type(filename):
|
||||||
|
"""
|
||||||
|
Return the extension from the filename.
|
||||||
|
"""
|
||||||
|
return filename.rsplit('.')[-1:][0]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_unity_runner(project_root_path, unity_test_path, unity_runner_dir,
|
||||||
|
unity_runner_suffix):
|
||||||
|
"""
|
||||||
|
Invoke the Unity runner generation script for the given test file, and
|
||||||
|
return the path to the generated file. The output directory will be created
|
||||||
|
if it does not already exist.
|
||||||
|
"""
|
||||||
|
runner_path = os.path.join(os.path.join(unity_runner_dir, get_test_name(unity_test_path)))
|
||||||
|
if not os.path.exists(runner_path):
|
||||||
|
os.makedirs(runner_path)
|
||||||
|
|
||||||
|
unity_runner_path = os.path.join(
|
||||||
|
runner_path, get_test_name(unity_test_path) + unity_runner_suffix
|
||||||
|
+ '.' + 'c')
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.check_call([get_ruby(),
|
||||||
|
get_unity_runner_generator(project_root_path),
|
||||||
|
unity_test_path,
|
||||||
|
unity_runner_path])
|
||||||
|
except OSError as e:
|
||||||
|
print("Ruby generator failed for {}\n\t{}".format(unity_test_path, e),
|
||||||
|
file=sys.stderr)
|
||||||
|
exit(1) # TODO: Check this is the correct way to kill xwaf on error
|
||||||
|
|
||||||
|
|
||||||
|
def add_unity_runner_build_config(waf_conf, project_root_path, unity_test_path,
|
||||||
|
unity_runner_build_flags, target):
|
||||||
|
"""
|
||||||
|
Add a config to xwaf to build each Unity test runner into an xCORE
|
||||||
|
executable.
|
||||||
|
"""
|
||||||
|
print(f"get_test_name(unity_test_path) = {get_test_name(unity_test_path)}. target = {target}")
|
||||||
|
waf_conf.setenv(get_test_name(unity_test_path) + '_' + target)
|
||||||
|
waf_conf.load('xwaf.compiler_xcc')
|
||||||
|
waf_conf.env.XCC_FLAGS = unity_runner_build_flags
|
||||||
|
waf_conf.env.PROJECT_ROOT = project_root_path
|
||||||
|
# TODO: can the xwaf boilerplate help here?
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_unity_test_for_build(waf_conf, project_root_path, unity_test_path,
|
||||||
|
unity_runner_dir, unity_runner_suffix, target):
|
||||||
|
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
|
||||||
|
add_unity_runner_build_config(waf_conf, project_root_path, unity_test_path,
|
||||||
|
runner_build_flags, target)
|
||||||
|
|
||||||
|
|
||||||
|
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+'*'))
|
||||||
|
|
||||||
|
|
||||||
|
def find_unity_tests(unity_test_dir, unity_test_prefix):
|
||||||
|
"""
|
||||||
|
Return a dictionary of all {test names, test language} pairs with the
|
||||||
|
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)
|
||||||
|
for path in unity_test_paths}
|
||||||
|
|
||||||
|
|
||||||
|
def generate_all_unity_runners(waf_conf, project_root_path,
|
||||||
|
unity_test_dir, unity_test_prefix,
|
||||||
|
unity_runner_dir, unity_runner_suffix):
|
||||||
|
"""
|
||||||
|
Generate a runner and a build config for each test file in the
|
||||||
|
unity_test_dir.
|
||||||
|
"""
|
||||||
|
# FIXME: pass unity_tests in?
|
||||||
|
unity_test_paths = find_unity_test_paths(unity_test_dir, unity_test_prefix)
|
||||||
|
for trgt in TARGETS:
|
||||||
|
for unity_test_path in unity_test_paths:
|
||||||
|
prepare_unity_test_for_build(waf_conf, project_root_path,
|
||||||
|
unity_test_path,
|
||||||
|
unity_runner_dir, unity_runner_suffix, trgt)
|
||||||
|
|
||||||
|
|
||||||
|
# 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 ctx in (BuildContext, CleanContext):
|
||||||
|
raw_context = ctx.__name__.replace('Context', '').lower()
|
||||||
|
|
||||||
|
class tmp(ctx):
|
||||||
|
cmd = raw_context + '_' + test_name + '_' + trgt
|
||||||
|
variant = test_name + '_' + trgt
|
||||||
|
#cmd = raw_context + '_' + test_name
|
||||||
|
#variant = test_name
|
||||||
|
language = test_language
|
||||||
|
target = trgt
|
||||||
|
runner = test_name
|
||||||
|
print(f"cmd {cmd}, variant {variant}, language {language}")
|
||||||
|
|
||||||
|
|
||||||
|
UNITY_TEST_DIR = 'src'
|
||||||
|
UNITY_TEST_PREFIX = 'test_'
|
||||||
|
UNITY_RUNNER_DIR = 'runners'
|
||||||
|
UNITY_RUNNER_SUFFIX = '_Runner'
|
||||||
|
UNITY_TESTS = find_unity_tests(UNITY_TEST_DIR, UNITY_TEST_PREFIX)
|
||||||
|
|
||||||
|
create_waf_contexts(UNITY_TESTS)
|
||||||
|
|
||||||
|
def options(opt):
|
||||||
|
opt.add_option('--target', action='store', default='xcore200')
|
||||||
|
opt.load('xwaf.xcommon')
|
||||||
|
|
||||||
|
def configure(conf):
|
||||||
|
# TODO: move the call to generate_all_unity_runners() to build()
|
||||||
|
project_root = os.path.join('..', '..', '..')
|
||||||
|
generate_all_unity_runners(conf, project_root,
|
||||||
|
UNITY_TEST_DIR, UNITY_TEST_PREFIX,
|
||||||
|
UNITY_RUNNER_DIR, UNITY_RUNNER_SUFFIX)
|
||||||
|
conf.load('xwaf.xcommon')
|
||||||
|
|
||||||
|
|
||||||
|
def build(bld):
|
||||||
|
if not bld.variant:
|
||||||
|
print('Adding test runners to build queue')
|
||||||
|
trgt = [
|
||||||
|
c for c in TARGETS if c == bld.options.target
|
||||||
|
]
|
||||||
|
|
||||||
|
if len(trgt) == 0:
|
||||||
|
bld.fatal('specify a target with --target.\nAvailable targets: {}'.format(', '.join(TARGETS)))
|
||||||
|
return
|
||||||
|
|
||||||
|
for name in UNITY_TESTS:
|
||||||
|
Options.commands.insert(0, 'build_' + name + '_' + trgt[0])
|
||||||
|
#Options.commands.insert(0, 'build_' + name)
|
||||||
|
print('Build queue {}'.format(Options.commands))
|
||||||
|
else:
|
||||||
|
print('Building runner {}'.format(bld.runner))
|
||||||
|
bld.env.XSCOPE = bld.path.find_resource('config.xscope')
|
||||||
|
|
||||||
|
depends_on = ['lib_xua',
|
||||||
|
'lib_xud',
|
||||||
|
'lib_spdif',
|
||||||
|
'lib_mic_array',
|
||||||
|
'lib_logging',
|
||||||
|
'lib_xassert',
|
||||||
|
'Unity']
|
||||||
|
|
||||||
|
makefile_opts = {}
|
||||||
|
makefile_opts['SOURCE_DIRS'] = ['src', os.path.join('runners',bld.runner)]
|
||||||
|
if(bld.target == 'xcoreai'):
|
||||||
|
print('TARGET XCOREAI')
|
||||||
|
makefile_opts['TARGET'] = ['XCORE-AI-EXPLORER']
|
||||||
|
else:
|
||||||
|
print('TARGET XCORE200')
|
||||||
|
makefile_opts['TARGET'] = ['XCORE-200-EXPLORER']
|
||||||
|
|
||||||
|
makefile_opts['INCLUDE_DIRS'] = ['src',
|
||||||
|
'../../lib_xua/api',
|
||||||
|
'../../lib_xua/src/core/pdm_mics',
|
||||||
|
'../../lib_xua/src/hid',
|
||||||
|
'../../../lib_xud/lib_xud/src/user/class']
|
||||||
|
|
||||||
|
makefile_opts['XCC_FLAGS'] = ['-O2',
|
||||||
|
'-g',
|
||||||
|
'-Wall',
|
||||||
|
'-DUNITY_SUPPORT_64',
|
||||||
|
'-DUNITY_INCLUDE_DOUBLE',
|
||||||
|
'-DXUD_CORE_CLOCK=600',
|
||||||
|
'-DXUD_SERIES_SUPPORT=4']
|
||||||
|
|
||||||
|
makefile_opts['APP_NAME'] = [bld.variant]
|
||||||
|
makefile_opts['USED_MODULES'] = depends_on
|
||||||
|
makefile_opts['XCOMMON_MAKEFILE'] = ['Makefile.common']
|
||||||
|
bld.do_xcommon(makefile_opts)
|
||||||
|
|
||||||
|
|
||||||
|
def test(bld):
|
||||||
|
# Call pytest to run Unity tests inside axe or xsim
|
||||||
|
try:
|
||||||
|
test_output = subprocess.check_output(['pytest'])
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
# pytest exits non-zero if an assertion fails
|
||||||
|
test_output = e.output
|
||||||
|
print(test_output)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: ensure clean deletes the runners dir/
|
||||||
|
def dist(ctx):
|
||||||
|
ctx.load('xwaf.xcommon')
|
||||||
|
|
||||||
|
def distcheck(ctx):
|
||||||
|
ctx.load('xwaf.xcommon')
|
||||||
Reference in New Issue
Block a user