Merge pull request #103 from mbanth/feature/pendragon

Feature/pendragon
This commit is contained in:
Michael Banther
2019-11-15 12:30:22 +00:00
committed by GitHub
17 changed files with 979 additions and 633 deletions

1
.gitignore vendored
View File

@@ -27,3 +27,4 @@ _build*
build/
.build*
*.pyc
xscope.xmt

View File

@@ -1,6 +1,13 @@
lib_xua Change Log
==================
0.3.0
-----
* ADDED: UAC1 HID support with simulated Voice Command detection reported
every 10 seconds
* ADDED: Support for USB HID Set Idle request
0.2.1
-----

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2011-2018, XMOS Ltd, All rights reserved
// Copyright (c) 2011-2019, XMOS Ltd, All rights reserved
#ifndef __XUA_BUFFER_H__
#define __XUA_BUFFER_H__
@@ -58,7 +58,7 @@ void XUA_Buffer(
chanend c_sof,
chanend c_aud_ctl,
in port p_off_mclk
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
, chanend c_hid
#endif
, chanend c_aud
@@ -97,7 +97,7 @@ void XUA_Buffer_Ep(chanend c_aud_out,
chanend c_sof,
chanend c_aud_ctl,
in port p_off_mclk
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
, chanend c_hid
#endif
#ifdef CHAN_BUFF_CTRL

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2011-2018, XMOS Ltd, All rights reserved
// Copyright (c) 2011-2019, XMOS Ltd, All rights reserved
/*
* @brief Defines relating to device configuration and customisation of lib_xua
* @author Ross Owen, XMOS Limited
@@ -425,10 +425,6 @@
#define HID_CONTROLS (0)
#endif
#if defined(HID_CONTROLS) && (HID_CONTROLS == 0)
#undef HID_CONTROLS
#endif
/* @brief Defines whether XMOS device runs as master (i.e. drives LR and Bit clocks)
*
* 0: XMOS is I2S master. 1: CODEC is I2s master.
@@ -1158,6 +1154,10 @@
#endif
#if (defined(UAC_FORCE_FEEDBACK_EP) && UAC_FORCE_FEEDBACK_EP == 0)
#undef UAC_FORCE_FEEDBACK_EP
#endif
#ifndef __ASSEMBLER__
/* Endpoint addresses enums */
enum USBEndpointNumber_In
@@ -1173,7 +1173,7 @@ enum USBEndpointNumber_In
#ifdef MIDI
ENDPOINT_NUMBER_IN_MIDI,
#endif
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
ENDPOINT_NUMBER_IN_HID,
#endif
#ifdef IAP

View File

@@ -1,4 +1,4 @@
VERSION = 0.2.1
VERSION = 0.3.0
DEPENDENT_MODULES = lib_logging(>=3.0.0) \
lib_xassert(>=4.0.0) \
@@ -43,6 +43,7 @@ INCLUDE_DIRS = $(EXPORT_INCLUDE_DIRS) \
src/core/support/powersave \
src/core/user \
src/core/user/audiostream \
src/core/user/hid \
src/core/user/hostactive \
src/midi
@@ -61,6 +62,7 @@ SOURCE_DIRS = src/core \
src/core/user/hostactive \
src/core/xuduser \
src/dfu \
src/hid \
src/midi
EXCLUDE_FILES += descriptors_2.rst

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2011-2018, XMOS Ltd, All rights reserved
// Copyright (c) 2011-2019, XMOS Ltd, All rights reserved
#include "xua.h"
#if XUA_USB_EN
@@ -12,7 +12,7 @@
#include "usbaudio20.h" /* Defines from the USB Audio 2.0 Specifications */
#endif
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
#include "user_hid.h"
#endif
#define MAX(x,y) ((x)>(y) ? (x) : (y))

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2011-2018, XMOS Ltd, All rights reserved
// Copyright (c) 2011-2019, XMOS Ltd, All rights reserved
#include "xua.h"
#if XUA_USB_EN
#include <xs1.h>
@@ -19,7 +19,7 @@
#include "xud.h"
#include "testct_byref.h"
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
#include "user_hid.h"
unsigned char g_hidData[1] = {0};
#endif
@@ -120,7 +120,7 @@ void XUA_Buffer(
chanend c_sof,
chanend c_aud_ctl,
in port p_off_mclk
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
, chanend c_hid
#endif
, chanend c_aud
@@ -164,7 +164,7 @@ void XUA_Buffer(
c_clk_int,
#endif
c_sof, c_aud_ctl, p_off_mclk
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
, c_hid
#endif
#ifdef CHAN_BUFF_CTRL
@@ -223,7 +223,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
chanend c_sof,
chanend c_aud_ctl,
in port p_off_mclk
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
, chanend c_hid
#endif
#ifdef CHAN_BUFF_CTRL
@@ -260,7 +260,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
XUD_ep ep_int = XUD_InitEp(c_ep_int);
#endif
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
XUD_ep ep_hid = XUD_InitEp(c_hid);
#endif
unsigned u_tmp;
@@ -364,7 +364,7 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#endif
#endif
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
XUD_SetReady_In(ep_hid, g_hidData, 1);
#endif
@@ -875,12 +875,12 @@ void XUA_Buffer_Ep(register chanend c_aud_out,
#endif
#endif
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
/* HID Report Data */
case XUD_SetData_Select(c_hid, ep_hid, result):
{
g_hidData[0]=0;
UserReadHIDButtons(g_hidData);
UserReadHIDData(g_hidData);
XUD_SetReady_In(ep_hid, g_hidData, 1);
}
break;

View File

@@ -1,8 +1,13 @@
// Copyright (c) 2015-2018, XMOS Ltd, All rights reserved
// Copyright (c) 2015-2019, XMOS Ltd, All rights reserved
#ifndef __DESCRIPTOR_DEFS_H__
#define __DESCRIPTOR_DEFS_H__
/*
Include xua.h to pick up the #defines of NUM_USB_CHAN_IN and NUM_USB_CHAN_OUT.
*/
#include "xua.h"
#if (NUM_USB_CHAN_IN > 0) && (NUM_USB_CHAN_OUT > 0)
#define AUDIO_INTERFACE_COUNT 3
#elif (NUM_USB_CHAN_IN > 0) || (NUM_USB_CHAN_OUT > 0)
@@ -54,10 +59,14 @@ enum USBInterfaceNumber
INTERFACE_NUMBER_IAP_EA_NATIVE_TRANS,
#endif
#endif
#if defined(HID_CONTROLS) && (HID_CONTROLS != 0)
#if( 0 < HID_CONTROLS )
INTERFACE_NUMBER_HID,
#endif
INTERFACE_COUNT /* End marker */
};
#if( 0 < HID_CONTROLS )
#define ENDPOINT_INT_INTERVAL_IN_HID 0x08
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -561,27 +561,24 @@ unsigned char devQualDesc_Null[] =
#define MIXER_LENGTH (0)
#endif
#ifdef HID_CONTROLS
unsigned char hidReportDescriptor[] =
#if( 0 < HID_CONTROLS )
unsigned char hidReportDescriptor[] = /* Voice Command usage as per request #HUTRR45 */
{
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 */
0x15, 0x01, /* Logical Minimum (1) */
0x25, 0x01, /* Logical Maximum (1) */
0x75, 0x01, /* Report Size (1) */
0x05, 0x0c, /* Usage Page (Consumer Device) */
0x09, 0x01, /* Usage (Consumer Control) */
0xa1, 0x01, /* Collection (Application) */
0x0a, 0x00, 0x02, /* Usage (Generic GUI Application Controls) */
0xa1, 0x02, /* Collection (Logical) */
0x0a, 0x21, 0x02, /* Usage (AC Search) */
0x95, 0x01, /* Report Count (1) */
0x81, 0x40, /* Input (Data, Ary, Abs, Nul) */
0x95, 0x07, /* Report Count (7) */
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
0xc0, /* End collection (Logical) */
0xc0 /* End collection (Application) */
};
#endif
@@ -784,7 +781,7 @@ typedef struct
#endif
#endif
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
USB_Descriptor_Interface_t HID_Interface;
unsigned char hidDesc[9]; //TODO ideally we would have a struct for this.
USB_Descriptor_Endpoint_t HID_In_Endpoint;
@@ -1099,7 +1096,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
},
0, /* 60 iFeature */
},
#endif
#endif /* (OUTPUT_VOLUME_CONTROL == 1) */
/* Output Terminal Descriptor (Audio) */
.Audio_Out_OutputTerminal =
@@ -1119,7 +1116,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
0x0000, /* 9 bmControls */
0, /* 11 iTerminal */
},
#endif
#endif /* (NUM_USB_CHAN_OUT > 0) */
@@ -1274,7 +1271,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
},
0, /* 60 iFeature */
},
#endif
#endif /* (INPUT_VOLUME_CONTROL == 1) */
.Audio_In_OutputTerminal =
{
@@ -1295,7 +1292,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
.bmControls = 0x0000,
.iTerminal = offsetof(StringDescTable_t, usbOutputTermStr_Audio2)/sizeof(char *)
},
#endif
#endif /* (NUM_USB_CHAN_IN > 0) */
#if defined(MIXER) && (MAX_MIX_COUNT > 0)
/* Extension Unit Descriptor (4.7.2.12) */
@@ -1389,7 +1386,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
0x00, /* bmControls */
0 /* Mixer unit string descriptor index */
},
#endif
#endif /* defined(MIXER) && (MAX_MIX_COUNT > 0) */
#if (SPDIF_RX) || (ADAT_RX)
/* Standard AS Interrupt Endpoint Descriptor (4.8.2.1): */
@@ -1586,7 +1583,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
4, /* 6 bInterval. Only values <= 1 frame (4) supported by MS */
},
#endif
#endif
#endif /* OUTPUT_FORMAT_COUNT > 1 */
#if (OUTPUT_FORMAT_COUNT > 2)
/* Standard AS Interface Descriptor (4.9.1) (Alt) */
.Audio_Out_StreamInterface_Alt3 =
@@ -1831,7 +1828,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
.bLockDelayUnits = 0x02,
.wLockDelay = 0x0008,
},
#endif
#endif /* (INPUT_FORMAT_COUNT > 1) */
#if (INPUT_FORMAT_COUNT > 2)
/* Alternative 3 */
/* Standard AS Interface Descriptor (4.9.1) (Alt) */
@@ -1904,7 +1901,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
.bLockDelayUnits = 0x02,
.wLockDelay = 0x0008,
},
#endif
#endif /* (INPUT_FORMAT_COUNT > 2) */
#endif /* #if(NUM_USB_CHAN_IN > 0) */
#ifdef MIDI
@@ -2060,7 +2057,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
0x10, /* 7 bcdDFUVersion */
0x01}, /* 7 bcdDFUVersion */
#endif
#endif
#endif /* (XUA_DFU_EN == 1) */
#ifdef IAP
/* Interface descriptor */
@@ -2169,7 +2166,7 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
#endif
#endif /* IAP */
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
.HID_Interface =
{
9, /* 0 bLength : Size of descriptor in Bytes */
@@ -2203,22 +2200,22 @@ USB_Config_Descriptor_Audio2_t cfgDesc_Audio2=
ENDPOINT_ADDRESS_IN_HID, /* 2 bEndpointAddress */
3, /* 3 bmAttributes (INTERRUPT) */
64, /* 4 wMaxPacketSize */
8, /* 6 bInterval */
ENDPOINT_INT_INTERVAL_IN_HID, /* 6 bInterval */
}
#endif
};
#endif
#endif /* (AUDIO_CLASS == 2) */
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
unsigned char hidDescriptor[] =
{
9, /* 0 bLength : Size of descriptor in Bytes */
0x09, /* 0 bLength : Size of descriptor in Bytes */
0x21, /* 1 bDescriptorType (HID) */
0x10, /* 2 bcdHID */
0x01, /* 3 bcdHID */
0, /* 4 bCountryCode */
1, /* 5 bNumDescriptors */
0x00, /* 4 bCountryCode */
0x01, /* 5 bNumDescriptors */
0x22, /* 6 bDescriptorType[0] (Report) */
sizeof(hidReportDescriptor) & 0xff, /* 7 wDescriptorLength[0] */
sizeof(hidReportDescriptor) >> 8, /* 8 wDescriptorLength[0] */
@@ -2325,18 +2322,13 @@ const unsigned num_freqs_a1 = MAX(3, (0
#define DFU_INTERFACES_A1 0
#endif
/* Total number of bytes returned for the class-specific AudioControl interface descriptor.
* Includes the combined length of this descriptor header and all Unit and Terminal descriptors
* For us this is IT -> FU -> OT * 2 and a header */
#define AC_TOTAL_LENGTH (AC_LENGTH + \
(INPUT_INTERFACES_A1 * (12 + ( (8 + NUM_USB_CHAN_IN_FS) * INPUT_VOLUME_CONTROL) + 9)) +\
(OUTPUT_INTERFACES_A1 * (12 + ( (8 + NUM_USB_CHAN_OUT_FS) * OUTPUT_VOLUME_CONTROL) + 9)))
#define STREAMING_INTERFACES (INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1)
//#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
//#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (58 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES)
//#endif
#if( 0 < HID_CONTROLS )
#define HID_INTERFACE_BYTES ( 9 + 9 + 7 )
#define HID_INTERFACES_A1 1
#else
#define HID_INTERFACE_BYTES 0
#define HID_INTERFACES_A1 0
#endif
/* Total number of bytes returned for the class-specific AudioControl interface descriptor.
* Includes the combined length of this descriptor header and all Unit and Terminal descriptors
@@ -2349,12 +2341,12 @@ const unsigned num_freqs_a1 = MAX(3, (0
/* Number of interfaces for Audio 1.0 (+1 for control ) */
/* Note, this is different that INTERFACE_COUNT since we dont support items such as MIDI, iAP etc in UAC1 mode */
#define NUM_INTERFACES_A1 (1+INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1+NUM_CONTROL_USB_INTERFACES+DFU_INTERFACES_A1)
#define NUM_INTERFACES_A1 (1 + INPUT_INTERFACES_A1 + OUTPUT_INTERFACES_A1 + NUM_CONTROL_USB_INTERFACES + DFU_INTERFACES_A1 + HID_INTERFACES_A1)
#if (NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP)
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (58 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES)
#define CFG_TOTAL_LENGTH_A1 (18 + AC_TOTAL_LENGTH + (INPUT_INTERFACES_A1 * (49 + num_freqs_a1 * 3)) + (OUTPUT_INTERFACES_A1 * (58 + num_freqs_a1 * 3)) + CONTROL_INTERFACE_BYTES + DFU_INTERFACE_BYTES + HID_INTERFACE_BYTES)
#else
#define CFG_TOTAL_LENGTH_A1 (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)
#define CFG_TOTAL_LENGTH_A1 (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 + HID_INTERFACE_BYTES)
#endif
#define CHARIFY_SR(x) (x & 0xff),((x & 0xff00)>> 8),((x & 0xff0000)>> 16)
@@ -2856,6 +2848,39 @@ unsigned char cfgDesc_Audio1[] =
offsetof(StringDescTable_t, ctrlStr)/sizeof(char *), /* 8 iInterface */
#endif
#if( 0 < HID_CONTROLS )
/* HID interface descriptor */
0x09, /* 0 bLength : Size of descriptor in Bytes */
0x04, /* 1 bDescriptorType (Interface: 0x04)*/
INTERFACE_NUMBER_HID, /* 2 bInterfaceNumber : Number of interface */
0x00, /* 3 bAlternateSetting : Value used alternate interfaces using SetInterface Request */
0x01, /* 4: bNumEndpoints : Number of endpoitns for this interface (excluding 0) */
0x03, /* 5: bInterfaceClass */
0x00, /* 6: bInterfaceSubClass - no boot device */
0x00, /* 7: bInterfaceProtocol*/
0x00, /* 8 iInterface */
/* HID descriptor */
0x09, /* 0 bLength : Size of descriptor in Bytes */
0x21, /* 1 bDescriptorType (HID) */
0x10, /* 2 bcdHID */
0x01, /* 3 bcdHID */
0x00, /* 4 bCountryCode */
0x01, /* 5 bNumDescriptors */
0x22, /* 6 bDescriptorType[0] (Report) */
0x1E, /* 7 wDescriptorLength[0] */
0x00, /* 8 wDescriptorLength[0] */
/* HID Endpoint descriptor (IN) */
0x07, /* 0 bLength */
0x05, /* 1 bDescriptorType */
ENDPOINT_ADDRESS_IN_HID, /* 2 bEndpointAddress */
0x03, /* 3 bmAttributes (INTERRUPT) */
0x40, /* 4 wMaxPacketSize */
0x00, /* 5 wMaxPacketSize */
ENDPOINT_INT_INTERVAL_IN_HID, /* 6 bInterval */
#endif
};
#endif
#endif

View File

@@ -5,13 +5,13 @@
#include <xccompat.h>
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, REFERENCE_PARAM(USB_SetupPacket_t, sp), chanend c_audioControl,
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, REFERENCE_PARAM(USB_SetupPacket_t, sp), NULLABLE_RESOURCE(chanend, c_audioControl),
NULLABLE_RESOURCE(chanend, c_mix_ctl), NULLABLE_RESOURCE(chanend, c_clk_ctl));
XUD_Result_t AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, REFERENCE_PARAM(USB_SetupPacket_t, sp), chanend c_audioControl,
XUD_Result_t AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, REFERENCE_PARAM(USB_SetupPacket_t, sp), NULLABLE_RESOURCE(chanend, c_audioControl),
NULLABLE_RESOURCE(chanend, c_mix_ctl), NULLABLE_RESOURCE(chanend, c_clk_ctl));
int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, REFERENCE_PARAM(USB_SetupPacket_t, sp), chanend c_audioControl,
int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, REFERENCE_PARAM(USB_SetupPacket_t, sp), NULLABLE_RESOURCE(chanend, c_audioControl),
NULLABLE_RESOURCE(chanend, c_mix_ctl), NULLABLE_RESOURCE(chanend, c_clk_ctl));

