1
0
Fork 0

Initial vusb console support (#8559)

This commit is contained in:
Joel Challis 2020-05-03 01:25:39 +01:00 committed by GitHub
parent 2e6959ed87
commit 5f82b0782f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 256 additions and 48 deletions

View file

@ -10,6 +10,7 @@ TMK_COMMON_SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/action_util.c \ $(COMMON_DIR)/action_util.c \
$(COMMON_DIR)/print.c \ $(COMMON_DIR)/print.c \
$(COMMON_DIR)/debug.c \ $(COMMON_DIR)/debug.c \
$(COMMON_DIR)/sendchar_null.c \
$(COMMON_DIR)/util.c \ $(COMMON_DIR)/util.c \
$(COMMON_DIR)/eeconfig.c \ $(COMMON_DIR)/eeconfig.c \
$(COMMON_DIR)/report.c \ $(COMMON_DIR)/report.c \

View file

@ -16,4 +16,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "sendchar.h" #include "sendchar.h"
int8_t sendchar(uint8_t c) { return 0; } __attribute__((weak)) int8_t sendchar(uint8_t c) { return 0; }

View file

@ -161,7 +161,9 @@ ISR(IBM4704_INT_VECT) {
case STOP: case STOP:
// Data:Low // Data:Low
WAIT(data_lo, 100, state); WAIT(data_lo, 100, state);
rbuf_enqueue(data); if (!rbuf_enqueue(data)) {
print("rbuf: full\n");
}
ibm4704_error = IBM4704_ERR_NONE; ibm4704_error = IBM4704_ERR_NONE;
goto DONE; goto DONE;
break; break;

View file

@ -801,8 +801,6 @@ ERROR_EXIT:
Endpoint_SelectEndpoint(ep); Endpoint_SelectEndpoint(ep);
return -1; return -1;
} }
#else
int8_t sendchar(uint8_t c) { return 0; }
#endif #endif
/******************************************************************************* /*******************************************************************************

View file

@ -9,13 +9,12 @@ SRC += $(VUSB_DIR)/main.c \
$(VUSB_DIR)/usbdrv/oddebug.c $(VUSB_DIR)/usbdrv/oddebug.c
ifdef NO_UART ifneq ($(strip $(CONSOLE_ENABLE)), yes)
SRC += $(COMMON_DIR)/sendchar_null.c ifndef NO_UART
else
SRC += $(COMMON_DIR)/sendchar_uart.c \ SRC += $(COMMON_DIR)/sendchar_uart.c \
$(COMMON_DIR)/uart.c $(COMMON_DIR)/uart.c
endif endif
endif
# Search Path # Search Path
VPATH += $(TMK_PATH)/$(VUSB_DIR) VPATH += $(TMK_PATH)/$(VUSB_DIR)

View file

@ -21,12 +21,23 @@
#include "uart.h" #include "uart.h"
#include "debug.h" #include "debug.h"
#include "suspend.h" #include "suspend.h"
#include "wait.h"
#include "sendchar.h"
#ifdef SLEEP_LED_ENABLE #ifdef SLEEP_LED_ENABLE
# include "sleep_led.h" # include "sleep_led.h"
#endif #endif
#define UART_BAUD_RATE 115200 #define UART_BAUD_RATE 115200
#ifdef CONSOLE_ENABLE
void console_task(void);
#endif
#ifdef RAW_ENABLE
void raw_hid_task(void);
#endif
/* This is from main.c of USBaspLoader */ /* This is from main.c of USBaspLoader */
static void initForUsbConnectivity(void) { static void initForUsbConnectivity(void) {
uint8_t i = 0; uint8_t i = 0;
@ -39,10 +50,9 @@ static void initForUsbConnectivity(void) {
_delay_ms(1); _delay_ms(1);
} }
usbDeviceConnect(); usbDeviceConnect();
sei();
} }
void usb_remote_wakeup(void) { static void usb_remote_wakeup(void) {
cli(); cli();
int8_t ddr_orig = USBDDR; int8_t ddr_orig = USBDDR;
@ -59,6 +69,23 @@ void usb_remote_wakeup(void) {
sei(); sei();
} }
/** \brief Setup USB
*
* FIXME: Needs doc
*/
static void setup_usb(void) {
// debug("initForUsbConnectivity()\n");
initForUsbConnectivity();
// for Console_Task
print_set_sendchar(sendchar);
}
/** \brief Main
*
* FIXME: Needs doc
*/
int main(void) __attribute__((weak));
int main(void) { int main(void) {
bool suspended = false; bool suspended = false;
#if USB_COUNT_SOF #if USB_COUNT_SOF
@ -76,8 +103,10 @@ int main(void) {
keyboard_setup(); keyboard_setup();
host_set_driver(vusb_driver()); host_set_driver(vusb_driver());
debug("initForUsbConnectivity()\n"); setup_usb();
initForUsbConnectivity(); sei();
wait_ms(50);
keyboard_init(); keyboard_init();
#ifdef SLEEP_LED_ENABLE #ifdef SLEEP_LED_ENABLE
@ -120,18 +149,26 @@ int main(void) {
if (!suspended) { if (!suspended) {
usbPoll(); usbPoll();
// TODO: configuration process is incosistent. it sometime fails. // TODO: configuration process is inconsistent. it sometime fails.
// To prevent failing to configure NOT scan keyboard during configuration // To prevent failing to configure NOT scan keyboard during configuration
if (usbConfiguration && usbInterruptIsReady()) { if (usbConfiguration && usbInterruptIsReady()) {
keyboard_task(); keyboard_task();
} }
vusb_transfer_keyboard(); vusb_transfer_keyboard();
#ifdef RAW_ENABLE #ifdef RAW_ENABLE
usbPoll(); usbPoll();
if (usbConfiguration && usbInterruptIsReady3()) { if (usbConfiguration && usbInterruptIsReady3()) {
raw_hid_task(); raw_hid_task();
} }
#endif
#ifdef CONSOLE_ENABLE
usbPoll();
if (usbConfiguration && usbInterruptIsReady3()) {
console_task();
}
#endif #endif
} else if (suspend_wakeup_condition()) { } else if (suspend_wakeup_condition()) {
usb_remote_wakeup(); usb_remote_wakeup();

View file

@ -15,25 +15,50 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <avr/eeprom.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include <util/delay.h>
#include <stdint.h> #include <stdint.h>
#include "usbdrv.h" #include "usbdrv.h"
#include "usbconfig.h" #include "usbconfig.h"
#include "host.h" #include "host.h"
#include "report.h" #include "report.h"
#include "print.h"
#include "debug.h"
#include "host_driver.h" #include "host_driver.h"
#include "vusb.h" #include "vusb.h"
#include <util/delay.h> #include "print.h"
#include "debug.h"
#ifdef RAW_ENABLE #ifdef RAW_ENABLE
# include "raw_hid.h" # include "raw_hid.h"
#endif #endif
#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && defined(RAW_ENABLE) #if defined(CONSOLE_ENABLE)
# error "Enabling Mousekeys/Extrakeys and Raw HID at the same time is not currently supported on V-USB." # define RBUF_SIZE 128
# include "ring_buffer.h"
#endif
#define NEXT_INTERFACE __COUNTER__
/*
* Interface indexes
*/
enum usb_interfaces {
KEYBOARD_INTERFACE = NEXT_INTERFACE,
#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE))
MOUSE_EXTRA_INTERFACE = NEXT_INTERFACE,
#endif
#ifdef RAW_ENABLE
RAW_INTERFACE = NEXT_INTERFACE,
#endif
#ifdef CONSOLE_ENABLE
CONSOLE_INTERFACE = NEXT_INTERFACE,
#endif
TOTAL_INTERFACES = NEXT_INTERFACE,
};
#define MAX_INTERFACES 2
#if (NEXT_INTERFACE - 1) > MAX_INTERFACES
# error There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console
#endif #endif
static uint8_t vusb_keyboard_leds = 0; static uint8_t vusb_keyboard_leds = 0;
@ -120,7 +145,60 @@ void raw_hid_task(void) {
raw_output_received_bytes = 0; raw_output_received_bytes = 0;
} }
} }
#endif
/*------------------------------------------------------------------*
* Console
*------------------------------------------------------------------*/
#ifdef CONSOLE_ENABLE
# define CONSOLE_BUFFER_SIZE 32
# define CONSOLE_EPSIZE 8
int8_t sendchar(uint8_t c) {
rbuf_enqueue(c);
return 0;
}
static inline bool usbSendData3(char *data, uint8_t len) {
uint8_t retries = 5;
while (!usbInterruptIsReady3()) {
if (!(retries--)) {
return false;
}
usbPoll();
}
usbSetInterrupt3((unsigned char *)data, len);
return true;
}
void console_task(void) {
if (!usbConfiguration) {
return;
}
if (!rbuf_has_data()) {
return;
}
// Send in chunks of 8 padded to 32
char send_buf[CONSOLE_BUFFER_SIZE] = {0};
uint8_t send_buf_count = 0;
while (rbuf_has_data() && send_buf_count < CONSOLE_EPSIZE) {
send_buf[send_buf_count++] = rbuf_dequeue();
}
char *temp = send_buf;
for (uint8_t i = 0; i < 4; i++) {
if (!usbSendData3(temp, 8)) {
break;
}
temp += 8;
}
usbSendData3(0, 0);
usbPoll();
}
#endif #endif
/*------------------------------------------------------------------* /*------------------------------------------------------------------*
@ -429,7 +507,30 @@ const PROGMEM uchar raw_hid_report[] = {
0x95, RAW_BUFFER_SIZE, // Report Count 0x95, RAW_BUFFER_SIZE, // Report Count
0x75, 0x08, // Report Size (8) 0x75, 0x08, // Report Size (8)
0x91, 0x02, // Output (Data, Variable, Absolute) 0x91, 0x02, // Output (Data, Variable, Absolute)
0xC0, // End Collection 0xC0 // End Collection
};
#endif
#if defined(CONSOLE_ENABLE)
const PROGMEM uchar console_hid_report[] = {
0x06, 0x31, 0xFF, // Usage Page (Vendor Defined - PJRC Teensy compatible)
0x09, 0x74, // Usage (Vendor Defined - PJRC Teensy compatible)
0xA1, 0x01, // Collection (Application)
// Data to host
0x09, 0x75, // Usage (Vendor Defined)
0x15, 0x00, // Logical Minimum (0x00)
0x26, 0xFF, 0x00, // Logical Maximum (0x00FF)
0x95, CONSOLE_BUFFER_SIZE, // Report Count
0x75, 0x08, // Report Size (8)
0x81, 0x02, // Input (Data, Variable, Absolute)
// Data from host
0x09, 0x76, // Usage (Vendor Defined)
0x15, 0x00, // Logical Minimum (0x00)
0x26, 0xFF, 0x00, // Logical Maximum (0x00FF)
0x95, CONSOLE_BUFFER_SIZE, // Report Count
0x75, 0x08, // Report Size (8)
0x91, 0x02, // Output (Data)
0xC0 // End Collection
}; };
#endif #endif
@ -511,11 +612,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
.bDescriptorType = USBDESCR_CONFIG .bDescriptorType = USBDESCR_CONFIG
}, },
.wTotalLength = sizeof(usbConfigurationDescriptor_t), .wTotalLength = sizeof(usbConfigurationDescriptor_t),
# if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(RAW_ENABLE) .bNumInterfaces = TOTAL_INTERFACES,
.bNumInterfaces = 2,
# else
.bNumInterfaces = 1,
# endif
.bConfigurationValue = 0x01, .bConfigurationValue = 0x01,
.iConfiguration = 0x00, .iConfiguration = 0x00,
.bmAttributes = (1 << 7) | USBATTR_REMOTEWAKE, .bmAttributes = (1 << 7) | USBATTR_REMOTEWAKE,
@ -530,7 +627,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
.bLength = sizeof(usbInterfaceDescriptor_t), .bLength = sizeof(usbInterfaceDescriptor_t),
.bDescriptorType = USBDESCR_INTERFACE .bDescriptorType = USBDESCR_INTERFACE
}, },
.bInterfaceNumber = 0, .bInterfaceNumber = KEYBOARD_INTERFACE,
.bAlternateSetting = 0x00, .bAlternateSetting = 0x00,
.bNumEndpoints = 1, .bNumEndpoints = 1,
.bInterfaceClass = 0x03, .bInterfaceClass = 0x03,
@ -569,7 +666,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
.bLength = sizeof(usbInterfaceDescriptor_t), .bLength = sizeof(usbInterfaceDescriptor_t),
.bDescriptorType = USBDESCR_INTERFACE .bDescriptorType = USBDESCR_INTERFACE
}, },
.bInterfaceNumber = 1, .bInterfaceNumber = MOUSE_EXTRA_INTERFACE,
.bAlternateSetting = 0x00, .bAlternateSetting = 0x00,
.bNumEndpoints = 1, .bNumEndpoints = 1,
.bInterfaceClass = 0x03, .bInterfaceClass = 0x03,
@ -597,14 +694,15 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
.bmAttributes = 0x03, .bmAttributes = 0x03,
.wMaxPacketSize = 8, .wMaxPacketSize = 8,
.bInterval = USB_POLLING_INTERVAL_MS .bInterval = USB_POLLING_INTERVAL_MS
} },
# elif defined(RAW_ENABLE) # endif
# if defined(RAW_ENABLE)
.rawInterface = { .rawInterface = {
.header = { .header = {
.bLength = sizeof(usbInterfaceDescriptor_t), .bLength = sizeof(usbInterfaceDescriptor_t),
.bDescriptorType = USBDESCR_INTERFACE .bDescriptorType = USBDESCR_INTERFACE
}, },
.bInterfaceNumber = 1, .bInterfaceNumber = RAW_INTERFACE,
.bAlternateSetting = 0x00, .bAlternateSetting = 0x00,
.bNumEndpoints = 2, .bNumEndpoints = 2,
.bInterfaceClass = 0x03, .bInterfaceClass = 0x03,
@ -642,7 +740,56 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
.bmAttributes = 0x03, .bmAttributes = 0x03,
.wMaxPacketSize = RAW_EPSIZE, .wMaxPacketSize = RAW_EPSIZE,
.bInterval = USB_POLLING_INTERVAL_MS .bInterval = USB_POLLING_INTERVAL_MS
} },
# endif
# if defined(CONSOLE_ENABLE)
/*
* Console
*/
.consoleInterface = {
.header = {
.bLength = sizeof(usbInterfaceDescriptor_t),
.bDescriptorType = USBDESCR_INTERFACE
},
.bInterfaceNumber = CONSOLE_INTERFACE,
.bAlternateSetting = 0x00,
.bNumEndpoints = 2,
.bInterfaceClass = 0x03,
.bInterfaceSubClass = 0x00,
.bInterfaceProtocol = 0x00,
.iInterface = 0x00
},
.consoleHID = {
.header = {
.bLength = sizeof(usbHIDDescriptor_t),
.bDescriptorType = USBDESCR_HID
},
.bcdHID = 0x0111,
.bCountryCode = 0x00,
.bNumDescriptors = 1,
.bDescriptorType = USBDESCR_HID_REPORT,
.wDescriptorLength = sizeof(console_hid_report)
},
.consoleINEndpoint = {
.header = {
.bLength = sizeof(usbEndpointDescriptor_t),
.bDescriptorType = USBDESCR_ENDPOINT
},
.bEndpointAddress = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP3_NUMBER),
.bmAttributes = 0x03,
.wMaxPacketSize = CONSOLE_EPSIZE,
.bInterval = 0x01
},
.consoleOUTEndpoint = {
.header = {
.bLength = sizeof(usbEndpointDescriptor_t),
.bDescriptorType = USBDESCR_ENDPOINT
},
.bEndpointAddress = (USBRQ_DIR_HOST_TO_DEVICE | USB_CFG_EP3_NUMBER),
.bmAttributes = 0x03,
.wMaxPacketSize = CONSOLE_EPSIZE,
.bInterval = 0x01
},
# endif # endif
}; };
@ -690,40 +837,54 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
break; break;
case USBDESCR_HID: case USBDESCR_HID:
switch (rq->wValue.bytes[0]) { switch (rq->wValue.bytes[0]) {
case 0: case KEYBOARD_INTERFACE:
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.keyboardHID; usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.keyboardHID;
len = sizeof(usbHIDDescriptor_t); len = sizeof(usbHIDDescriptor_t);
break; break;
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) #if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
case 1: case MOUSE_EXTRA_INTERFACE:
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID; usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
len = sizeof(usbHIDDescriptor_t); len = sizeof(usbHIDDescriptor_t);
break; break;
#elif defined(RAW_ENABLE) #endif
case 1: #if defined(RAW_ENABLE)
case RAW_INTERFACE:
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID; usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID;
len = sizeof(usbHIDDescriptor_t); len = sizeof(usbHIDDescriptor_t);
break; break;
#endif
#if defined(CONSOLE_ENABLE)
case CONSOLE_INTERFACE:
usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.consoleHID;
len = sizeof(usbHIDDescriptor_t);
break;
#endif #endif
} }
break; break;
case USBDESCR_HID_REPORT: case USBDESCR_HID_REPORT:
/* interface index */ /* interface index */
switch (rq->wIndex.word) { switch (rq->wIndex.word) {
case 0: case KEYBOARD_INTERFACE:
usbMsgPtr = (unsigned char *)keyboard_hid_report; usbMsgPtr = (unsigned char *)keyboard_hid_report;
len = sizeof(keyboard_hid_report); len = sizeof(keyboard_hid_report);
break; break;
#if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) #if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
case 1: case MOUSE_EXTRA_INTERFACE:
usbMsgPtr = (unsigned char *)mouse_extra_hid_report; usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
len = sizeof(mouse_extra_hid_report); len = sizeof(mouse_extra_hid_report);
break; break;
#elif defined(RAW_ENABLE) #endif
case 1: #if defined(RAW_ENABLE)
case RAW_INTERFACE:
usbMsgPtr = (unsigned char *)raw_hid_report; usbMsgPtr = (unsigned char *)raw_hid_report;
len = sizeof(raw_hid_report); len = sizeof(raw_hid_report);
break; break;
#endif
#if defined(CONSOLE_ENABLE)
case CONSOLE_INTERFACE:
usbMsgPtr = (unsigned char *)console_hid_report;
len = sizeof(console_hid_report);
break;
#endif #endif
} }
break; break;

