[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
					
				| @ -158,7 +158,7 @@ void solenoid_setup(void) { | |||||||
| #endif | #endif | ||||||
|         gpio_write_pin(solenoid_pads[i], !solenoid_active_state[i]); |         gpio_write_pin(solenoid_pads[i], !solenoid_active_state[i]); | ||||||
|         gpio_set_pin_output(solenoid_pads[i]); |         gpio_set_pin_output(solenoid_pads[i]); | ||||||
|         if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) { |         if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state_get_configure_state() == USB_DEVICE_STATE_CONFIGURED)) { | ||||||
|             solenoid_fire(i); |             solenoid_fire(i); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -8,6 +8,9 @@ | |||||||
|         "pid": "0xE88F", |         "pid": "0xE88F", | ||||||
|         "device_version": "0.0.1" |         "device_version": "0.0.1" | ||||||
|     }, |     }, | ||||||
|  |     "build": { | ||||||
|  |         "lto": true | ||||||
|  |     }, | ||||||
|     "features": { |     "features": { | ||||||
|         "bootmagic": true, |         "bootmagic": true, | ||||||
|         "command": false, |         "command": false, | ||||||
|  | |||||||
| @ -8,6 +8,9 @@ | |||||||
|         "pid": "0x8C9C", |         "pid": "0x8C9C", | ||||||
|         "device_version": "0.0.2" |         "device_version": "0.0.2" | ||||||
|     }, |     }, | ||||||
|  |     "build": { | ||||||
|  |         "lto": true | ||||||
|  |     }, | ||||||
|     "features": { |     "features": { | ||||||
|         "bootmagic": true, |         "bootmagic": true, | ||||||
|         "encoder": true, |         "encoder": true, | ||||||
|  | |||||||
| @ -30,7 +30,6 @@ | |||||||
|             "knight": true, |             "knight": true, | ||||||
|             "rainbow_mood": true, |             "rainbow_mood": true, | ||||||
|             "rainbow_swirl": true, |             "rainbow_swirl": true, | ||||||
|             "rgb_test": true, |  | ||||||
|             "snake": true, |             "snake": true, | ||||||
|             "static_gradient": true, |             "static_gradient": true, | ||||||
|             "twinkle": true |             "twinkle": true | ||||||
|  | |||||||
| @ -51,8 +51,7 @@ | |||||||
|             "pixel_rain": true, |             "pixel_rain": true, | ||||||
|             "pixel_flow": true, |             "pixel_flow": true, | ||||||
|             "pixel_fractal": true, |             "pixel_fractal": true, | ||||||
|             "typing_heatmap": true, |             "typing_heatmap": true | ||||||
|             "digital_rain": true |  | ||||||
|         }, |         }, | ||||||
|         "driver": "ws2812", |         "driver": "ws2812", | ||||||
|         "max_brightness": 120, |         "max_brightness": 120, | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| #include "action_layer.h" | #include "action_layer.h" | ||||||
| #include "timer.h" | #include "timer.h" | ||||||
| #include "keycode_config.h" | #include "keycode_config.h" | ||||||
|  | #include "usb_device_state.h" | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 | 
 | ||||||
