NKRO and CC bugfix, remove printf from PIO in non-debug env

This commit is contained in:
Hrvoje Cavrak 2024-06-25 10:24:41 +02:00
parent bb78fea579
commit 0aa4addf2d
10 changed files with 92 additions and 90 deletions

View File

@ -32,6 +32,8 @@ int pio_usb_set_out_data(endpoint_t *ep, const uint8_t *buffer, uint8_t len);
// Misc functions
int pio_usb_kbd_set_leds(usb_device_t *device, uint8_t port, uint8_t value);
extern int dh_debug_printf(const char *format, ...);
#ifdef __cplusplus
}
#endif

View File

@ -414,7 +414,7 @@ bool pio_usb_host_send_setup(uint8_t root_idx, uint8_t device_address,
uint8_t const setup_packet[8]) {
endpoint_t *ep = _find_ep(root_idx, device_address, 0);
if (!ep) {
printf("cannot find ep 0x00\r\n");
dh_debug_printf("cannot find ep 0x00\r\n");
return false;
}
@ -430,7 +430,7 @@ bool pio_usb_host_endpoint_transfer(uint8_t root_idx, uint8_t device_address,
uint16_t buflen) {
endpoint_t *ep = _find_ep(root_idx, device_address, ep_address);
if (!ep) {
printf("no endpoint 0x%02X\r\n", ep_address);
dh_debug_printf("no endpoint 0x%02X\r\n", ep_address);
return false;
}
@ -449,7 +449,7 @@ bool pio_usb_host_endpoint_abort_transfer(uint8_t root_idx, uint8_t device_addre
uint8_t ep_address) {
endpoint_t *ep = _find_ep(root_idx, device_address, ep_address);
if (!ep) {
printf("no endpoint 0x%02X\r\n", ep_address);
dh_debug_printf("no endpoint 0x%02X\r\n", ep_address);
return false;
}
@ -679,13 +679,13 @@ static int __no_inline_not_in_flash_func(control_out_protocol)(
}
if (time_us_64() - start_time >= timeout) {
printf("control out[timeout]\n");
dh_debug_printf("control out[timeout]\n");
res = -2;
} else if (pipe->operation == CONTROL_ERROR) {
printf("control out[error]\n");
dh_debug_printf("control out[error]\n");
res = -1;
} else if (pipe->operation == CONTROL_COMPLETE) {
printf("control out[complete]\n");
dh_debug_printf("control out[complete]\n");
res = 0;
}
pipe->operation = CONTROL_NONE;
@ -723,13 +723,13 @@ static int __no_inline_not_in_flash_func(control_in_protocol)(
}
if (time_us_64() - start_time >= timeout) {
printf("control in[timeout]\n");
dh_debug_printf("control in[timeout]\n");
res = -2;
} else if (pipe->operation == CONTROL_ERROR) {
printf("control in[error]\n");
dh_debug_printf("control in[error]\n");
res = -1;
} else if (pipe->operation == CONTROL_COMPLETE) {
printf("control in[complete]\n");
dh_debug_printf("control in[complete]\n");
res = 0;
}
pipe->operation = CONTROL_NONE;
@ -763,18 +763,18 @@ static int get_hub_port_status(usb_device_t *device, uint8_t port,
static int initialize_hub(usb_device_t *device) {
uint8_t rx_buffer[16];
int res = 0;
printf("USB Hub detected\n");
dh_debug_printf("USB Hub detected\n");
usb_setup_packet_t get_hub_desc_request = GET_HUB_DESCRPTOR_REQUEST;
control_in_protocol(device, (uint8_t *)&get_hub_desc_request,
sizeof(get_hub_desc_request), rx_buffer, 8);
const hub_descriptor_t *desc = (hub_descriptor_t *)rx_buffer;
uint8_t port_num = desc->port_num;
printf("\tTurn on port powers\n");
dh_debug_printf("\tTurn on port powers\n");
for (int idx = 0; idx < port_num; idx++) {
res = set_hub_feature(device, idx, HUB_SET_PORT_POWER);
if (res != 0) {
printf("\tFailed to turn on ports\n");
dh_debug_printf("\tFailed to turn on ports\n");
break;
}
}
@ -837,7 +837,7 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
uint8_t idx_product = desc->product;
uint8_t idx_serial = desc->serial;
printf("Enumerating %04x:%04x, class:%d, address:%d\n", device->vid,
dh_debug_printf("Enumerating %04x:%04x, class:%d, address:%d\n", device->vid,
device->pid, device->device_class, address);
usb_setup_packet_t set_address_request = SET_ADDRESS_REQ_DEFAULT;
@ -862,9 +862,9 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
if (idx_manufacture != 0) {
res = get_string_descriptor(device, idx_manufacture, rx_buffer, str);
if (res == 0) {
printf("Manufacture:%s\n", str);
dh_debug_printf("Manufacture:%s\n", str);
} else {
printf("Failed to get string descriptor (Manufacture)\n");
dh_debug_printf("Failed to get string descriptor (Manufacture)\n");
}
stdio_flush();
}
@ -872,9 +872,9 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
if (idx_product != 0) {
res = get_string_descriptor(device, idx_product, rx_buffer, str);
if (res == 0) {
printf("Product:%s\n", str);
dh_debug_printf("Product:%s\n", str);
} else {
printf("Failed to get string descriptor (Product)\n");
dh_debug_printf("Failed to get string descriptor (Product)\n");
}
stdio_flush();
}
@ -882,9 +882,9 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
if (idx_serial != 0) {
res = get_string_descriptor(device, idx_serial, rx_buffer, str);
if (res == 0) {
printf("Serial:%s\n", str);
dh_debug_printf("Serial:%s\n", str);
} else {
printf("Failed to get string descriptor (Serial)\n");
dh_debug_printf("Failed to get string descriptor (Serial)\n");
}
stdio_flush();
}
@ -943,7 +943,7 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
case DESC_TYPE_INTERFACE: {
const interface_descriptor_t *d =
(const interface_descriptor_t *)descriptor;
printf(
dh_debug_printf(
"inum:%d, altsetting:%d, numep:%d, iclass:%d, isubclass:%d, "
"iprotcol:%d, iface:%d\n",
d->inum, d->altsetting, d->numep, d->iclass, d->isubclass,
@ -954,7 +954,7 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
case DESC_TYPE_ENDPOINT: {
const endpoint_descriptor_t *d =
(const endpoint_descriptor_t *)descriptor;
printf("\t\t\tepaddr:0x%02x, attr:%d, size:%d, interval:%d\n",
dh_debug_printf("\t\t\tepaddr:0x%02x, attr:%d, size:%d, interval:%d\n",
d->epaddr, d->attr, d->max_size[0] | (d->max_size[1] << 8),
d->interval);
@ -983,13 +983,13 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
ep->need_pre = !device->is_root && !device->is_fullspeed;
ep->is_tx = (d->epaddr & 0x80) ? false : true;
} else {
printf("No empty EP\n");
dh_debug_printf("No empty EP\n");
}
}
} break;
case DESC_TYPE_HID: {
const hid_descriptor_t *d = (const hid_descriptor_t *)descriptor;
printf(
dh_debug_printf(
"\tbcdHID:%x.%x, country:%d, desc num:%d, desc_type:%d, "
"desc_size:%d\n",
d->bcd_hid[1], d->bcd_hid[0], d->contry_code, d->num_desc,
@ -1011,11 +1011,11 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
control_in_protocol(
device, (uint8_t *)&get_hid_report_descrpitor_request,
sizeof(get_hid_report_descrpitor_request), rx_buffer, desc_len);
printf("\t\tReport descriptor:");
dh_debug_printf("\t\tReport descriptor:");
for (int i = 0; i < desc_len; i++) {
printf("%02x ", device->control_pipe.rx_buffer[i]);
dh_debug_printf("%02x ", device->control_pipe.rx_buffer[i]);
}
printf("\n");
dh_debug_printf("\n");
stdio_flush();
} break;
@ -1044,7 +1044,7 @@ static int enumerate_device(usb_device_t *device, uint8_t address) {
}
static void device_disconnect(usb_device_t *device) {
printf("Disconnect device %d\n", device->address);
dh_debug_printf("Disconnect device %d\n", device->address);
for (int port = 0; port < PIO_USB_HUB_PORT_CNT; port++) {
if (device->child_devices[port] != 0) {
device_disconnect(&pio_usb_device[device->child_devices[port]]);
@ -1086,7 +1086,7 @@ static int assign_new_device_to_port(usb_device_t *hub_device, uint8_t port, boo
pio_usb_device[idx].connected = true;
pio_usb_device[idx].is_fullspeed = !is_ls;
pio_usb_device[idx].event = EVENT_CONNECT;
printf("Assign device %d to %d-%d\n", idx, hub_device->address, port);
dh_debug_printf("Assign device %d to %d-%d\n", idx, hub_device->address, port);
endpoint_descriptor_t ep0_desc = {
sizeof(endpoint_descriptor_t), DESC_TYPE_ENDPOINT, 0x00, 0x00, { 0x08, 0x00 }, 0x00
@ -1097,7 +1097,7 @@ static int assign_new_device_to_port(usb_device_t *hub_device, uint8_t port, boo
return 0;
}
printf("Failed to assign device\n");
dh_debug_printf("Failed to assign device\n");
return -1;
}
@ -1114,22 +1114,22 @@ static void __no_inline_not_in_flash_func(process_hub_event)(
hub_port_status_t status;
int res = get_hub_port_status(device, port, &status);
if (res != 0) {
printf("Failed to get port%d-%d status\n", device->address, port);
dh_debug_printf("Failed to get port%d-%d status\n", device->address, port);
continue;
}
printf("port%d-%d status:%d %d\n", device->address, port,
dh_debug_printf("port%d-%d status:%d %d\n", device->address, port,
status.port_change, status.port_status);
if (status.port_change & HUB_CHANGE_PORT_CONNECTION) {
if (status.port_status & HUB_STAT_PORT_CONNECTION) {
printf("new device on port %d, reset port\n", port);
dh_debug_printf("new device on port %d, reset port\n", port);
if (device->child_devices[port] != 0) {
printf("device is already assigned. disconnect previous\n");
dh_debug_printf("device is already assigned. disconnect previous\n");
device_disconnect(&pio_usb_device[device->child_devices[port]]);
}
if (device->root->addr0_exists) {
printf("Address 0 already exists\n");
dh_debug_printf("Address 0 already exists\n");
continue;
}
@ -1137,17 +1137,17 @@ static void __no_inline_not_in_flash_func(process_hub_event)(
set_hub_feature(device, port, HUB_SET_PORT_RESET);
device->root->addr0_exists = true;
} else {
printf("No vacant in device pool\n");
dh_debug_printf("No vacant in device pool\n");
}
} else {
printf("device removed from port %d\n", port);
dh_debug_printf("device removed from port %d\n", port);
if (device->child_devices[port] != 0) {
device_disconnect(&pio_usb_device[device->child_devices[port]]);
}
}
clear_hub_feature(device, port, HUB_CLR_PORT_CONNECTION);
} else if (status.port_change & HUB_CHANGE_PORT_RESET) {
printf("reset port %d complete\n", port);
dh_debug_printf("reset port %d complete\n", port);
res = clear_hub_feature(device, port, HUB_CLR_PORT_RESET);
if (res == 0) {
assign_new_device_to_port(device, port,
@ -1164,7 +1164,7 @@ static void __no_inline_not_in_flash_func(process_hub_event)(
void __no_inline_not_in_flash_func(pio_usb_host_task)(void) {
for (int root_idx = 0; root_idx < PIO_USB_ROOT_PORT_CNT; root_idx++) {
if (pio_usb_root_port[root_idx].event == EVENT_CONNECT) {
printf("Root %d connected\n", root_idx);
dh_debug_printf("Root %d connected\n", root_idx);
int dev_idx = device_pool_vacant();
if (dev_idx >= 0) {
on_device_connect(&pio_port[0], &pio_usb_root_port[root_idx], dev_idx);
@ -1172,7 +1172,7 @@ void __no_inline_not_in_flash_func(pio_usb_host_task)(void) {
}
pio_usb_root_port[root_idx].event = EVENT_NONE;
} else if (pio_usb_root_port[root_idx].event == EVENT_DISCONNECT) {
printf("Root %d disconnected\n", root_idx);
dh_debug_printf("Root %d disconnected\n", root_idx);
pio_usb_host_close_device(
root_idx, pio_usb_root_port[root_idx].root_device->address);
pio_usb_root_port[root_idx].root_device->connected = false;
@ -1187,7 +1187,7 @@ void __no_inline_not_in_flash_func(pio_usb_host_task)(void) {
if (device->event == EVENT_CONNECT) {
device->event = EVENT_NONE;
printf("Device %d Connected\n", idx);
dh_debug_printf("Device %d Connected\n", idx);
int res = enumerate_device(device, idx + 1);
if (res == 0) {
device->enumerated = true;
@ -1198,7 +1198,7 @@ void __no_inline_not_in_flash_func(pio_usb_host_task)(void) {
}
if (res != 0) {
printf("Enumeration failed(%d)\n", res);
dh_debug_printf("Enumeration failed(%d)\n", res);
// retry
if (device->is_root) {
device->root->event = EVENT_DISCONNECT;
@ -1210,7 +1210,7 @@ void __no_inline_not_in_flash_func(pio_usb_host_task)(void) {
}
} else if (device->event == EVENT_DISCONNECT) {
device->event = EVENT_NONE;
printf("Disconnect\n");
dh_debug_printf("Disconnect\n");
device_disconnect(device);
} else if (device->event == EVENT_HUB_PORT_CHANGE) {
process_hub_event(device);

View File

@ -117,8 +117,9 @@ void config_enable_hotkey_handler(device_t *state, hid_keyboard_report_t *report
watchdog_hw->scratch[5] = MAGIC_WORD_1;
watchdog_hw->scratch[6] = MAGIC_WORD_2;
}
reboot();
release_all_keys(state);
state->reboot_requested = true;
};

View File

@ -46,7 +46,7 @@ void update_usage(parser_state_t *parser, int i) {
*(parser->p_usage + i) = *(parser->p_usage + i - 1);
}
void store_element(parser_state_t *parser, report_val_t *val, int i, uint32_t data, uint16_t size) {
void store_element(parser_state_t *parser, report_val_t *val, int i, uint32_t data, uint16_t size, hid_interface_t *iface) {
*val = (report_val_t){
.offset = parser->offset_in_bits,
.offset_idx = parser->offset_in_bits >> 3,
@ -63,6 +63,8 @@ void store_element(parser_state_t *parser, report_val_t *val, int i, uint32_t da
.global_usage = parser->global_usage,
.report_id = parser->report_id
};
iface->uses_report_id |= (parser->report_id != 0);
}
void handle_global_item(parser_state_t *parser, item_t *item) {
@ -102,7 +104,7 @@ void handle_main_input(parser_state_t *parser, item_t *item, hid_interface_t *if
for (int i = 0; i < count; i++) {
update_usage(parser, i);
store_element(parser, &val, i, item->val, size);
store_element(parser, &val, i, item->val, size, iface);
/* Use the parsed data to populate internal device structures */
extract_data(iface, &val);

View File

@ -55,7 +55,7 @@ int32_t get_report_value(uint8_t *report, report_val_t *val) {
}
/* After processing the descriptor, assign the values so we can later use them to interpret reports */
void handle_consumer_control_values(report_val_t *src, report_val_t *dst, hid_interface_t *iface) {
void handle_consumer_control_values(report_val_t *src, report_val_t *dst, hid_interface_t *iface) {
if (src->offset > MAX_CC_BUTTONS) {
return;
}
@ -90,10 +90,6 @@ void handle_keyboard_descriptor_values(report_val_t *src, report_val_t *dst, hid
if (src->item_type == CONSTANT)
return;
/* Make note if we're using a report ID or not */
if (src->report_id > 0)
iface->keyboard.uses_report_id = true;
/* Detect and handle modifier keys. <= if modifier is less + constant padding? */
if (src->size <= MODIFIER_BIT_LENGTH && src->data_type == VARIABLE) {
/* To make sure this really is the modifier key, we expect e.g. left control to be
@ -236,10 +232,11 @@ int32_t _extract_kbd_boot(uint8_t *raw_report, int len, hid_keyboard_report_t *r
return KBD_REPORT_LENGTH;
}
int32_t _extract_kbd_other(uint8_t *raw_report, int len, keyboard_t *kb, hid_keyboard_report_t *report) {
int32_t _extract_kbd_other(uint8_t *raw_report, int len, hid_interface_t *iface, hid_keyboard_report_t *report) {
uint8_t *src = raw_report;
keyboard_t *kb = &iface->keyboard;
if (kb->uses_report_id)
if (iface->uses_report_id)
src++;
report->modifier = src[kb->modifier.offset_idx];
@ -251,11 +248,12 @@ int32_t _extract_kbd_other(uint8_t *raw_report, int len, keyboard_t *kb, hid_key
return KBD_REPORT_LENGTH;
}
int32_t _extract_kbd_nkro(uint8_t *raw_report, int len, keyboard_t *kb, hid_keyboard_report_t *report) {
int32_t _extract_kbd_nkro(uint8_t *raw_report, int len, hid_interface_t *iface, hid_keyboard_report_t *report) {
uint8_t *ptr = raw_report;
keyboard_t *kb = &iface->keyboard;
/* Skip report ID */
if (kb->uses_report_id)
if (iface->uses_report_id)
ptr++;
/* We expect array of bits mapping 1:1 from usage_min to usage_max, otherwise panic */
@ -282,19 +280,20 @@ int32_t extract_kbd_data(
/* Clear the report to start fresh */
memset(report, 0, KBD_REPORT_LENGTH);
/* NKRO is a special case */
if (report_id == iface->keyboard.nkro.report_id
&& iface->keyboard.is_nkro
&& itf == HID_ITF_PROTOCOL_NONE)
return _extract_kbd_nkro(raw_report, len, &iface->keyboard, report);
/* If we're in boot protocol mode, then it's easy to decide. */
if (iface->protocol == HID_PROTOCOL_BOOT)
return _extract_kbd_boot(raw_report, len, report);
/* NKRO is a special case */
if (report_id > 0
&& report_id == iface->keyboard.nkro.report_id
&& iface->keyboard.is_nkro)
return _extract_kbd_nkro(raw_report, len, iface, report);
/* If we're getting 8 bytes of report, it's safe to assume standard modifier + reserved + keys */
if (len == KBD_REPORT_LENGTH || len == KBD_REPORT_LENGTH + 1)
return _extract_kbd_boot(raw_report, len, report);
/* This is something completely different, look at the report */
return _extract_kbd_other(raw_report, len, &iface->keyboard, report);
return _extract_kbd_other(raw_report, len, iface, report);
}

View File

@ -138,6 +138,7 @@ struct hid_interface_t {
report_t system;
process_report_f report_handler[MAX_REPORTS];
uint8_t protocol;
bool uses_report_id;
};
typedef struct {

View File

@ -86,7 +86,6 @@
//------------- DEBUG -------------//
#ifdef DH_DEBUG
#define CFG_TUD_CDC 1
#define CFG_TUD_LOG_LEVEL 3
#define CFG_TUSB_DEBUG_PRINTF dh_debug_printf
extern int dh_debug_printf(const char *__restrict __format, ...);

View File

@ -162,7 +162,7 @@ void process_kbd_queue_task(device_t *state) {
void queue_kbd_report(hid_keyboard_report_t *report, device_t *state) {
/* It wouldn't be fun to queue up a bunch of messages and then dump them all on host */
if (!state->tud_connected)
return;
return;
queue_try_add(&state->kbd_queue, report);
}
@ -214,6 +214,10 @@ void process_keyboard_report(uint8_t *raw_report, int length, uint8_t itf, hid_i
if (length < KBD_REPORT_LENGTH)
return;
/* No more keys accepted if we're about to reboot */
if (global_state.reboot_requested)
return;
extract_kbd_data(raw_report, length, itf, iface, &new_report);
/* Check if any hotkey was pressed */
@ -240,7 +244,7 @@ void process_keyboard_report(uint8_t *raw_report, int length, uint8_t itf, hid_i
void process_consumer_report(uint8_t *raw_report, int length, uint8_t itf, hid_interface_t *iface) {
uint8_t new_report[CONSUMER_CONTROL_LENGTH] = {0};
uint16_t *report_ptr = (uint16_t *)new_report;
/* If consumer control is variable, read the values from cc_array and send as array. */
if (iface->consumer.is_variable) {
for (int i = 0; i < MAX_CC_BUTTONS && i < 8 * (length - 1); i++) {

View File

@ -55,7 +55,10 @@ void pio_usb_host_config(device_t *state) {
static pio_usb_configuration_t config = PIO_USB_DEFAULT_CONFIG;
config.pin_dp = PIO_USB_DP_PIN_DEFAULT;
tuh_hid_set_default_protocol(HID_PROTOCOL_REPORT);
/* Board B is always report mode, board A is default-boot if configured */
if (state->board_role == OUTPUT_B || ENFORCE_KEYBOARD_BOOT_PROTOCOL == 0)
tuh_hid_set_default_protocol(HID_PROTOCOL_REPORT);
tuh_configure(BOARD_TUH_RHPORT, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &config);
/* Initialize and configure TinyUSB Host */

View File

@ -141,7 +141,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
return;
/* Parse the report descriptor into our internal structure. */
parse_report_descriptor(iface, desc_report, desc_len);
parse_report_descriptor(iface, desc_report, desc_len);
switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
@ -150,9 +150,7 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
if (global_state.config.force_kbd_boot_protocol)
tuh_hid_set_protocol(dev_addr, instance, HID_PROTOCOL_BOOT);
iface->keyboard.uses_report_id = iface->keyboard.report_id > 0;
/* Keeping this is required for setting leds from device set_report callback */
global_state.kbd_dev_addr = dev_addr;
global_state.kbd_instance = instance;
@ -168,8 +166,6 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_re
if (tuh_hid_get_protocol(dev_addr, instance) == HID_PROTOCOL_BOOT) {
tuh_hid_set_protocol(dev_addr, instance, HID_PROTOCOL_REPORT);
}
iface->mouse.uses_report_id = iface->mouse.report_id > 0;
break;
case HID_ITF_PROTOCOL_NONE:
@ -198,26 +194,21 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
if (instance >= MAX_INTERFACES)
return;
switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
process_keyboard_report((uint8_t *)report, len, itf_protocol, iface);
break;
if (iface->uses_report_id) {
uint8_t report_id = report[0];
case HID_ITF_PROTOCOL_MOUSE:
process_mouse_report((uint8_t *)report, len, itf_protocol, iface);
break;
if (report_id < MAX_REPORTS) {
process_report_f receiver = iface->report_handler[report_id];
/* This can be NKRO keyboard, consumer control, system, mouse, anything. */
case HID_ITF_PROTOCOL_NONE:
uint8_t report_id = report[0];
if (report_id < MAX_REPORTS) {
process_report_f receiver = iface->report_handler[report_id];
if (receiver != NULL)
receiver((uint8_t *)report, len, itf_protocol, iface);
}
break;
if (receiver != NULL)
receiver((uint8_t *)report, len, itf_protocol, iface);
}
}
else if (itf_protocol == HID_ITF_PROTOCOL_KEYBOARD) {
process_keyboard_report((uint8_t *)report, len, itf_protocol, iface);
}
else if (itf_protocol == HID_ITF_PROTOCOL_MOUSE) {
process_mouse_report((uint8_t *)report, len, itf_protocol, iface);
}
/* Continue requesting reports */