View file

@ -93,19 +93,24 @@ typedef struct usbConfigurationDescriptor {
usbInterfaceDescriptor_t mouseExtraInterface; usbInterfaceDescriptor_t mouseExtraInterface;
usbHIDDescriptor_t mouseExtraHID; usbHIDDescriptor_t mouseExtraHID;
usbEndpointDescriptor_t mouseExtraINEndpoint; usbEndpointDescriptor_t mouseExtraINEndpoint;
#elif defined(RAW_ENABLE) #endif
#if defined(RAW_ENABLE)
usbInterfaceDescriptor_t rawInterface; usbInterfaceDescriptor_t rawInterface;
usbHIDDescriptor_t rawHID; usbHIDDescriptor_t rawHID;
usbEndpointDescriptor_t rawINEndpoint; usbEndpointDescriptor_t rawINEndpoint;
usbEndpointDescriptor_t rawOUTEndpoint; usbEndpointDescriptor_t rawOUTEndpoint;
#endif #endif
#if defined(CONSOLE_ENABLE)
usbInterfaceDescriptor_t consoleInterface;
usbHIDDescriptor_t consoleHID;
usbEndpointDescriptor_t consoleINEndpoint;
usbEndpointDescriptor_t consoleOUTEndpoint;
#endif
} __attribute__((packed)) usbConfigurationDescriptor_t; } __attribute__((packed)) usbConfigurationDescriptor_t;
#define USB_STRING_LEN(s) (sizeof(usbDescriptorHeader_t) + ((s) << 1)) #define USB_STRING_LEN(s) (sizeof(usbDescriptorHeader_t) + ((s) << 1))
host_driver_t *vusb_driver(void); host_driver_t *vusb_driver(void);
void vusb_transfer_keyboard(void); void vusb_transfer_keyboard(void);
#ifdef RAW_ENABLE
void raw_hid_task(void);
#endif