| extern keymap_config_t keymap_config; | extern keymap_config_t keymap_config; | ||||||
| @ -318,7 +319,7 @@ void send_nkro_report(void) { | |||||||
|  */ |  */ | ||||||
| void send_keyboard_report(void) { | void send_keyboard_report(void) { | ||||||
| #ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||||
|     if (keyboard_protocol && keymap_config.nkro) { |     if (usb_device_state_get_protocol() == USB_PROTOCOL_REPORT && keymap_config.nkro) { | ||||||
|         send_nkro_report(); |         send_nkro_report(); | ||||||
|     } else { |     } else { | ||||||
|         send_6kro_report(); |         send_6kro_report(); | ||||||
|  | |||||||
| @ -32,6 +32,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>. | |||||||
| #include "led.h" | #include "led.h" | ||||||
| #include "command.h" | #include "command.h" | ||||||
| #include "quantum.h" | #include "quantum.h" | ||||||
|  | #include "usb_device_state.h" | ||||||
| #include "version.h" | #include "version.h" | ||||||
| 
 | 
 | ||||||
| #ifdef BACKLIGHT_ENABLE | #ifdef BACKLIGHT_ENABLE | ||||||
| @ -230,8 +231,8 @@ static void print_status(void) { | |||||||
|         "timer_read32(): %08lX\n" |         "timer_read32(): %08lX\n" | ||||||
| 
 | 
 | ||||||
|         , host_keyboard_leds() |         , host_keyboard_leds() | ||||||
|         , keyboard_protocol |         , usb_device_state_get_protocol() | ||||||
|         , keyboard_idle |         , usb_device_state_get_idle_rate() | ||||||
| #ifdef NKRO_ENABLE | #ifdef NKRO_ENABLE | ||||||
|         , keymap_config.nkro |         , keymap_config.nkro | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -36,7 +36,7 @@ extern uint8_t split_haptic_play; | |||||||
| haptic_config_t haptic_config; | haptic_config_t haptic_config; | ||||||
| 
 | 
 | ||||||
| static void update_haptic_enable_gpios(void) { | static void update_haptic_enable_gpios(void) { | ||||||
|     if (haptic_config.enable && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) { |     if (haptic_config.enable && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state_get_configure_state() == USB_DEVICE_STATE_CONFIGURED))) { | ||||||
| #if defined(HAPTIC_ENABLE_PIN) | #if defined(HAPTIC_ENABLE_PIN) | ||||||
|         HAPTIC_ENABLE_PIN_WRITE_ACTIVE(); |         HAPTIC_ENABLE_PIN_WRITE_ACTIVE(); | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -65,8 +65,8 @@ static volatile os_variant_t reported_os = OS_UNSURE; | |||||||
| static volatile bool first_report = true; | static volatile bool first_report = true; | ||||||
| 
 | 
 | ||||||
| // to react on USB state changes
 | // to react on USB state changes
 | ||||||
| static volatile enum usb_device_state current_usb_device_state = USB_DEVICE_STATE_NO_INIT; | static volatile struct usb_device_state current_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT}; | ||||||
| static volatile enum usb_device_state maxprev_usb_device_state = USB_DEVICE_STATE_NO_INIT; | static volatile struct usb_device_state maxprev_usb_device_state = {.configure_state = USB_DEVICE_STATE_NO_INIT}; | ||||||
| 
 | 
 | ||||||
| // the OS detection might be unstable for a while, "debounce" it
 | // the OS detection might be unstable for a while, "debounce" it
 | ||||||
| static volatile bool         debouncing = false; | static volatile bool         debouncing = false; | ||||||
| @ -88,7 +88,7 @@ void os_detection_task(void) { | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|     if (current_usb_device_state == USB_DEVICE_STATE_CONFIGURED) { |     if (current_usb_device_state.configure_state == USB_DEVICE_STATE_CONFIGURED) { | ||||||
|         // debouncing goes for both the detected OS as well as the USB state
 |         // debouncing goes for both the detected OS as well as the USB state
 | ||||||
|         if (debouncing && timer_elapsed_fast(last_time) >= OS_DETECTION_DEBOUNCE) { |         if (debouncing && timer_elapsed_fast(last_time) >= OS_DETECTION_DEBOUNCE) { | ||||||
|             debouncing = false; |             debouncing = false; | ||||||
| @ -163,19 +163,19 @@ os_variant_t detected_host_os(void) { | |||||||
| 
 | 
 | ||||||
| void erase_wlength_data(void) { | void erase_wlength_data(void) { | ||||||
|     memset(&setups_data, 0, sizeof(setups_data)); |     memset(&setups_data, 0, sizeof(setups_data)); | ||||||
|     detected_os              = OS_UNSURE; |     detected_os                              = OS_UNSURE; | ||||||
|     reported_os              = OS_UNSURE; |     reported_os                              = OS_UNSURE; | ||||||
|     current_usb_device_state = USB_DEVICE_STATE_NO_INIT; |     current_usb_device_state.configure_state = USB_DEVICE_STATE_NO_INIT; | ||||||
|     maxprev_usb_device_state = USB_DEVICE_STATE_NO_INIT; |     maxprev_usb_device_state.configure_state = USB_DEVICE_STATE_NO_INIT; | ||||||
|     debouncing               = false; |     debouncing                               = false; | ||||||
|     last_time                = 0; |     last_time                                = 0; | ||||||
|     first_report             = true; |     first_report                             = true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void os_detection_notify_usb_device_state_change(enum usb_device_state usb_device_state) { | void os_detection_notify_usb_device_state_change(struct usb_device_state usb_device_state) { | ||||||
|     // treat this like any other source of instability
 |     // treat this like any other source of instability
 | ||||||
|     if (maxprev_usb_device_state < current_usb_device_state) { |     if (maxprev_usb_device_state.configure_state < current_usb_device_state.configure_state) { | ||||||
|         maxprev_usb_device_state = current_usb_device_state; |         maxprev_usb_device_state.configure_state = current_usb_device_state.configure_state; | ||||||
|     } |     } | ||||||
|     current_usb_device_state = usb_device_state; |     current_usb_device_state = usb_device_state; | ||||||
|     last_time                = timer_read_fast(); |     last_time                = timer_read_fast(); | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ typedef enum { | |||||||
| void         process_wlength(const uint16_t w_length); | void         process_wlength(const uint16_t w_length); | ||||||
| os_variant_t detected_host_os(void); | os_variant_t detected_host_os(void); | ||||||
| void         erase_wlength_data(void); | void         erase_wlength_data(void); | ||||||
| void         os_detection_notify_usb_device_state_change(enum usb_device_state usb_device_state); | void         os_detection_notify_usb_device_state_change(struct usb_device_state usb_device_state); | ||||||
| 
 | 
 | ||||||
| void os_detection_task(void); | void os_detection_task(void); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -253,9 +253,11 @@ TEST_F(OsDetectionTest, TestDoNotReportIfUsbUnstable) { | |||||||
|     EXPECT_EQ(detected_host_os(), OS_LINUX); |     EXPECT_EQ(detected_host_os(), OS_LINUX); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static struct usb_device_state usb_device_state_configured = {.configure_state = USB_DEVICE_STATE_CONFIGURED}; | ||||||
|  | 
 | ||||||
| TEST_F(OsDetectionTest, TestReportAfterDebounce) { | TEST_F(OsDetectionTest, TestReportAfterDebounce) { | ||||||
|     EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF, 0xFE}), OS_LINUX); |     EXPECT_EQ(check_sequence({0xFF, 0xFF, 0xFF, 0xFE}), OS_LINUX); | ||||||
|     os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); |     os_detection_notify_usb_device_state_change(usb_device_state_configured); | ||||||
|     os_detection_task(); |     os_detection_task(); | ||||||
|     assert_not_reported(); |     assert_not_reported(); | ||||||
| 
 | 
 | ||||||
| @ -291,7 +293,7 @@ TEST_F(OsDetectionTest, TestReportAfterDebounce) { | |||||||
| 
 | 
 | ||||||
| TEST_F(OsDetectionTest, TestReportAfterDebounceLongWait) { | TEST_F(OsDetectionTest, TestReportAfterDebounceLongWait) { | ||||||
|     EXPECT_EQ(check_sequence({0x12, 0xFF, 0xFF, 0x4, 0x10, 0xFF, 0xFF, 0xFF, 0x4, 0x10, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); |     EXPECT_EQ(check_sequence({0x12, 0xFF, 0xFF, 0x4, 0x10, 0xFF, 0xFF, 0xFF, 0x4, 0x10, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); | ||||||
|     os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); |     os_detection_notify_usb_device_state_change(usb_device_state_configured); | ||||||
|     os_detection_task(); |     os_detection_task(); | ||||||
|     assert_not_reported(); |     assert_not_reported(); | ||||||
| 
 | 
 | ||||||
| @ -318,7 +320,7 @@ TEST_F(OsDetectionTest, TestReportAfterDebounceLongWait) { | |||||||
| 
 | 
 | ||||||
| TEST_F(OsDetectionTest, TestReportUnsure) { | TEST_F(OsDetectionTest, TestReportUnsure) { | ||||||
|     EXPECT_EQ(check_sequence({0x12, 0xFF}), OS_UNSURE); |     EXPECT_EQ(check_sequence({0x12, 0xFF}), OS_UNSURE); | ||||||
|     os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); |     os_detection_notify_usb_device_state_change(usb_device_state_configured); | ||||||
|     os_detection_task(); |     os_detection_task(); | ||||||
|     assert_not_reported(); |     assert_not_reported(); | ||||||
| 
 | 
 | ||||||
| @ -345,7 +347,7 @@ TEST_F(OsDetectionTest, TestReportUnsure) { | |||||||
| 
 | 
 | ||||||
| TEST_F(OsDetectionTest, TestDoNotReportIntermediateResults) { | TEST_F(OsDetectionTest, TestDoNotReportIntermediateResults) { | ||||||
|     EXPECT_EQ(check_sequence({0x12, 0xFF}), OS_UNSURE); |     EXPECT_EQ(check_sequence({0x12, 0xFF}), OS_UNSURE); | ||||||
|     os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); |     os_detection_notify_usb_device_state_change(usb_device_state_configured); | ||||||
|     os_detection_task(); |     os_detection_task(); | ||||||
|     assert_not_reported(); |     assert_not_reported(); | ||||||
| 
 | 
 | ||||||
| @ -356,7 +358,7 @@ TEST_F(OsDetectionTest, TestDoNotReportIntermediateResults) { | |||||||
| 
 | 
 | ||||||
|     // at this stage, the final result has not been reached yet
 |     // at this stage, the final result has not been reached yet
 | ||||||
|     EXPECT_EQ(check_sequence({0xFF}), OS_LINUX); |     EXPECT_EQ(check_sequence({0xFF}), OS_LINUX); | ||||||
|     os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); |     os_detection_notify_usb_device_state_change(usb_device_state_configured); | ||||||
|     advance_time(OS_DETECTION_DEBOUNCE - 1); |     advance_time(OS_DETECTION_DEBOUNCE - 1); | ||||||
|     os_detection_task(); |     os_detection_task(); | ||||||
|     assert_not_reported(); |     assert_not_reported(); | ||||||
| @ -365,7 +367,7 @@ TEST_F(OsDetectionTest, TestDoNotReportIntermediateResults) { | |||||||
| 
 | 
 | ||||||
|     // the remainder is processed
 |     // the remainder is processed
 | ||||||
|     EXPECT_EQ(check_sequence({0x4, 0x10, 0xFF, 0xFF, 0xFF, 0x4, 0x10, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); |     EXPECT_EQ(check_sequence({0x4, 0x10, 0xFF, 0xFF, 0xFF, 0x4, 0x10, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A, 0x20A}), OS_WINDOWS); | ||||||
|     os_detection_notify_usb_device_state_change(USB_DEVICE_STATE_CONFIGURED); |     os_detection_notify_usb_device_state_change(usb_device_state_configured); | ||||||
|     advance_time(OS_DETECTION_DEBOUNCE - 1); |     advance_time(OS_DETECTION_DEBOUNCE - 1); | ||||||
|     os_detection_task(); |     os_detection_task(); | ||||||
|     assert_not_reported(); |     assert_not_reported(); | ||||||
|  | |||||||
| @ -129,7 +129,7 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) { |     if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state_get_configure_state() == USB_DEVICE_STATE_CONFIGURED))) { | ||||||
|         if (record->event.pressed) { |         if (record->event.pressed) { | ||||||
|             // keypress
 |             // keypress
 | ||||||
|             if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) { |             if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) { | ||||||
|  | |||||||
| @ -62,14 +62,13 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /* declarations */ | /* declarations */ | ||||||
| uint8_t keyboard_leds(void); | void send_keyboard(report_keyboard_t *report); | ||||||
| void    send_keyboard(report_keyboard_t *report); | void send_nkro(report_nkro_t *report); | ||||||
| void    send_nkro(report_nkro_t *report); | void send_mouse(report_mouse_t *report); | ||||||
| void    send_mouse(report_mouse_t *report); | void send_extra(report_extra_t *report); | ||||||
| void    send_extra(report_extra_t *report); |  | ||||||
| 
 | 
 | ||||||
| /* host struct */ | /* 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 | #ifdef VIRTSER_ENABLE | ||||||
| void virtser_task(void); | 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_in_t  usb_endpoints_in[USB_ENDPOINT_IN_COUNT]; | ||||||
| extern usb_endpoint_out_t usb_endpoints_out[USB_ENDPOINT_OUT_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 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 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); | 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; |                 break; | ||||||
|             case USB_EVENT_RESET: |             case USB_EVENT_RESET: | ||||||
|                 usb_device_state_set_reset(); |                 usb_device_state_set_reset(); | ||||||
|  |                 usb_device_state_set_protocol(USB_PROTOCOL_REPORT); | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
|                 // Nothing to do, we don't handle it.
 |                 // Nothing to do, we don't handle it.
 | ||||||
| @ -250,10 +247,10 @@ static void set_led_transfer_cb(USBDriver *usbp) { | |||||||
|     if (setup->wLength == 2) { |     if (setup->wLength == 2) { | ||||||
|         uint8_t report_id = set_report_buf[0]; |         uint8_t report_id = set_report_buf[0]; | ||||||
|         if ((report_id == REPORT_ID_KEYBOARD) || (report_id == REPORT_ID_NKRO)) { |         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 { |     } 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); |                         return usb_get_report_cb(usbp); | ||||||
|                     case HID_REQ_GetProtocol: |                     case HID_REQ_GetProtocol: | ||||||
|                         if (setup->wIndex == KEYBOARD_INTERFACE) { |                         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; |                             return true; | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
| @ -292,12 +291,12 @@ static bool usb_requests_hook_cb(USBDriver *usbp) { | |||||||
|                         break; |                         break; | ||||||
|                     case HID_REQ_SetProtocol: |                     case HID_REQ_SetProtocol: | ||||||
|                         if (setup->wIndex == KEYBOARD_INTERFACE) { |                         if (setup->wIndex == KEYBOARD_INTERFACE) { | ||||||
|                             keyboard_protocol = setup->wValue.word; |                             usb_device_state_set_protocol(setup->wValue.lbyte); | ||||||
|                         } |                         } | ||||||
|                         usbSetupTransfer(usbp, NULL, 0, NULL); |                         usbSetupTransfer(usbp, NULL, 0, NULL); | ||||||
|                         return true; |                         return true; | ||||||
|                     case HID_REQ_SetIdle: |                     case HID_REQ_SetIdle: | ||||||
|                         keyboard_idle = setup->wValue.hbyte; |                         usb_device_state_set_idle_rate(setup->wValue.hbyte); | ||||||
|                         return usb_set_idle_cb(usbp); |                         return usb_set_idle_cb(usbp); | ||||||
|                 } |                 } | ||||||
|                 break; |                 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 |  * @brief Send a report to the host, the report is enqueued into an output | ||||||
|  * queue and send once the USB endpoint becomes empty. |  * 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) { | void send_keyboard(report_keyboard_t *report) { | ||||||
|     /* If we're in Boot Protocol, don't send any report ID or other funky fields */ |     /* 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); |         send_report(USB_ENDPOINT_IN_KEYBOARD, &report->mods, 8); | ||||||
|     } else { |     } else { | ||||||
|         send_report(USB_ENDPOINT_IN_KEYBOARD, report, KEYBOARD_REPORT_SIZE); |         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" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern uint8_t keyboard_idle; |  | ||||||
| extern uint8_t keyboard_protocol; |  | ||||||
| 
 |  | ||||||
| /* host driver */ | /* host driver */ | ||||||
| void           host_set_driver(host_driver_t *driver); | void           host_set_driver(host_driver_t *driver); | ||||||
| host_driver_t *host_get_driver(void); | host_driver_t *host_get_driver(void); | ||||||
|  | |||||||
| @ -72,20 +72,14 @@ | |||||||
| #    define USB_WAIT_FOR_ENUMERATION | #    define USB_WAIT_FOR_ENUMERATION | ||||||
| #endif | #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; | static report_keyboard_t keyboard_report_sent; | ||||||
| 
 | 
 | ||||||
| /* Host driver */ | /* Host driver */ | ||||||
| static uint8_t keyboard_leds(void); | static void   send_keyboard(report_keyboard_t *report); | ||||||
| static void    send_keyboard(report_keyboard_t *report); | static void   send_nkro(report_nkro_t *report); | ||||||
| static void    send_nkro(report_nkro_t *report); | static void   send_mouse(report_mouse_t *report); | ||||||
| static void    send_mouse(report_mouse_t *report); | static void   send_extra(report_extra_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}; | ||||||
| host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_nkro, send_mouse, send_extra}; |  | ||||||
| 
 | 
 | ||||||
| void send_report(uint8_t endpoint, void *report, size_t size) { | void send_report(uint8_t endpoint, void *report, size_t size) { | ||||||
|     uint8_t timeout = 255; |     uint8_t timeout = 255; | ||||||
| @ -271,6 +265,7 @@ void EVENT_USB_Device_Disconnect(void) { | |||||||
| void EVENT_USB_Device_Reset(void) { | void EVENT_USB_Device_Reset(void) { | ||||||
|     print("[R]"); |     print("[R]"); | ||||||
|     usb_device_state_set_reset(); |     usb_device_state_set_reset(); | ||||||
|  |     usb_device_state_set_protocol(USB_PROTOCOL_REPORT); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** \brief Event USB Device Connect
 | /** \brief Event USB Device Connect
 | ||||||
| @ -453,10 +448,10 @@ void EVENT_USB_Device_ControlRequest(void) { | |||||||
|                             uint8_t report_id = Endpoint_Read_8(); |                             uint8_t report_id = Endpoint_Read_8(); | ||||||
| 
 | 
 | ||||||
|                             if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) { |                             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 { |                         } else { | ||||||
|                             keyboard_led_state = Endpoint_Read_8(); |                             usb_device_state_set_leds(Endpoint_Read_8()); | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         Endpoint_ClearOUT(); |                         Endpoint_ClearOUT(); | ||||||
| @ -473,7 +468,7 @@ void EVENT_USB_Device_ControlRequest(void) { | |||||||
|                     Endpoint_ClearSETUP(); |                     Endpoint_ClearSETUP(); | ||||||
|                     while (!(Endpoint_IsINReady())) |                     while (!(Endpoint_IsINReady())) | ||||||
|                         ; |                         ; | ||||||
|                     Endpoint_Write_8(keyboard_protocol); |                     Endpoint_Write_8(usb_device_state_get_protocol()); | ||||||
|                     Endpoint_ClearIN(); |                     Endpoint_ClearIN(); | ||||||
|                     Endpoint_ClearStatusStage(); |                     Endpoint_ClearStatusStage(); | ||||||
|                 } |                 } | ||||||
| @ -486,7 +481,7 @@ void EVENT_USB_Device_ControlRequest(void) { | |||||||
|                     Endpoint_ClearSETUP(); |                     Endpoint_ClearSETUP(); | ||||||
|                     Endpoint_ClearStatusStage(); |                     Endpoint_ClearStatusStage(); | ||||||
| 
 | 
 | ||||||
|                     keyboard_protocol = (USB_ControlRequest.wValue & 0xFF); |                     usb_device_state_set_protocol(USB_ControlRequest.wValue & 0xFF); | ||||||
|                     clear_keyboard(); |                     clear_keyboard(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -497,7 +492,7 @@ void EVENT_USB_Device_ControlRequest(void) { | |||||||
|                 Endpoint_ClearSETUP(); |                 Endpoint_ClearSETUP(); | ||||||
|                 Endpoint_ClearStatusStage(); |                 Endpoint_ClearStatusStage(); | ||||||
| 
 | 
 | ||||||
|                 keyboard_idle = ((USB_ControlRequest.wValue & 0xFF00) >> 8); |                 usb_device_state_set_idle_rate(USB_ControlRequest.wValue >> 8); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             break; |             break; | ||||||
| @ -506,7 +501,7 @@ void EVENT_USB_Device_ControlRequest(void) { | |||||||
|                 Endpoint_ClearSETUP(); |                 Endpoint_ClearSETUP(); | ||||||
|                 while (!(Endpoint_IsINReady())) |                 while (!(Endpoint_IsINReady())) | ||||||
|                     ; |                     ; | ||||||
|                 Endpoint_Write_8(keyboard_idle); |                 Endpoint_Write_8(usb_device_state_get_idle_rate()); | ||||||
|                 Endpoint_ClearIN(); |                 Endpoint_ClearIN(); | ||||||
|                 Endpoint_ClearStatusStage(); |                 Endpoint_ClearStatusStage(); | ||||||
|             } |             } | ||||||
| @ -522,13 +517,6 @@ void EVENT_USB_Device_ControlRequest(void) { | |||||||
| /*******************************************************************************
 | /*******************************************************************************
 | ||||||
|  * Host driver |  * Host driver | ||||||
|  ******************************************************************************/ |  ******************************************************************************/ | ||||||
| /** \brief Keyboard LEDs
 |  | ||||||
|  * |  | ||||||
|  * FIXME: Needs doc |  | ||||||
|  */ |  | ||||||
| static uint8_t keyboard_leds(void) { |  | ||||||
|     return keyboard_led_state; |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| /** \brief Send Keyboard
 | /** \brief Send Keyboard
 | ||||||
|  * |  * | ||||||
| @ -536,7 +524,7 @@ static uint8_t keyboard_leds(void) { | |||||||
|  */ |  */ | ||||||
| static void send_keyboard(report_keyboard_t *report) { | 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 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); |         send_report(KEYBOARD_IN_EPNUM, &report->mods, 8); | ||||||
|     } else { |     } else { | ||||||
|         send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE); |         send_report(KEYBOARD_IN_EPNUM, report, KEYBOARD_REPORT_SIZE); | ||||||
|  | |||||||
| @ -19,6 +19,7 @@ | |||||||
| #include "host.h" | #include "host.h" | ||||||
| #include "keycode_config.h" | #include "keycode_config.h" | ||||||
| #include "debug.h" | #include "debug.h" | ||||||
|  | #include "usb_device_state.h" | ||||||
| #include "util.h" | #include "util.h" | ||||||
| #include <string.h> | #include <string.h> | ||||||
| 
 | 
 | ||||||
| @ -31,7 +32,7 @@ uint8_t has_anykey(void) { | |||||||
|     uint8_t* p   = keyboard_report->keys; |     uint8_t* p   = keyboard_report->keys; | ||||||
|     uint8_t  lp  = sizeof(keyboard_report->keys); |     uint8_t  lp  = sizeof(keyboard_report->keys); | ||||||
| #ifdef NKRO_ENABLE | #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; |         p  = nkro_report->bits; | ||||||
|         lp = sizeof(nkro_report->bits); |         lp = sizeof(nkro_report->bits); | ||||||
|     } |     } | ||||||
| @ -48,7 +49,7 @@ uint8_t has_anykey(void) { | |||||||
|  */ |  */ | ||||||
| uint8_t get_first_key(void) { | uint8_t get_first_key(void) { | ||||||
| #ifdef NKRO_ENABLE | #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; |         uint8_t i = 0; | ||||||
|         for (; i < NKRO_REPORT_BITS && !nkro_report->bits[i]; i++) |         for (; i < NKRO_REPORT_BITS && !nkro_report->bits[i]; i++) | ||||||
|             ; |             ; | ||||||
| @ -68,7 +69,7 @@ bool is_key_pressed(uint8_t key) { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| #ifdef NKRO_ENABLE | #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) { |         if ((key >> 3) < NKRO_REPORT_BITS) { | ||||||
|             return nkro_report->bits[key >> 3] & 1 << (key & 7); |             return nkro_report->bits[key >> 3] & 1 << (key & 7); | ||||||
|         } else { |         } 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) { | void add_key_to_report(uint8_t key) { | ||||||
| #ifdef NKRO_ENABLE | #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); |         add_key_bit(nkro_report, key); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @ -164,7 +165,7 @@ void add_key_to_report(uint8_t key) { | |||||||
|  */ |  */ | ||||||
| void del_key_from_report(uint8_t key) { | void del_key_from_report(uint8_t key) { | ||||||
| #ifdef NKRO_ENABLE | #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); |         del_key_bit(nkro_report, key); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @ -179,7 +180,7 @@ void del_key_from_report(uint8_t key) { | |||||||
| void clear_keys_from_report(void) { | void clear_keys_from_report(void) { | ||||||
|     // not clear mods
 |     // not clear mods
 | ||||||
| #ifdef NKRO_ENABLE | #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)); |         memset(nkro_report->bits, 0, sizeof(nkro_report->bits)); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -24,15 +24,15 @@ | |||||||
| #    include "os_detection.h" | #    include "os_detection.h" | ||||||
| #endif | #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); |     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 | #if defined(HAPTIC_ENABLE) && HAPTIC_OFF_IN_LOW_POWER | ||||||
|     haptic_notify_usb_device_state_change(); |     haptic_notify_usb_device_state_change(); | ||||||
| #endif | #endif | ||||||
| @ -44,27 +44,58 @@ static void notify_usb_device_state_change(enum usb_device_state usb_device_stat | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { | void usb_device_state_set_configuration(bool is_configured, uint8_t configuration_number) { | ||||||
|     usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; |     usb_device_state.configure_state = is_configured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; | ||||||
|     notify_usb_device_state_change(usb_device_state); |     notify_usb_device_state_change(usb_device_state); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void usb_device_state_set_suspend(bool isConfigured, uint8_t configurationNumber) { | void usb_device_state_set_suspend(bool is_configured, uint8_t configuration_number) { | ||||||
|     usb_device_state = USB_DEVICE_STATE_SUSPEND; |     usb_device_state.configure_state = USB_DEVICE_STATE_SUSPEND; | ||||||
|     notify_usb_device_state_change(usb_device_state); |     notify_usb_device_state_change(usb_device_state); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void usb_device_state_set_resume(bool isConfigured, uint8_t configurationNumber) { | void usb_device_state_set_resume(bool is_configured, uint8_t configuration_number) { | ||||||
|     usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; |     usb_device_state.configure_state = is_configured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; | ||||||
|     notify_usb_device_state_change(usb_device_state); |     notify_usb_device_state_change(usb_device_state); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void usb_device_state_set_reset(void) { | 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); |     notify_usb_device_state_change(usb_device_state); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void usb_device_state_init(void) { | 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); |     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 <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| 
 | 
 | ||||||
| void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber); | typedef enum { | ||||||
| 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 { |  | ||||||
|     USB_DEVICE_STATE_NO_INIT    = 0, // We're in this state before calling usb_device_state_init()
 |     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_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_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_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_kb(struct 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_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 "debug.h" | ||||||
| #include "wait.h" | #include "wait.h" | ||||||
| #include "usb_descriptor_common.h" | #include "usb_descriptor_common.h" | ||||||
|  | #include "usb_device_state.h" | ||||||
| 
 | 
 | ||||||
| #ifdef RAW_ENABLE | #ifdef RAW_ENABLE | ||||||
| #    include "raw_hid.h" | #    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. | #    error Mouse/Extra Keys share an endpoint with Console. Please disable one of the two. | ||||||
| #endif | #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 report_keyboard_t keyboard_report_sent; | ||||||
| 
 | 
 | ||||||
| static void send_report_fragment(uint8_t endpoint, void *data, size_t size) { | static void send_report_fragment(uint8_t endpoint, void *data, size_t size) { | ||||||
| @ -212,24 +209,19 @@ void console_task(void) { | |||||||
| /*------------------------------------------------------------------*
 | /*------------------------------------------------------------------*
 | ||||||
|  * Host driver |  * Host driver | ||||||
|  *------------------------------------------------------------------*/ |  *------------------------------------------------------------------*/ | ||||||
| static uint8_t keyboard_leds(void); | static void send_keyboard(report_keyboard_t *report); | ||||||
| static void    send_keyboard(report_keyboard_t *report); | static void send_nkro(report_nkro_t *report); | ||||||
| static void    send_nkro(report_nkro_t *report); | static void send_mouse(report_mouse_t *report); | ||||||
| static void    send_mouse(report_mouse_t *report); | static void send_extra(report_extra_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) { | host_driver_t *vusb_driver(void) { | ||||||
|     return &driver; |     return &driver; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static uint8_t keyboard_leds(void) { |  | ||||||
|     return keyboard_led_state; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void send_keyboard(report_keyboard_t *report) { | 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); |         send_report(1, &report->mods, 8); | ||||||
|     } else { |     } else { | ||||||
|         send_report(1, report, sizeof(report_keyboard_t)); |         send_report(1, report, sizeof(report_keyboard_t)); | ||||||
| @ -304,11 +296,15 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) { | |||||||
|                 break; |                 break; | ||||||
|             case USBRQ_HID_GET_IDLE: |             case USBRQ_HID_GET_IDLE: | ||||||
|                 dprint("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; |                 return 1; | ||||||
|             case USBRQ_HID_GET_PROTOCOL: |             case USBRQ_HID_GET_PROTOCOL: | ||||||
|                 dprint("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; |                 return 1; | ||||||
|             case USBRQ_HID_SET_REPORT: |             case USBRQ_HID_SET_REPORT: | ||||||
|                 dprint("SET_REPORT:"); |                 dprint("SET_REPORT:"); | ||||||
| @ -320,13 +316,13 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) { | |||||||
|                 } |                 } | ||||||
|                 return USB_NO_MSG; // to get data in usbFunctionWrite
 |                 return USB_NO_MSG; // to get data in usbFunctionWrite
 | ||||||
|             case USBRQ_HID_SET_IDLE: |             case USBRQ_HID_SET_IDLE: | ||||||
|                 keyboard_idle = (rq->wValue.word & 0xFF00) >> 8; |                 usb_device_state_set_idle_rate(rq->wValue.word >> 8); | ||||||
|                 dprintf("SET_IDLE: %02X", keyboard_idle); |                 dprintf("SET_IDLE: %02X", usb_device_state_get_idle_rate()); | ||||||
|                 break; |                 break; | ||||||
|             case USBRQ_HID_SET_PROTOCOL: |             case USBRQ_HID_SET_PROTOCOL: | ||||||
|                 if (rq->wIndex.word == KEYBOARD_INTERFACE) { |                 if (rq->wIndex.word == KEYBOARD_INTERFACE) { | ||||||
|                     keyboard_protocol = rq->wValue.word & 0xFF; |                     usb_device_state_set_protocol(rq->wValue.word & 0xFF); | ||||||
|                     dprintf("SET_PROTOCOL: %02X", keyboard_protocol); |                     dprintf("SET_PROTOCOL: %02X", usb_device_state_get_protocol()); | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
| @ -347,9 +343,9 @@ uchar usbFunctionWrite(uchar *data, uchar len) { | |||||||
|     } |     } | ||||||
|     switch (last_req.kind) { |     switch (last_req.kind) { | ||||||
|         case SET_LED: |         case SET_LED: | ||||||
|             dprintf("SET_LED: %02X\n", data[0]); |             usb_device_state_set_leds(data[0]); | ||||||
|             keyboard_led_state = data[0]; |             dprintf("SET_LED: %02X\n", usb_device_state_get_leds()); | ||||||
|             last_req.len       = 0; |             last_req.len = 0; | ||||||
|             return 1; |             return 1; | ||||||
|             break; |             break; | ||||||
|         case NONE: |         case NONE: | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user