[Core] usb_device_state: consolidate usb state handling across implementations (#24258)
				
					
				
			* usb_device_state: add idle_rate, led and protocol Previously all usb drivers and platform implementations (expect for our oddball atsam) tracked the same two global variables: - keyboard_protocol: to indicate if we are in report or boot protocol - keyboard_idle: for the idle_rate of the keyboard endpoint And a local variable that was exposed trough some indirection: - keyboard_led_state: for the currently set indicator leds (caps lock etc.) These have all been moved into the usb_device_state struct wich is accessible by getters and setters. This reduces code duplication and centralizes the state management across platforms and drivers. Signed-off-by: Stefan Kerkmann <karlk90@pm.me> * usb_device_state: reset protocol on reset The usb hid specification section 7.2.6 states: When initialized, all devices default to report protocol. However the host should not make any assumptions about the device’s state and should set the desired protocol whenever initializing a device. Thus on reset we should always do exactly that. Signed-off-by: Stefan Kerkmann <karlk90@pm.me> * keyboards: fix oversize warnings Signed-off-by: Stefan Kerkmann <karlk90@pm.me> --------- Signed-off-by: Stefan Kerkmann <karlk90@pm.me>
This commit is contained in:
		
							parent
							
								
									80f8aae3ec
								
							
						
					
					
						commit
						3f9d464412
					
				
					 20 changed files with 165 additions and 130 deletions
				
			
		| 
						 | 
				
			
			@ -62,14 +62,13 @@
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
/* declarations */
 | 
			
		||||
uint8_t keyboard_leds(void);
 | 
			
		||||
void    send_keyboard(report_keyboard_t *report);
 | 
			
		||||
void    send_nkro(report_nkro_t *report);
 | 
			
		||||
void    send_mouse(report_mouse_t *report);
 | 
			
		||||
void    send_extra(report_extra_t *report);
 | 
			
		||||
void send_keyboard(report_keyboard_t *report);
 | 
			
		||||
void send_nkro(report_nkro_t *report);
 | 
			
		||||
void send_mouse(report_mouse_t *report);
 | 
			
		||||
void send_extra(report_extra_t *report);
 | 
			
		||||
 | 
			
		||||
/* host struct */
 | 
			
		||||
host_driver_t chibios_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
 | 
			
		||||
host_driver_t chibios_driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra};
 | 
			
		||||
 | 
			
		||||
#ifdef VIRTSER_ENABLE
 | 
			
		||||