View File

@@ -273,7 +273,7 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl)
* XUD_RES_RST for device reset
* else XUD_RES_ERR
*/
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend ?c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
)
{
unsigned int buffer[32];
@@ -1071,7 +1071,7 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c
#if (AUDIO_CLASS_FALLBACK != 0) || (AUDIO_CLASS == 1)
int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl)
int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend ?c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl)
{
/* At this point we know:
* bmRequestType.Recipient = Endpoint
@@ -1159,7 +1159,7 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp
/* Handles the Audio Class 1.0 specific requests */
XUD_Result_t AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
XUD_Result_t AudioClassRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend ?c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl
)
{
#if (OUTPUT_VOLUME_CONTROL == 1) || (INPUT_VOLUME_CONTROL == 1)

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2012-2018, XMOS Ltd, All rights reserved
// Copyright (c) 2012-2019, XMOS Ltd, All rights reserved
#include "xua.h" /* Device specific defines */
#ifndef EXCLUDE_USB_AUDIO_MAIN
@@ -259,7 +259,7 @@ XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENAB
#ifdef MIDI
XUD_EPTYPE_BUL,
#endif
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
XUD_EPTYPE_INT,
#endif
#ifdef IAP
@@ -400,7 +400,7 @@ VENDOR_REQUESTS_PARAMS_DEC_
c_clk_int,
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#ifdef HID_CONTROLS
#if( 0 < HID_CONTROLS )
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
#ifdef CHAN_BUFF_CTRL

View File

@@ -0,0 +1,19 @@
// Copyright (c) 2013-2019, XMOS Ltd, All rights reserved
/* These defines relate to the HID report desc - do not mod */
#define HID_CONTROL_PLAYPAUSE_SHIFT 0x00
#define HID_CONTROL_NEXT_SHIFT 0x01
#define HID_CONTROL_PREV_SHIFT 0x02
#define HID_CONTROL_VOLUP_SHIFT 0x03
#define HID_CONTROL_VOLDN_SHIFT 0x04
#define HID_CONTROL_MUTE_SHIFT 0x05
#define HID_DATA_SIZE 1
#if( 0 < HID_CONTROLS )
void UserInitHIDData( void );
void UserReadHIDData( unsigned char hidData[ HID_DATA_SIZE ]);
void UserSetHIDData( const unsigned hidData );
#endif /* ( 0 < HID_CONTROLS ) */

View File

@@ -1,13 +0,0 @@
// Copyright (c) 2013-2018, XMOS Ltd, All rights reserved
/* These defines relate to the HID report desc - do not mod */
#define HID_CONTROL_PLAYPAUSE_SHIFT 0x00
#define HID_CONTROL_NEXT_SHIFT 0x01
#define HID_CONTROL_PREV_SHIFT 0x02
#define HID_CONTROL_VOLUP_SHIFT 0x03
#define HID_CONTROL_VOLDN_SHIFT 0x04
#define HID_CONTROL_MUTE_SHIFT 0x05
void UserReadHIDButtons(unsigned char hidData[]);

222
lib_xua/src/hid/hid.xc Normal file
View File

@@ -0,0 +1,222 @@
// Copyright (c) 2019, XMOS Ltd, All rights reserved
#include <xs1.h>
#include "descriptor_defs.h"
#include "hid.h"
#include "xud.h"
#include "xud_std_requests.h"
#include "xua_hid.h"
#if( 0 < HID_CONTROLS )
#define MS_IN_TICKS 100000U
static unsigned s_hidIdleActive = 0U;
static unsigned s_hidCurrentPeriod = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
static unsigned s_hidIndefiniteDuration = 0U;
static unsigned s_hidNextReportTime = 0U;
static unsigned s_hidReportTime = 0U;
static unsigned HidCalcNewReportTime( const unsigned currentPeriod, const unsigned reportTime, const unsigned reportToSetIdleInterval, const unsigned newPeriod );
static unsigned HidCalcReportToSetIdleInterval( const unsigned reportTime );
static unsigned HidFindSetIdleActivationPoint( const unsigned currentPeriod, const unsigned timeWithinPeriod );
static XUD_Result_t HidProcessSetIdleRequest( XUD_ep c_ep0_out, XUD_ep c_ep0_in, USB_SetupPacket_t &sp );
static unsigned HidTimeDiff( const unsigned earlierTime, const unsigned laterTime );
void HidCalcNextReportTime( void )
{
s_hidNextReportTime = s_hidReportTime + s_hidCurrentPeriod;
}
void HidCaptureReportTime( void )
{
timer tmr;
tmr :> s_hidReportTime;
}
XUD_Result_t HidInterfaceClassRequests(
XUD_ep c_ep0_out,
XUD_ep c_ep0_in,
USB_SetupPacket_t &sp )
{
XUD_Result_t result = XUD_RES_ERR;
switch ( sp.bRequest ) {
case HID_SET_IDLE:
result = HidProcessSetIdleRequest( c_ep0_out, c_ep0_in, sp );
break;
default:
break;
}
return result;
}
unsigned HidIsSetIdleSilenced( void )
{
unsigned isSilenced = s_hidIdleActive;
if( s_hidIdleActive ) {
unsigned currentTime;
asm volatile( "gettime %0" : "=r" ( currentTime )); // Use inline assembly to access the time without creating a side-effect
isSilenced = ( s_hidIndefiniteDuration || ( timeafter( s_hidNextReportTime, currentTime )));
}
return isSilenced;
}
/**
* \brief Calculate the timer value for sending the next HID Report.
*
* With regard to Section 7.2.4 Set_Idle Request of the USB Device Class Definition for Human
* Interface Devices (HID) Version 1.11, I've interpreted 'currently executing period' and
* 'current period' to mean the previously established Set Idle duration if one has been
* established or the polling interval from the HID Report Descriptor if a Set Idle duration
* has not been established.
*
* \param[in] currentPeriod -- The duration of the current period in timer ticks
* \param[in] reportTime -- The time at which the last HID Report was sent
* \param[in] reportToSetIdleInterval -- The time interval between receiving the Set Idle Request
* and sending the most recent HID Report
* \param[in] newPeriod -- The new period value in timer ticks
*
* \return The time at which the next HID Report should be sent
*/
static unsigned HidCalcNewReportTime( const unsigned currentPeriod, const unsigned reportTime, const unsigned reportToSetIdleInterval, const unsigned newPeriod )
{
unsigned nextReportTime = 0;
if( HidFindSetIdleActivationPoint( currentPeriod, reportToSetIdleInterval )) {
/* Activate immediately after sending the next HID Report */
nextReportTime = reportTime + currentPeriod;
} else {
/* Activate immediately after sending the most recent HID Report */
nextReportTime = reportTime + newPeriod;
}
return nextReportTime;
}
/**
* \brief Calculate the time interval between the most recent HID Report and a subsequent Set Idle Request
*
* \warning For this function to produce an accurate interval measument, it must be called without delay
* upon receiving a Set Idle Request from the USB Host.
*
* \param[in] reportTime -- The time at which the last HID Report was sent
*
* \return The time interval between receiving the Set Idle Request and sending the most recent HID Report
*/
static unsigned HidCalcReportToSetIdleInterval( const unsigned reportTime )
{
timer tmr;
unsigned setIdleTime;
tmr :> setIdleTime;
unsigned result = HidTimeDiff( reportTime, setIdleTime );
return result;
}
/**
* \brief Indicate if activation of the Set Idle Request happens at the previous or next HID Report
*
* Section 7.2.4 Set_Idle Request of the USB Device Class Definition for Human Interface
* Devices (HID) Version 1.11 makes two statements about the activation point for starting the
* duration of the request:
* - 'A new request will be executed as if it were issued immediately after the last report, if
* the new request is received at least 4 milliseconds before the end of the currently executing
* period.'
* - 'If the new request is received within 4 milliseconds of the end of the current period, then
* the new request will have no effect until after the report.'
*
* \param[in] currentPeriod -- The duration of the current period
* \param[in] timeWithinPeriod -- The current point in time relative to the current period
*
* \return A Boolean indicating where the activation of the Set Idle Request Duration occurs.
* \retval 1 -- Activate immediately after the next HID Report
* \retval 0 -- Activate immediately after the previous HID Report
*/
static unsigned HidFindSetIdleActivationPoint( const unsigned currentPeriod, const unsigned timeWithinPeriod )
{
unsigned result = (( currentPeriod - timeWithinPeriod ) < ( 4U * MS_IN_TICKS )) ? 1 : 0;
return result;
}
/**
* \brief Process a Set Idle request
*
* \param[in] c_ep0_out -- the channel that carries data from Endpoint 0
* \param[in] c_ep0_in -- the channel that carries data for Endpoint 0
* \param[in] sp -- a structure containing the Set Idle data
*
* \return An XUD status value
*/
static XUD_Result_t HidProcessSetIdleRequest( XUD_ep c_ep0_out, XUD_ep c_ep0_in, USB_SetupPacket_t &sp )
{
XUD_Result_t result = XUD_RES_ERR;
/*
The Set Idle request wValue field contains two sub-fields:
- Duration in the MSB; and
- Report ID in the LSB.
The Duration field specifies how long the USB Device responds with NAK provided the HID data hasn't changed.
Zero means indefinitely.
The value is in units of 4ms.
The Report ID identifies the HID report that the USB Host wishes to silence.
The Set Idle request xIndex field contains the interface number.
*/
uint16_t duration = ( sp.wValue & 0xFF00 ) >> 6; // Transform from units of 4ms into units of 1ms.
uint8_t reportId = sp.wValue & 0x00FF;
uint16_t interfaceNum = sp.wIndex;
/*
As long as our HID Report Descriptor does not include a Report ID, any Report ID value other than zero
indicates an error by the USB Host (see xua_ep0_descriptors.h for the definition of the HID
Report Descriptor).
Any Interface value other than INTERFACE_NUMBER_HID indicates an error by the USB Host.
*/
if(( 0U == reportId ) && ( INTERFACE_NUMBER_HID == interfaceNum )) {
s_hidIdleActive = (( 0U == duration ) || ( ENDPOINT_INT_INTERVAL_IN_HID < duration ));
if( s_hidIdleActive ) {
unsigned reportToSetIdleInterval = HidCalcReportToSetIdleInterval( s_hidReportTime );
s_hidNextReportTime = HidCalcNewReportTime( s_hidCurrentPeriod, s_hidReportTime, reportToSetIdleInterval, duration * MS_IN_TICKS );
s_hidCurrentPeriod = duration * MS_IN_TICKS;
s_hidIndefiniteDuration = ( 0U == duration );
} else {
s_hidCurrentPeriod = ENDPOINT_INT_INTERVAL_IN_HID * MS_IN_TICKS;
s_hidIndefiniteDuration = 0U;
}
result = XUD_DoSetRequestStatus( c_ep0_in );
}
return result;
}
/**
* \brief Calculate the difference between two points in time
*
* This function calculates the difference between two two points in time.
* It always returns a positive value even if the timer used to obtain the two
* time measurements has wrapped around.
*
* \warning If time values have been obtained from a timer that has wrapped
* more than once in between the two measurements, this function returns an
* incorrect value.
*
* \param[in] earlierTime -- A value from a timer
* \param[in] laterTime -- A value from a timer taken after \a earlierTime
*
* \return The interval between the two points in time
*/
static unsigned HidTimeDiff( const unsigned earlierTime, const unsigned laterTime )
{
return ( earlierTime < laterTime ) ? laterTime - earlierTime : UINT_MAX - earlierTime + laterTime;
}
#endif /* ( 0 < HID_CONTROLS ) */

55
lib_xua/src/hid/xua_hid.h Normal file
View File

@@ -0,0 +1,55 @@
// Copyright (c) 2019, XMOS Ltd, All rights reserved
#include <xs1.h>
#include <xccompat.h>
#include "xud.h"
#include "xud_std_requests.h"
/**
* \brief Calculate the next time to respond with a HID Report.
*
* If the USB Host has previously sent a valid HID Set_Idle request with
* a duration of zero or greater than the default reporting interval,
* the device sends HID Reports periodically or when the value of the
* payload has changed.
*
* This function calculates the time for sending the next periodic
* HID Report.
*/
void HidCalcNextReportTime( void );
/**
* \brief Capture the time of sending the current HID Report.
*
* If the USB Host has previously sent a valid HID Set_Idle request with
* a duration of zero or greater than the default reporting interval,
* the device sends HID Reports periodically or when the value of the
* payload has changed.
*
* This function captures the time when the HID Report was sent so that
* a subsequent call to HidCalNextReportTime() can calculate the time
* to send the next periodic HID Report.
*/
void HidCaptureReportTime( void );
XUD_Result_t HidInterfaceClassRequests(
XUD_ep c_ep0_out,
XUD_ep c_ep0_in,
REFERENCE_PARAM( USB_SetupPacket_t, sp ));
/**
* \brief Indicate whether to send a HID Report based on elapsed time.
*
* If the USB Host has previously sent a valid HID Set_Idle request with
* a duration of zero or greater than the default reporting interval,
* the device sends HID Reports periodically or when the value of the
* payload has changed.
*
* This function monitors the passage of time and reports to the caller
* whether or not the time to send the next periodic HID Report has
* elapsed.
*
* \return A Boolean value indicating whether or not to send the HID Report.
* \retval 1 -- Do not send the HID Report
* \retval 0 -- Send the HID Report
*/
unsigned HidIsSetIdleSilenced( void );