Initial commit for CM108 style HID endpoint PTT support

pull/21/head v1.2.0-rc.1
Simon Kueppers 2023-02-23 16:12:03 +01:00
rodzic ae24f73803
commit 6e77ea22ae
7 zmienionych plików z 194 dodań i 31 usunięć

Wyświetl plik

@ -97,6 +97,7 @@
//------------- CLASS -------------//
#define CFG_TUD_AUDIO 1
#define CFG_TUD_CDC 1
#define CFG_TUD_HID 1
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE 128
@ -105,6 +106,9 @@
// CDC Endpoint transfer buffer size, more is faster
#define CFG_TUD_CDC_EP_BUFSIZE 64
// HID buffer size
#define CFG_TUD_HID_EP_BUFSIZE 8
//--------------------------------------------------------------------
// AUDIO CLASS DRIVER CONFIGURATION
//--------------------------------------------------------------------
@ -115,7 +119,7 @@
#define CFG_TUD_AUDIO_ENABLE_EP_OUT 1
#define CFG_TUD_AUDIO_ENABLE_FEEDBACK_EP 1
#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN TUD_AUDIO_IO_DESC_LEN
#define CFG_TUD_AUDIO_FUNC_1_DESC_LEN AIOC_AUDIO_DESC_LEN
#define CFG_TUD_AUDIO_FUNC_1_N_AS_INT 1
#define CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ 64
#define CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE 2

Wyświetl plik

@ -1,6 +1,7 @@
#include "stm32f3xx_hal.h"
#include "aioc.h"
#include "led.h"
#include "ptt.h"
#include "usb.h"
#include <assert.h>
#include <stdio.h>
@ -91,6 +92,8 @@ int main(void)
LED_MODE(0, LED_MODE_SLOWPULSE2X);
LED_MODE(1, LED_MODE_SLOWPULSE2X);
PTT_Init();
USB_Init();
uint32_t i = 0;

Wyświetl plik

@ -4,6 +4,7 @@
#include "tusb.h"
#include "usb_serial.h"
#include "usb_audio.h"
#include "usb_hid.h"
// We have ISOCHRONOUS endpoints defined that share the same endpoint number, but have opposing directions.
// However with STM32 hardware, ISOCHRONOUS endpoints use both RX and TX structures of the same endpoint register in hardware
@ -26,13 +27,17 @@ uint8_t tu_stm32_edpt_number_cb(uint8_t addr)
case EPNUM_AUDIO_FB:
return 0x03;
case EPNUM_CDC_0_OUT:
case EPNUM_CDC_0_IN:
case EPNUM_HID_IN:
case EPNUM_HID_OUT:
return 0x04;
case EPNUM_CDC_0_NOTIF:
case EPNUM_CDC_0_OUT:
case EPNUM_CDC_0_IN:
return 0x05;
case EPNUM_CDC_0_NOTIF:
return 0x06;
default:
TU_BREAKPOINT();
return 0x00;
@ -127,6 +132,7 @@ void USB_Init(void)
// Init classes
USB_SerialInit();
USB_AudioInit();
USB_HIDInit();
// Start USB Stack
tud_init(BOARD_TUD_RHPORT);

Wyświetl plik

