add CDC interface

This commit is contained in:
King Kévin 2024-04-12 02:43:03 +02:00
parent 47b70f4584
commit 3ae95c20cf
4 changed files with 111 additions and 89 deletions

View File

@ -23,6 +23,8 @@
*
*/
#include "stm32f0xx_hal.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -32,6 +34,13 @@
#include "usb_descriptors.h"
#define BUTTON1_PORT GPIOA
#define BUTTON1_PIN GPIO_PIN_5
#define BUTTON1_STATE_ACTIVE 0
#define BUTTON2_PORT GPIOA
#define BUTTON2_PIN GPIO_PIN_7
#define BUTTON2_STATE_ACTIVE 0
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
@ -51,15 +60,38 @@ static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
void led_blinking_task(void);
void hid_task(void);
void cdc_task(void);
static void board_supplement_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = BUTTON1_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(BUTTON1_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BUTTON2_PIN;
HAL_GPIO_Init(BUTTON2_PORT, &GPIO_InitStruct);
}
uint32_t board_button1_read(void) {
return BUTTON1_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON1_PORT, BUTTON1_PIN);
}
uint32_t board_button2_read(void) {
return BUTTON2_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON2_PORT, BUTTON2_PIN);
}
/*------------- MAIN -------------*/
int main(void)
{
board_init();
board_supplement_init();
// init device stack on configured roothub port
tud_init(BOARD_TUD_RHPORT);
board_uart_write("\r\npasskey v2\r\n", 14);
if (board_init_after_tusb) {
board_init_after_tusb();
}
@ -70,6 +102,7 @@ int main(void)
led_blinking_task();
hid_task();
cdc_task();
}
}
@ -104,6 +137,49 @@ void tud_resume_cb(void)
blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
}
//--------------------------------------------------------------------+
// USB CDC
//--------------------------------------------------------------------+
void cdc_task(void) {
// connected() check for DTR bit
// Most but not all terminal client set this when making connection
// if ( tud_cdc_connected() )
{
// connected and there are data available
if (tud_cdc_available()) {
// read data
char buf[64];
uint32_t count = tud_cdc_read(buf, sizeof(buf));
(void) count;
// Echo back
// Note: Skip echo by commenting out write() and write_flush()
// for throughput test e.g
// $ dd if=/dev/zero of=/dev/ttyACM0 count=10000
tud_cdc_write(buf, count);
tud_cdc_write_flush();
}
}
}
// Invoked when cdc when line state changed e.g connected/disconnected
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) {
(void) itf;
(void) rts;
// TODO set some indicator
if (dtr) {
// Terminal connected
} else {
// Terminal disconnected
}
}
// Invoked when CDC interface received data from host
void tud_cdc_rx_cb(uint8_t itf) {
(void) itf;
}
//--------------------------------------------------------------------+
// USB HID
//--------------------------------------------------------------------+
@ -125,6 +201,7 @@ static void send_hid_report(uint8_t report_id, uint32_t btn)
uint8_t keycode[6] = { 0 };
keycode[0] = HID_KEY_A;
board_uart_write("K", 1);
tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode);
has_keyboard_key = true;
}else
@ -136,64 +213,6 @@ static void send_hid_report(uint8_t report_id, uint32_t btn)
}
break;
case REPORT_ID_MOUSE:
{
int8_t const delta = 5;
// no button, right + down, no scroll, no pan
tud_hid_mouse_report(REPORT_ID_MOUSE, 0x00, delta, delta, 0, 0);
}
break;
case REPORT_ID_CONSUMER_CONTROL:
{
// use to avoid send multiple consecutive zero report
static bool has_consumer_key = false;
if ( btn )
{
// volume down
uint16_t volume_down = HID_USAGE_CONSUMER_VOLUME_DECREMENT;
tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &volume_down, 2);
has_consumer_key = true;
}else
{
// send empty key report (release key) if previously has key pressed
uint16_t empty_key = 0;
if (has_consumer_key) tud_hid_report(REPORT_ID_CONSUMER_CONTROL, &empty_key, 2);
has_consumer_key = false;
}
}
break;
case REPORT_ID_GAMEPAD:
{
// use to avoid send multiple consecutive zero report for keyboard
static bool has_gamepad_key = false;
hid_gamepad_report_t report =
{
.x = 0, .y = 0, .z = 0, .rz = 0, .rx = 0, .ry = 0,
.hat = 0, .buttons = 0
};
if ( btn )
{
report.hat = GAMEPAD_HAT_UP;
report.buttons = GAMEPAD_BUTTON_A;
tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
has_gamepad_key = true;
}else
{
report.hat = GAMEPAD_HAT_CENTERED;
report.buttons = 0;
if (has_gamepad_key) tud_hid_report(REPORT_ID_GAMEPAD, &report, sizeof(report));
has_gamepad_key = false;
}
}
break;
default: break;
}
}
@ -209,7 +228,7 @@ void hid_task(void)
if ( board_millis() - start_ms < interval_ms) return; // not enough time
start_ms += interval_ms;
uint32_t const btn = board_button_read();
uint32_t const btn = board_button1_read();
// Remote wakeup
if ( tud_suspended() && btn )
@ -303,4 +322,6 @@ void led_blinking_task(void)
board_led_write(led_state);
led_state = 1 - led_state; // toggle
board_uart_write(".", 1);
}