View file

@ -3,21 +3,26 @@
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* Ring buffer to store scan codes from keyboard * Ring buffer to store scan codes from keyboard
*------------------------------------------------------------------*/ *------------------------------------------------------------------*/
#define RBUF_SIZE 32 #ifndef RBUF_SIZE
# define RBUF_SIZE 32
#endif
#include <util/atomic.h> #include <util/atomic.h>
#include <stdint.h>
#include <stdbool.h>
static uint8_t rbuf[RBUF_SIZE]; static uint8_t rbuf[RBUF_SIZE];
static uint8_t rbuf_head = 0; static uint8_t rbuf_head = 0;
static uint8_t rbuf_tail = 0; static uint8_t rbuf_tail = 0;
static inline void rbuf_enqueue(uint8_t data) { static inline bool rbuf_enqueue(uint8_t data) {
bool ret = false;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
uint8_t next = (rbuf_head + 1) % RBUF_SIZE; uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
if (next != rbuf_tail) { if (next != rbuf_tail) {
rbuf[rbuf_head] = data; rbuf[rbuf_head] = data;
rbuf_head = next; rbuf_head = next;
} else { ret = true;
print("rbuf: full\n");
} }
} }
return ret;
} }
static inline uint8_t rbuf_dequeue(void) { static inline uint8_t rbuf_dequeue(void) {
uint8_t val = 0; uint8_t val = 0;