@ -52,10 +52,50 @@ uint8_t const* tud_descriptor_device_cb(void) {
return (uint8_t const*) &desc_device;
}
//--------------------------------------------------------------------+
// HID Report Descriptor
//--------------------------------------------------------------------+
uint8_t const desc_hid_report[] = {
/* CM108 emulation */
HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ),
HID_USAGE ( HID_USAGE_CONSUMER_CONTROL ),
HID_COLLECTION ( HID_COLLECTION_APPLICATION ),
/* Input */
HID_USAGE ( 0x00 ),
HID_LOGICAL_MIN ( 0x00 ),
HID_LOGICAL_MAX_N ( 0xff, 2 ),
HID_REPORT_SIZE ( 8 ),
HID_REPORT_COUNT( 4 ),
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),
/* Output */
HID_USAGE ( 0x00 ),
HID_LOGICAL_MIN ( 0x00 ),
HID_LOGICAL_MAX_N ( 0xff, 2 ),
HID_REPORT_SIZE ( 8 ),
HID_REPORT_COUNT( 4 ),
HID_OUTPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ),
HID_COLLECTION_END
};
// Invoked when received GET HID REPORT DESCRIPTOR
// Application return pointer to descriptor
// Descriptor contents must exist long enough for transfer to complete
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
{
(void) itf;
return desc_hid_report;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN + CFG_TUD_AUDIO * TUD_AUDIO_IO_DESC_LEN)
#define CONFIG_TOTAL_LEN ( \
TUD_CONFIG_DESC_LEN + \
AIOC_AUDIO_DESC_LEN + \
AIOC_HID_DESC_LEN + \
AIOC_CDC_DESC_LEN \
)
uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
@ -68,7 +108,28 @@ uint8_t const desc_fs_configuration[] = {
/* _power_ma */ 100
),
TUD_CDC_DESCRIPTOR(
AIOC_AUDIO_DESCRIPTOR(
/* _itfnum */ ITF_NUM_AUDIO_CONTROL,
/* _stridx */ STR_IDX_AUDIOITF,
/* _nBytesPerSample */ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE,
/* _nBitsUsedPerSample */ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE*8,
/* _epin */ EPNUM_AUDIO_IN,
/* _epinsize */ CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX,
/* _epout */ EPNUM_AUDIO_OUT,
/* _epoutsize */ CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX,
/* _epfb */ EPNUM_AUDIO_FB
),
AIOC_HID_DESCRIPTOR(
/* _itfnum */ ITF_NUM_HID,
/* _stridx */ STR_IDX_HIDITF,
/* _boot_protocol */HID_ITF_PROTOCOL_NONE,
/*_report_desc_len*/sizeof(desc_hid_report),
/* _epin */ EPNUM_HID_IN,
/* _epsize */ CFG_TUD_HID_EP_BUFSIZE,
/* _ep_interval */ 0x20
),
AIOC_CDC_DESCRIPTOR(
/* _itfnum */ ITF_NUM_CDC_0,
/* _stridx */ STR_IDX_CDCITF,
/* _ep_notif */ EPNUM_CDC_0_NOTIF,
@ -76,18 +137,6 @@ uint8_t const desc_fs_configuration[] = {
/* _epout */ EPNUM_CDC_0_OUT,
/* _epin */ EPNUM_CDC_0_IN,
/* _epsize */ CFG_TUD_CDC_EP_BUFSIZE
),
TUD_AUDIO_IO_DESCRIPTOR(
/*_itfnum*/ ITF_NUM_AUDIO_CONTROL,
/*_stridx*/ STR_IDX_AUDIOITF,
/*_nBytesPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE,
/*_nBitsUsedPerSample*/ CFG_TUD_AUDIO_FUNC_1_N_BYTES_PER_SAMPLE*8,
/*_epin*/ EPNUM_AUDIO_IN,
/*_epinsize*/ CFG_TUD_AUDIO_FUNC_1_EP_IN_SZ_MAX,
/*_epout*/ EPNUM_AUDIO_OUT,
/*_epoutsize*/ CFG_TUD_AUDIO_FUNC_1_EP_OUT_SZ_MAX,
/*_epfb*/ EPNUM_AUDIO_FB
)
};
@ -209,6 +258,10 @@ const uint16_t * tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
len = ascii_to_utf16(ptr, len, USB_STRING_AUDIOOUTCHAN);
break;
case STR_IDX_HIDITF:
len = ascii_to_utf16(ptr, len, USB_STRING_HIDITF);
break;
default:
TU_ASSERT(0, NULL);
break;

Wyświetl plik

@ -3,11 +3,12 @@
/* Interfaces */
enum USB_DESCRIPTORS_ITF {
ITF_NUM_CDC_0 = 0,
ITF_NUM_CDC_0_DATA,
ITF_NUM_AUDIO_CONTROL,
ITF_NUM_AUDIO_CONTROL = 0,
ITF_NUM_AUDIO_STREAMING_OUT,
ITF_NUM_AUDIO_STREAMING_IN,
ITF_NUM_HID, /* For CM108 compatibility make this interface #3 */
ITF_NUM_CDC_0,
ITF_NUM_CDC_0_DATA,
ITF_NUM_TOTAL
};
@ -17,7 +18,6 @@ enum USB_STRING_IDX {
STR_IDX_MANUFACTURER,
STR_IDX_PRODUCT,
STR_IDX_SERIAL,
STR_IDX_CDCITF,
STR_IDX_AUDIOITF,
STR_IDX_AUDIOIN,
STR_IDX_AUDIOOUT,
@ -25,6 +25,8 @@ enum USB_STRING_IDX {
STR_IDX_AUDIOOUTVOL,
STR_IDX_AUDIOINCHAN,
STR_IDX_AUDIOOUTCHAN,
STR_IDX_HIDITF,
STR_IDX_CDCITF
};
#define USB_VID 0x1209
@ -33,7 +35,6 @@ enum USB_STRING_IDX {
#define USB_STRING_MANUFACTURER "AIOC"
#define USB_STRING_PRODUCT "All-In-One-Cable"
#define USB_STRING_CDCITF "AIOC CDC"
#define USB_STRING_AUDIOITF "AIOC Audio"
#define USB_STRING_AUDIOIN "AIOC Audio In"
#define USB_STRING_AUDIOOUT "AIOC Audio Out"
@ -41,14 +42,19 @@ enum USB_STRING_IDX {
#define USB_STRING_AUDIOOUTVOL "AIOC Audio Out Volume"
#define USB_STRING_AUDIOINCHAN "AIOC Audio In Channel"
#define USB_STRING_AUDIOOUTCHAN "AIOC Audio Out Channel"
#define USB_STRING_CDCITF "AIOC CDC"
#define USB_STRING_HIDITF "AIOC HID"
/* Endpoints */
#define EPNUM_AUDIO_IN 0x81
#define EPNUM_AUDIO_OUT 0x02
#define EPNUM_AUDIO_FB 0x82
#define EPNUM_CDC_0_OUT 0x03
#define EPNUM_CDC_0_IN 0x83
#define EPNUM_CDC_0_NOTIF 0x84
#define EPNUM_HID_IN 0x83
#define EPNUM_HID_OUT 0x03
#define EPNUM_CDC_0_OUT 0x04
#define EPNUM_CDC_0_IN 0x84
#define EPNUM_CDC_0_NOTIF 0x85
/* Custom Audio Descriptor.
* Courtesy of https://github.com/hathach/tinyusb/issues/1249#issuecomment-1148727765 */
@ -65,7 +71,7 @@ enum USB_STRING_IDX {
#define AUDIO_NUM_INCHANNELS 0x01
#define AUDIO_NUM_OUTCHANNELS 0x01
#define TUD_AUDIO_CTRL_TOTAL_LEN ( \
#define AIOC_AUDIO_CTRL_TOTAL_LEN ( \
TUD_AUDIO_DESC_CLK_SRC_LEN + \
TUD_AUDIO_DESC_INPUT_TERM_LEN + \
TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN + \
@ -75,11 +81,11 @@ enum USB_STRING_IDX {
TUD_AUDIO_DESC_OUTPUT_TERM_LEN + \
TUD_AUDIO_DESC_FEATURE_UNIT_ONE_CHANNEL_LEN)
#define TUD_AUDIO_IO_DESC_LEN ( \
#define AIOC_AUDIO_DESC_LEN ( \
TUD_AUDIO_DESC_IAD_LEN + \
TUD_AUDIO_DESC_STD_AC_LEN + \
TUD_AUDIO_DESC_CS_AC_LEN + \
TUD_AUDIO_CTRL_TOTAL_LEN + \
AIOC_AUDIO_CTRL_TOTAL_LEN + \
/* Speaker Interface */ \
TUD_AUDIO_DESC_STD_AS_INT_LEN + \
TUD_AUDIO_DESC_STD_AS_INT_LEN + \
@ -96,14 +102,14 @@ enum USB_STRING_IDX {
TUD_AUDIO_DESC_STD_AS_ISO_EP_LEN + \
TUD_AUDIO_DESC_CS_AS_ISO_EP_LEN)
#define TUD_AUDIO_IO_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epinsize, _epout, _epoutsize, _epfb) \
#define AIOC_AUDIO_DESCRIPTOR(_itfnum, _stridx, _nBytesPerSample, _nBitsUsedPerSample, _epin, _epinsize, _epout, _epoutsize, _epfb) \
/* Standard Interface Association Descriptor (IAD) */ \
TUD_AUDIO_DESC_IAD(_itfnum, AUDIO_NUM_INTERFACES, /*_stridx*/ 0x00), \
/* Audio Control Interface */ \
/* Standard AC Interface Descriptor(4.7.1) */ \
TUD_AUDIO_DESC_STD_AC(/*_itfnum*/ _itfnum, /*_nEPs*/ 0x00, /*_stridx*/ _stridx), \
/* Class-Specific AC Interface Header Descriptor(4.7.2) */ \
TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, AUDIO_FUNC_CONVERTER, TUD_AUDIO_CTRL_TOTAL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS), \
TUD_AUDIO_DESC_CS_AC(/*_bcdADC*/ 0x0200, AUDIO_FUNC_CONVERTER, AIOC_AUDIO_CTRL_TOTAL_LEN, /*_ctrl*/ AUDIO_CS_AS_INTERFACE_CTRL_LATENCY_POS), \
/* Clock Source Descriptor(4.7.2.1) */ \
TUD_AUDIO_DESC_CLK_SRC(AUDIO_CTRL_ID_SPK_CLOCK, AUDIO_CLOCK_SOURCE_ATT_INT_PRO_CLK, (AUDIO_CTRL_RW << AUDIO_CLOCK_SOURCE_CTRL_CLK_FRQ_POS), /*_assocTerm*/ AUDIO_CTRL_ID_SPK_INPUT_STREAM, /*_stridx*/ 0x00), \
/* Speaker Terminals */ \
@ -147,4 +153,19 @@ enum USB_STRING_IDX {
/* Class-Specific AS Isochronous Audio Data Endpoint Descriptor(4.10.1.2) */ \
TUD_AUDIO_DESC_CS_AS_ISO_EP(AUDIO_CS_AS_ISO_DATA_EP_ATT_NON_MAX_PACKETS_OK, AUDIO_CTRL_NONE, AUDIO_CS_AS_ISO_DATA_EP_LOCK_DELAY_UNIT_UNDEFINED, 0x0000)
#define AIOC_HID_DESC_LEN (9 + 9 + 7)
#define AIOC_HID_DESCRIPTOR(_itfnum, _stridx, _boot_protocol, _report_desc_len, _epin, _epsize, _ep_interval) \
/* Interface */\
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_HID, (uint8_t)((_boot_protocol) ? (uint8_t)HID_SUBCLASS_BOOT : 0), _boot_protocol, _stridx,\
/* HID descriptor */\
9, HID_DESC_TYPE_HID, U16_TO_U8S_LE(0x0100), 0, 1, HID_DESC_TYPE_REPORT, U16_TO_U8S_LE(_report_desc_len),\
/* Endpoint In */\
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval
#define AIOC_CDC_DESC_LEN TUD_CDC_DESC_LEN
#define AIOC_CDC_DESCRIPTOR TUD_CDC_DESCRIPTOR
#endif /* USB_DESCRIPTORS_H_ */

Wyświetl plik

@ -0,0 +1,70 @@
#include "usb_hid.h"
#include "tusb.h"
#include "ptt.h"
#include "usb_descriptors.h"
#define USB_HID_INOUT_REPORT_LEN 4
static uint8_t gpioState = 0x00;
static void ControlPTT(uint8_t gpio)
{
/* PTT1 on GPIO 3, PTT2 on GPIO4 */
uint8_t pttMask = (gpio & 0x04 ? PTT_MASK_PTT1 : 0) |
(gpio & 0x08 ? PTT_MASK_PTT2 : 0);
PTT_Control(pttMask);
}
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
(void) itf;
(void) report_id;
(void) report_type;
(void) buffer;
(void) reqlen;
buffer[0] = 0x00;
buffer[1] = gpioState;
buffer[2] = 0x00;
buffer[3] = 0x00;
return USB_HID_INOUT_REPORT_LEN;
}
// Invoked when received SET_REPORT control request
void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
(void) itf;
(void) report_id;
switch (report_type) {
case HID_REPORT_TYPE_OUTPUT:
TU_ASSERT(bufsize == USB_HID_INOUT_REPORT_LEN, /* */);
/* Output report, emulate CM108 behaviour */
if ((buffer[0] & 0xC0) == 0) {
gpioState = buffer[1];
ControlPTT(gpioState);
}
break;
case HID_REPORT_TYPE_FEATURE:
/* Custom extension for configuring the AIOC */
break;
default:
TU_BREAKPOINT();
break;
}
}
void USB_HIDInit(void)
{
}

Wyświetl plik

@ -0,0 +1,6 @@
#ifndef USB_HID_H_
#define USB_HID_H_
void USB_HIDInit(void);
#endif /* USB_HID_H_ */