View File

@ -92,7 +92,7 @@
//------------- CLASS -------------//
#define CFG_TUD_HID 1
#define CFG_TUD_CDC 0
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 0
#define CFG_TUD_MIDI 0
#define CFG_TUD_VENDOR 0
@ -100,6 +100,13 @@
// HID buffer size Should be sufficient to hold ID (if any) + Data
#define CFG_TUD_HID_EP_BUFSIZE 16
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// CDC Endpoint transfer buffer size, more is faster
#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#ifdef __cplusplus
}
#endif

View File

@ -27,17 +27,8 @@
#include "tusb.h"
#include "usb_descriptors.h"
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
*
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
*/
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
#define USB_VID 0xCafe
#define USB_PID 0x8861
#define USB_VID 0x1d50
#define USB_BCD 0x0200
//--------------------------------------------------------------------+
@ -48,9 +39,9 @@ tusb_desc_device_t const desc_device =
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = USB_BCD,
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bDeviceClass = TUSB_CLASS_HID,
.bDeviceSubClass = HID_SUBCLASS_NONE,
.bDeviceProtocol = HID_ITF_PROTOCOL_KEYBOARD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.idVendor = USB_VID,
@ -78,9 +69,6 @@ uint8_t const * tud_descriptor_device_cb(void)
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD )),
TUD_HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE )),
TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )),
TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD ))
};
// Invoked when received GET HID REPORT DESCRIPTOR
@ -99,12 +87,17 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t instance)
enum
{
ITF_NUM_HID,
ITF_NUM_CDC,
ITF_NUM_CDC_DATA,
ITF_NUM_TOTAL
};
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN)
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_CDC_DESC_LEN)
#define EPNUM_HID 0x81
#define EPNUM_HID 0x81
#define EPNUM_CDC_NOTIF 0x82
#define EPNUM_CDC_OUT 0x03
#define EPNUM_CDC_IN 0x83
uint8_t const desc_configuration[] =
{
@ -112,7 +105,11 @@ uint8_t const desc_configuration[] =
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5)
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 5),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 0, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, CFG_TUD_CDC_EP_BUFSIZE),
};
#if TUD_OPT_HIGH_SPEED
@ -128,9 +125,9 @@ tusb_desc_device_qualifier_t const desc_device_qualifier =
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
.bcdUSB = USB_BCD,
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bDeviceClass = TUSB_CLASS_HID,
.bDeviceSubClass = HID_SUBCLASS_NONE,
.bDeviceProtocol = HID_ITF_PROTOCOL_KEYBOARD,
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
.bNumConfigurations = 0x01,
@ -190,8 +187,8 @@ enum {
char const *string_desc_arr[] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB Device", // 2: Product
"CuVoodoo", // 1: Manufacturer
"passkey v2", // 2: Product
NULL, // 3: Serials will use unique ID if possible
};

View File

@ -28,9 +28,6 @@
enum
{
REPORT_ID_KEYBOARD = 1,
REPORT_ID_MOUSE,
REPORT_ID_CONSUMER_CONTROL,
REPORT_ID_GAMEPAD,
REPORT_ID_COUNT
};