void virtser_task(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,10 +54,6 @@ extern keymap_config_t keymap_config;
 | 
			
		|||
extern usb_endpoint_in_t  usb_endpoints_in[USB_ENDPOINT_IN_COUNT];
 | 
			
		||||
extern usb_endpoint_out_t usb_endpoints_out[USB_ENDPOINT_OUT_COUNT];
 | 
			
		||||
 | 
			
		||||
uint8_t _Alignas(2) keyboard_idle     = 0;
 | 
			
		||||
uint8_t _Alignas(2) keyboard_protocol = 1;
 | 
			
		||||
uint8_t keyboard_led_state            = 0;
 | 
			
		||||
 | 
			
		||||
static bool __attribute__((__unused__)) send_report_buffered(usb_endpoint_in_lut_t endpoint, void *report, size_t size);
 | 
			
		||||
static void __attribute__((__unused__)) flush_report_buffered(usb_endpoint_in_lut_t endpoint, bool padded);
 | 
			
		||||
static bool __attribute__((__unused__)) receive_report(usb_endpoint_out_lut_t endpoint, void *report, size_t size);
 | 
			
		||||
| 
						 | 
				
			
			@ -168,6 +164,7 @@ void usb_event_queue_task(void) {
 | 
			
		|||
                break;
 | 
			
		||||
            case USB_EVENT_RESET:
 | 
			
		||||
                usb_device_state_set_reset();
 | 
			
		||||
                usb_device_state_set_protocol(USB_PROTOCOL_REPORT);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                // Nothing to do, we don't handle it.
 | 
			
		||||
| 
						 | 
				
			
			@ -250,10 +247,10 @@ static void set_led_transfer_cb(USBDriver *usbp) {
 | 
			
		|||
    if (setup->wLength == 2) {
 | 
			
		||||
        uint8_t report_id = set_report_buf[0];
 | 
			
		||||
        if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) {
 | 
			
		||||
            keyboard_led_state = set_report_buf[1];
 | 
			
		||||
            usb_device_state_set_leds(set_report_buf[1]);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        keyboard_led_state = set_report_buf[0];
 | 
			
		||||
        usb_device_state_set_leds(set_report_buf[0]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -269,7 +266,9 @@ static bool usb_requests_hook_cb(USBDriver *usbp) {
 | 
			
		|||
                        return usb_get_report_cb(usbp);
 | 
			
		||||
                    case HID_REQ_GetProtocol:
 | 
			
		||||
                        if (setup->wIndex == KEYBOARD_INTERFACE) {
 | 
			
		||||
                            usbSetupTransfer(usbp, &keyboard_protocol, sizeof(uint8_t), NULL);
 | 
			
		||||
                            static uint8_t keyboard_protocol;
 | 
			
		||||
                            keyboard_protocol = usb_device_state_get_protocol();
 | 
			
		||||
                            usbSetupTransfer(usbp, &keyboard_protocol, sizeof(keyboard_protocol), NULL);
 | 
			
		||||
                            return true;
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -292,12 +291,12 @@ static bool usb_requests_hook_cb(USBDriver *usbp) {
 | 
			
		|||
                        break;
 | 
			
		||||
                    case HID_REQ_SetProtocol:
 | 
			
		||||
                        if (setup->wIndex == KEYBOARD_INTERFACE) {
 | 
			
		||||
                            keyboard_protocol = setup->wValue.word;
 | 
			
		||||
                            usb_device_state_set_protocol(setup->wValue.lbyte);
 | 
			
		||||
                        }
 | 
			
		||||
                        usbSetupTransfer(usbp, NULL, 0, NULL);
 | 
			
		||||
                        return true;
 | 
			
		||||
                    case HID_REQ_SetIdle:
 | 
			
		||||
                        keyboard_idle = setup->wValue.hbyte;
 | 
			
		||||
                        usb_device_state_set_idle_rate(setup->wValue.hbyte);
 | 
			
		||||
                        return usb_set_idle_cb(usbp);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
| 
						 | 
				
			
			@ -396,11 +395,6 @@ __attribute__((weak)) void restart_usb_driver(USBDriver *usbp) {
 | 
			
		|||
 * ---------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* LED status */
 | 
			
		||||
uint8_t keyboard_leds(void) {
 | 
			
		||||
    return keyboard_led_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @brief Send a report to the host, the report is enqueued into an output
 | 
			
		||||
 * queue and send once the USB endpoint becomes empty.
 | 
			
		||||
| 
						 | 
				
			
			@ -458,7 +452,7 @@ static bool receive_report(usb_endpoint_out_lut_t endpoint, void *report, size_t
 | 
			
		|||
 | 
			
		||||
void send_keyboard(report_keyboard_t *report) {
 | 
			
		||||
    /* If we're in Boot Protocol, don't send any report ID or other funky fields */
 | 
			
		||||
    if (!keyboard_protocol) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_BOOT) {
 | 
			
		||||
        send_report(USB_ENDPOINT_IN_KEYBOARD, &report->mods, 8);
 | 
			
		||||
    } else {
 | 
			
		||||
        send_report(USB_ENDPOINT_IN_KEYBOARD, report, KEYBOARD_REPORT_SIZE);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,9 +27,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern uint8_t keyboard_idle;
 | 
			
		||||
extern uint8_t keyboard_protocol;
 | 
			
		||||
 | 
			
		||||
/* host driver */
 | 
			
		||||
void           host_set_driver(host_driver_t *driver);
 | 
			
		||||
host_driver_t *host_get_driver(void);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,20 +72,14 @@
 | 
			
		|||
#    define USB_WAIT_FOR_ENUMERATION
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
uint8_t keyboard_idle = 0;
 | 
			
		||||
/* 0: Boot Protocol, 1: Report Protocol(default) */
 | 
			
		||||
uint8_t        keyboard_protocol  = 1;
 | 
			
		||||
static uint8_t keyboard_led_state = 0;
 | 
			
		||||
 | 
			
		||||
static report_keyboard_t keyboard_report_sent;
 | 
			
		||||
 | 
			
		||||
/* Host driver */
 | 
			
		||||
static uint8_t keyboard_leds(void);
 | 
			
		||||
static void    send_keyboard(report_keyboard_t *report);
 | 
			
		||||
static void    send_nkro(report_nkro_t *report);
 | 
			
		||||
static void    send_mouse(report_mouse_t *report);
 | 
			
		||||
static void    send_extra(report_extra_t *report);
 | 
			
		||||
host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
 | 
			
		||||
static void   send_keyboard(report_keyboard_t *report);
 | 
			
		||||
static void   send_nkro(report_nkro_t *report);
 | 
			
		||||
static void   send_mouse(report_mouse_t *report);
 | 
			
		||||
static void   send_extra(report_extra_t *report);
 | 
			
		||||
host_driver_t lufa_driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra};
 | 
			
		||||
 | 
			
		||||
void send_report(uint8_t endpoint, void *report, size_t size) {
 | 
			
		||||
    uint8_t timeout = 255;
 | 
			
		||||
| 
						 | 
				
			
			@ -271,6 +265,7 @@ void EVENT_USB_Device_Disconnect(void) {
 | 
			
		|||
void EVENT_USB_Device_Reset(void) {
 | 
			
		||||
    print("[R]");
 | 
			
		||||
    usb_device_state_set_reset();
 | 
			
		||||
    usb_device_state_set_protocol(USB_PROTOCOL_REPORT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Event USB Device Connect
 | 
			
		||||
| 
						 | 
				
			
			@ -453,10 +448,10 @@ void EVENT_USB_Device_ControlRequest(void) {
 | 
			
		|||
                            uint8_t report_id = Endpoint_Read_8();
 | 
			
		||||
 | 
			
		||||
                            if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) {
 | 
			
		||||
                                keyboard_led_state = Endpoint_Read_8();
 | 
			
		||||
                                usb_device_state_set_leds(Endpoint_Read_8());
 | 
			
		||||
                            }
 | 
			
		||||
                        } else {
 | 
			
		||||
                            keyboard_led_state = Endpoint_Read_8();
 | 
			
		||||
                            usb_device_state_set_leds(Endpoint_Read_8());
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        Endpoint_ClearOUT();
 | 
			
		||||
| 
						 | 
				
			
			@ -473,7 +468,7 @@ void EVENT_USB_Device_ControlRequest(void) {
 | 
			
		|||
                    Endpoint_ClearSETUP();
 | 
			
		||||
                    while (!(Endpoint_IsINReady()))
 | 
			
		||||
                        ;
 | 
			
		||||
                    Endpoint_Write_8(keyboard_protocol);
 | 
			
		||||
                    Endpoint_Write_8(usb_device_state_get_protocol());
 | 
			
		||||
                    Endpoint_ClearIN();
 | 
			
		||||
                    Endpoint_ClearStatusStage();
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -486,7 +481,7 @@ void EVENT_USB_Device_ControlRequest(void) {
 | 
			
		|||
                    Endpoint_ClearSETUP();
 | 
			
		||||
                    Endpoint_ClearStatusStage();
 | 
			
		||||
 | 
			
		||||
                    keyboard_protocol = (USB_ControlRequest.wValue & 0xFF);
 | 
			
		||||
                    usb_device_state_set_protocol(USB_ControlRequest.wValue & 0xFF);
 | 
			
		||||
                    clear_keyboard();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -497,7 +492,7 @@ void EVENT_USB_Device_ControlRequest(void) {
 | 
			
		|||
                Endpoint_ClearSETUP();
 | 
			
		||||
                Endpoint_ClearStatusStage();
 | 
			
		||||
 | 
			
		||||
                keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8);
 | 
			
		||||
                usb_device_state_set_idle_rate(USB_ControlRequest.wValue >> 8);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			@ -506,7 +501,7 @@ void EVENT_USB_Device_ControlRequest(void) {
 | 
			
		|||
                Endpoint_ClearSETUP();
 | 
			
		||||
                while (!(Endpoint_IsINReady()))
 | 
			
		||||
                    ;
 | 
			
		||||
                Endpoint_Write_8(keyboard_idle);
 | 
			
		||||
                Endpoint_Write_8(usb_device_state_get_idle_rate());
 | 
			
		||||
                Endpoint_ClearIN();
 | 
			
		||||
                Endpoint_ClearStatusStage();
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -522,13 +517,6 @@ void EVENT_USB_Device_ControlRequest(void) {
 | 
			
		|||
/*******************************************************************************
 | 
			
		||||
 * Host driver
 | 
			
		||||
 ******************************************************************************/
 | 
			
		||||
/** \brief Keyboard LEDs
 | 
			
		||||
 *
 | 
			
		||||
 * FIXME: Needs doc
 | 
			
		||||
 */
 | 
			
		||||
static uint8_t keyboard_leds(void) {
 | 
			
		||||
    return keyboard_led_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** \brief Send Keyboard
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			@ -536,7 +524,7 @@ static uint8_t keyboard_leds(void) {
 | 
			
		|||
 */
 | 
			
		||||
static void send_keyboard(report_keyboard_t *report) {
 | 
			
		||||
    /* If we're in Boot Protocol, don't send any report ID or other funky fields */
 | 
			
		||||
    if (!keyboard_protocol) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_BOOT) {
 | 
			
		||||
        send_report(KEYBOARD_IN_EPNUM, &report->mods, 8);
 | 
			
		||||
    } else {
 | 
			
		||||
        send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
#include "host.h"
 | 
			
		||||
#include "keycode_config.h"
 | 
			
		||||
#include "debug.h"
 | 
			
		||||
#include "usb_device_state.h"
 | 
			
		||||
#include "util.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +32,7 @@ uint8_t has_anykey(void) {
 | 
			
		|||
    uint8_t* p   = keyboard_report->keys;
 | 
			
		||||
    uint8_t  lp  = sizeof(keyboard_report->keys);
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_protocol && keymap_config.nkro) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
 | 
			
		||||
        p  = nkro_report->bits;
 | 
			
		||||
        lp = sizeof(nkro_report->bits);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +49,7 @@ uint8_t has_anykey(void) {
 | 
			
		|||
 */
 | 
			
		||||
uint8_t get_first_key(void) {
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_protocol && keymap_config.nkro) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
 | 
			
		||||
        uint8_t i = 0;
 | 
			
		||||
        for (; i < NKRO_REPORT_BITS && !nkro_report->bits[i]; i++)
 | 
			
		||||
            ;
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,7 @@ bool is_key_pressed(uint8_t key) {
 | 
			
		|||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_protocol && keymap_config.nkro) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
 | 
			
		||||
        if ((key >> 3) < NKRO_REPORT_BITS) {
 | 
			
		||||
            return nkro_report->bits[key >> 3] & 1 << (key & 7);
 | 
			
		||||
        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +151,7 @@ void del_key_bit(report_nkro_t* nkro_report, uint8_t code) {
 | 
			
		|||
 */
 | 
			
		||||
void add_key_to_report(uint8_t key) {
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_protocol && keymap_config.nkro) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
 | 
			
		||||
        add_key_bit(nkro_report, key);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -164,7 +165,7 @@ void add_key_to_report(uint8_t key) {
 | 
			
		|||
 */
 | 
			
		||||
void del_key_from_report(uint8_t key) {
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_protocol && keymap_config.nkro) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
 | 
			
		||||
        del_key_bit(nkro_report, key);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +180,7 @@ void del_key_from_report(uint8_t key) {
 | 
			
		|||
void clear_keys_from_report(void) {
 | 
			
		||||
    // not clear mods
 | 
			
		||||
#ifdef NKRO_ENABLE
 | 
			
		||||
    if (keyboard_protocol && keymap_config.nkro) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) {
 | 
			
		||||
        memset(nkro_report->bits, 0, sizeof(nkro_report->bits));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,15 +24,15 @@
 | 
			
		|||
#    include "os_detection.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT;
 | 
			
		||||
static struct usb_device_state usb_device_state = {.idle_rate = 0, .leds = 0, .protocol = USB_PROTOCOL_REPORT, .configure_state = USB_DEVICE_STATE_NO_INIT};
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) {
 | 
			
		||||
__attribute__((weak)) void notify_usb_device_state_change_kb(struct usb_device_state usb_device_state) {
 | 
			
		||||
    notify_usb_device_state_change_user(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {}
 | 
			
		||||
__attribute__((weak)) void notify_usb_device_state_change_user(struct usb_device_state usb_device_state) {}
 | 
			
		||||
 | 
			
		||||
static void notify_usb_device_state_change(enum usb_device_state usb_device_state) {
 | 
			
		||||
static void notify_usb_device_state_change(struct usb_device_state usb_device_state) {
 | 
			
		||||
#if defined(HAPTIC_ENABLE) && HAPTIC_OFF_IN_LOW_POWER
 | 
			
		||||
    haptic_notify_usb_device_state_change();
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -44,27 +44,58 @@ static void notify_usb_device_state_change(enum usb_device_state usb_device_stat
 | 
			
		|||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) {
 | 
			
		||||
    usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT;
 | 
			
		||||
void usb_device_state_set_configuration(bool is_configured, uint8_t configuration_number) {
 | 
			
		||||
    usb_device_state.configure_state = is_configured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) {
 | 
			
		||||
    usb_device_state = USB_DEVICE_STATE_SUSPEND;
 | 
			
		||||
void usb_device_state_set_suspend(bool is_configured, uint8_t configuration_number) {
 | 
			
		||||
    usb_device_state.configure_state = USB_DEVICE_STATE_SUSPEND;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) {
 | 
			
		||||
    usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT;
 | 
			
		||||
void usb_device_state_set_resume(bool is_configured, uint8_t configuration_number) {
 | 
			
		||||
    usb_device_state.configure_state = is_configured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_reset(void) {
 | 
			
		||||
    usb_device_state = USB_DEVICE_STATE_INIT;
 | 
			
		||||
    usb_device_state.configure_state = USB_DEVICE_STATE_INIT;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_init(void) {
 | 
			
		||||
    usb_device_state = USB_DEVICE_STATE_INIT;
 | 
			
		||||
    usb_device_state.configure_state = USB_DEVICE_STATE_INIT;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline usb_configure_state_t usb_device_state_get_configure_state(void) {
 | 
			
		||||
    return usb_device_state.configure_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_protocol(usb_hid_protocol_t protocol) {
 | 
			
		||||
    usb_device_state.protocol = protocol == USB_PROTOCOL_BOOT ? USB_PROTOCOL_BOOT : USB_PROTOCOL_REPORT;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline usb_hid_protocol_t usb_device_state_get_protocol() {
 | 
			
		||||
    return usb_device_state.protocol;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_leds(uint8_t leds) {
 | 
			
		||||
    usb_device_state.leds = leds;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline uint8_t usb_device_state_get_leds(void) {
 | 
			
		||||
    return usb_device_state.leds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_idle_rate(uint8_t idle_rate) {
 | 
			
		||||
    usb_device_state.idle_rate = idle_rate;
 | 
			
		||||
    notify_usb_device_state_change(usb_device_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline uint8_t usb_device_state_get_idle_rate(void) {
 | 
			
		||||
    return usb_device_state.idle_rate;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,20 +20,41 @@
 | 
			
		|||
#include <stdbool.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber);
 | 
			
		||||
void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber);
 | 
			
		||||
void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber);
 | 
			
		||||
void usb_device_state_set_reset(void);
 | 
			
		||||
void usb_device_state_init(void);
 | 
			
		||||
 | 
			
		||||
enum usb_device_state {
 | 
			
		||||
typedef enum {
 | 
			
		||||
    USB_DEVICE_STATE_NO_INIT    = 0, // We're in this state before calling usb_device_state_init()
 | 
			
		||||
    USB_DEVICE_STATE_INIT       = 1, // Can consume up to 100mA
 | 
			
		||||
    USB_DEVICE_STATE_CONFIGURED = 2, // Can consume up to what is specified in configuration descriptor, typically 500mA
 | 
			
		||||
    USB_DEVICE_STATE_SUSPEND    = 3  // Can consume only suspend current
 | 
			
		||||
} usb_configure_state_t;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    USB_PROTOCOL_BOOT   = 0,
 | 
			
		||||
    USB_PROTOCOL_REPORT = 1,
 | 
			
		||||
} usb_hid_protocol_t;
 | 
			
		||||
 | 
			
		||||
// note: we can't typedef this struct to usb_device_state_t because it would
 | 
			
		||||
// conflict with the previous definition in:
 | 
			
		||||
// lib/chibios-contrib/ext/nxp-middleware-usb/device/usb_device.h
 | 
			
		||||
struct usb_device_state {
 | 
			
		||||
    uint8_t               idle_rate;
 | 
			
		||||
    uint8_t               leds;
 | 
			
		||||
    usb_hid_protocol_t    protocol;
 | 
			
		||||
    usb_configure_state_t configure_state;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern enum usb_device_state usb_device_state;
 | 
			
		||||
void                  usb_device_state_set_configuration(bool is_configured, uint8_t configuration_number);
 | 
			
		||||
void                  usb_device_state_set_suspend(bool is_configured, uint8_t configuration_number);
 | 
			
		||||
void                  usb_device_state_set_resume(bool is_configured, uint8_t configuration_number);
 | 
			
		||||
void                  usb_device_state_set_reset(void);
 | 
			
		||||
void                  usb_device_state_init(void);
 | 
			
		||||
usb_configure_state_t usb_device_state_get_configure_state(void);
 | 
			
		||||
void                  usb_device_state_set_protocol(usb_hid_protocol_t protocol);
 | 
			
		||||
usb_hid_protocol_t    usb_device_state_get_protocol(void);
 | 
			
		||||
void                  usb_device_state_set_leds(uint8_t leds);
 | 
			
		||||
uint8_t               usb_device_state_get_leds(void);
 | 
			
		||||
void                  usb_device_state_set_idle_rate(uint8_t idle_rate);
 | 
			
		||||
uint8_t               usb_device_state_get_idle_rate(void);
 | 
			
		||||
void                  usb_device_state_reset_hid_state(void);
 | 
			
		||||
 | 
			
		||||
void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state);
 | 
			
		||||
void notify_usb_device_state_change_user(enum usb_device_state usb_device_state);
 | 
			
		||||
void notify_usb_device_state_change_kb(struct usb_device_state usb_device_state);
 | 
			
		||||
void notify_usb_device_state_change_user(struct usb_device_state usb_device_state);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
#include "debug.h"
 | 
			
		||||
#include "wait.h"
 | 
			
		||||
#include "usb_descriptor_common.h"
 | 
			
		||||
#include "usb_device_state.h"
 | 
			
		||||
 | 
			
		||||
#ifdef RAW_ENABLE
 | 
			
		||||
#    include "raw_hid.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -85,10 +86,6 @@ _Static_assert(TOTAL_INTERFACES <= MAX_INTERFACES, "There are not enough availab
 | 
			
		|||
#    error Mouse/Extra Keys share an endpoint with Console. Please disable one of the two.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint8_t keyboard_led_state = 0;
 | 
			
		||||
uint8_t        keyboard_idle      = 0;
 | 
			
		||||
uint8_t        keyboard_protocol  = 1;
 | 
			
		||||
 | 
			
		||||
static report_keyboard_t keyboard_report_sent;
 | 
			
		||||
 | 
			
		||||
static void send_report_fragment(uint8_t endpoint, void *data, size_t size) {
 | 
			
		||||
| 
						 | 
				
			
			@ -212,24 +209,19 @@ void console_task(void) {
 | 
			
		|||
/*------------------------------------------------------------------*
 | 
			
		||||
 * Host driver
 | 
			
		||||
 *------------------------------------------------------------------*/
 | 
			
		||||
static uint8_t keyboard_leds(void);
 | 
			
		||||
static void    send_keyboard(report_keyboard_t *report);
 | 
			
		||||
static void    send_nkro(report_nkro_t *report);
 | 
			
		||||
static void    send_mouse(report_mouse_t *report);
 | 
			
		||||
static void    send_extra(report_extra_t *report);
 | 
			
		||||
static void send_keyboard(report_keyboard_t *report);
 | 
			
		||||
static void send_nkro(report_nkro_t *report);
 | 
			
		||||
static void send_mouse(report_mouse_t *report);
 | 
			
		||||
static void send_extra(report_extra_t *report);
 | 
			
		||||
 | 
			
		||||
static host_driver_t driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra};
 | 
			
		||||
static host_driver_t driver = {.keyboard_leds = usb_device_state_get_leds, .send_keyboard = send_keyboard, .send_nkro = send_nkro, .send_mouse = send_mouse, .send_extra = send_extra};
 | 
			
		||||
 | 
			
		||||
host_driver_t *vusb_driver(void) {
 | 
			
		||||
    return &driver;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t keyboard_leds(void) {
 | 
			
		||||
    return keyboard_led_state;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void send_keyboard(report_keyboard_t *report) {
 | 
			
		||||
    if (!keyboard_protocol) {
 | 
			
		||||
    if (usb_device_state_get_protocol() == USB_PROTOCOL_BOOT) {
 | 
			
		||||
        send_report(1, &report->mods, 8);
 | 
			
		||||
    } else {
 | 
			
		||||
        send_report(1, report, sizeof(report_keyboard_t));
 | 
			
		||||
| 
						 | 
				
			
			@ -304,11 +296,15 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
 | 
			
		|||
                break;
 | 
			
		||||
            case USBRQ_HID_GET_IDLE:
 | 
			
		||||
                dprint("GET_IDLE:");
 | 
			
		||||
                usbMsgPtr = (usbMsgPtr_t)&keyboard_idle;
 | 
			
		||||
                static uint8_t keyboard_idle;
 | 
			
		||||
                keyboard_idle = usb_device_state_get_idle_rate();
 | 
			
		||||
                usbMsgPtr     = (usbMsgPtr_t)&keyboard_idle;
 | 
			
		||||
                return 1;
 | 
			
		||||
            case USBRQ_HID_GET_PROTOCOL:
 | 
			
		||||
                dprint("GET_PROTOCOL:");
 | 
			
		||||
                usbMsgPtr = (usbMsgPtr_t)&keyboard_protocol;
 | 
			
		||||
                static uint8_t keyboard_protocol;
 | 
			
		||||
                keyboard_protocol = usb_device_state_get_protocol();
 | 
			
		||||
                usbMsgPtr         = (usbMsgPtr_t)&keyboard_protocol;
 | 
			
		||||
                return 1;
 | 
			
		||||
            case USBRQ_HID_SET_REPORT:
 | 
			
		||||
                dprint("SET_REPORT:");
 | 
			
		||||
| 
						 | 
				
			
			@ -320,13 +316,13 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) {
 | 
			
		|||
                }
 | 
			
		||||
                return USB_NO_MSG; // to get data in usbFunctionWrite
 | 
			
		||||
            case USBRQ_HID_SET_IDLE:
 | 
			
		||||
                keyboard_idle = (rq->wValue.word & 0xFF00) >> 8;
 | 
			
		||||
                dprintf("SET_IDLE: %02X", keyboard_idle);
 | 
			
		||||
                usb_device_state_set_idle_rate(rq->wValue.word >> 8);
 | 
			
		||||
                dprintf("SET_IDLE: %02X", usb_device_state_get_idle_rate());
 | 
			
		||||
                break;
 | 
			
		||||
            case USBRQ_HID_SET_PROTOCOL:
 | 
			
		||||
                if (rq->wIndex.word == KEYBOARD_INTERFACE) {
 | 
			
		||||
                    keyboard_protocol = rq->wValue.word & 0xFF;
 | 
			
		||||
                    dprintf("SET_PROTOCOL: %02X", keyboard_protocol);
 | 
			
		||||
                    usb_device_state_set_protocol(rq->wValue.word & 0xFF);
 | 
			
		||||
                    dprintf("SET_PROTOCOL: %02X", usb_device_state_get_protocol());
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
| 
						 | 
				
			
			@ -347,9 +343,9 @@ uchar usbFunctionWrite(uchar *data, uchar len) {
 | 
			
		|||
    }
 | 
			
		||||
    switch (last_req.kind) {
 | 
			
		||||
        case SET_LED:
 | 
			
		||||
            dprintf("SET_LED: %02X\n", data[0]);
 | 
			
		||||
            keyboard_led_state = data[0];
 | 
			
		||||
            last_req.len       = 0;
 | 
			
		||||
            usb_device_state_set_leds(data[0]);
 | 
			
		||||
            dprintf("SET_LED: %02X\n", usb_device_state_get_leds());
 | 
			
		||||
            last_req.len = 0;
 | 
			
		||||
            return 1;
 | 
			
		||||
            break;
 | 
			
		||||
        case NONE:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue