improve memory management & polling

This commit is contained in:
2025-08-20 21:30:22 -04:00
parent 5b3a5beb32
commit a1e1ff70fc
13 changed files with 195 additions and 151 deletions
+2 -2
View File
@@ -15,7 +15,7 @@ target_sources(${PROJECT} PRIVATE
bt_device.c bt_device.c
hid_report.c hid_report.c
main.c main.c
#usb_descriptors.c usb_descriptors.c
usb_device.c usb_device.c
usb_host.c usb_host.c
) )
@@ -38,7 +38,7 @@ target_link_libraries(${PROJECT} PRIVATE
pico_pio_usb pico_pio_usb
pico_stdlib pico_stdlib
tinyusb_board tinyusb_board
#tinyusb_device tinyusb_device
tinyusb_host tinyusb_host
tinyusb_pico_pio_usb tinyusb_pico_pio_usb
) )
+33 -21
View File
@@ -26,6 +26,7 @@ static btstack_packet_callback_registration_t l2cap_event_callback_registration;
static btstack_packet_callback_registration_t sm_event_callback_registration; static btstack_packet_callback_registration_t sm_event_callback_registration;
static uint8_t battery = 100; static uint8_t battery = 100;
hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID; hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID;
uint16_t conn_interval=1000;
static uint8_t protocol_mode = 1; static uint8_t protocol_mode = 1;
static hids_device_report_t *dev_report_storage; static hids_device_report_t *dev_report_storage;
@@ -76,7 +77,7 @@ static void bt_hid_setup(void) {
// setup HID Device service // setup HID Device service
dev_report_storage = (hids_device_report_t *)malloc(sizeof(hids_device_report_t)*NUM_REPORT_IDS); dev_report_storage = (hids_device_report_t *)malloc(sizeof(hids_device_report_t)*NUM_REPORT_IDS);
hids_device_init_with_storage(0, get_desc_hid_report(), get_desc_hid_report_len(), NUM_REPORT_IDS, dev_report_storage); hids_device_init_with_storage(0, desc_hid_report, desc_hid_report_len, NUM_REPORT_IDS, dev_report_storage);
// setup advertisements // setup advertisements
uint16_t adv_int_min = 0x0030; uint16_t adv_int_min = 0x0030;
@@ -109,48 +110,56 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
(void) channel; (void) channel;
(void) size; (void) size;
uint16_t conn_interval;
if (packet_type != HCI_EVENT_PACKET) return; if (packet_type != HCI_EVENT_PACKET) return;
switch (hci_event_packet_get_type(packet)) { switch (hci_event_packet_get_type(packet)) {
case HCI_EVENT_DISCONNECTION_COMPLETE: case HCI_EVENT_DISCONNECTION_COMPLETE:
con_handle = HCI_CON_HANDLE_INVALID; con_handle = HCI_CON_HANDLE_INVALID;
printf("Disconnected\n"); cdc_print_msg("Disconnected\n");
set_host_state(HOST_STOP_LISTEN); host_state=HOST_STOP_LISTEN;
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0); cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
break; break;
case SM_EVENT_JUST_WORKS_REQUEST: case SM_EVENT_JUST_WORKS_REQUEST:
printf("Just Works requested\n"); cdc_print_msg("Just Works requested\n");
sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); sm_just_works_confirm(sm_event_just_works_request_get_handle(packet));
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0); cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
break; break;
case SM_EVENT_NUMERIC_COMPARISON_REQUEST: case SM_EVENT_NUMERIC_COMPARISON_REQUEST:
printf("Confirming numeric comparison: %"PRIu32"\n", sm_event_numeric_comparison_request_get_passkey(packet)); cdc_count = sprintf(cdc_buf, "Confirming numeric comparison: %"PRIu32"\n", sm_event_numeric_comparison_request_get_passkey(packet));
cdc_print_str(cdc_buf, cdc_count);
sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet)); sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet));
break; break;
case SM_EVENT_PASSKEY_DISPLAY_NUMBER: case SM_EVENT_PASSKEY_DISPLAY_NUMBER:
printf("Display Passkey: %"PRIu32"\n", sm_event_passkey_display_number_get_passkey(packet)); cdc_count = sprintf(cdc_buf, "Display Passkey: %"PRIu32"\n", sm_event_passkey_display_number_get_passkey(packet));
cdc_print_str(cdc_buf, cdc_count);
break; break;
case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE:
printf("L2CAP Connection Parameter Update Complete, response: %x\n", l2cap_event_connection_parameter_update_response_get_result(packet)); cdc_count = sprintf(cdc_buf, "L2CAP Connection Parameter Update Complete, response: %x\n", l2cap_event_connection_parameter_update_response_get_result(packet));
cdc_print_str(cdc_buf, cdc_count);
break; break;
case HCI_EVENT_LE_META: case HCI_EVENT_LE_META:
switch (hci_event_le_meta_get_subevent_code(packet)) { switch (hci_event_le_meta_get_subevent_code(packet)) {
case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: case HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
// print connection parameters (without using float operations) // print connection parameters (without using float operations)
conn_interval = hci_subevent_le_connection_complete_get_conn_interval(packet); conn_interval = hci_subevent_le_connection_complete_get_conn_interval(packet);
printf("LE Connection Complete:\n"); set_host_poll_interval(conn_interval);
printf("- Connection Interval: %u.%02u ms\n", conn_interval * 125 / 100, 25 * (conn_interval & 3)); cdc_print_msg("LE Connection Complete:\n");
printf("- Connection Latency: %u\n", hci_subevent_le_connection_complete_get_conn_latency(packet)); cdc_count = sprintf(cdc_buf, "- Connection Interval: %u.%02u ms\n", conn_interval * 125 / 100, 25 * (conn_interval & 3));
cdc_print_str(cdc_buf, cdc_count);
cdc_count = sprintf(cdc_buf, "- Connection Latency: %u\n", hci_subevent_le_connection_complete_get_conn_latency(packet));
cdc_print_str(cdc_buf, cdc_count);
break; break;
case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE:
// print connection parameters (without using float operations) // print connection parameters (without using float operations)
conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet);
printf("LE Connection Update:\n"); set_host_poll_interval(conn_interval);
printf("- Connection Interval: %u.%02u ms\n", conn_interval * 125 / 100, 25 * (conn_interval & 3)); cdc_print_msg("LE Connection Update:\n");
printf("- Connection Latency: %u\n", hci_subevent_le_connection_update_complete_get_conn_latency(packet)); cdc_count = sprintf(cdc_buf, "- Connection Interval: %u.%02u ms\n", conn_interval * 125 / 100, 25 * (conn_interval & 3));
cdc_print_str(cdc_buf, cdc_count);
cdc_count = sprintf(cdc_buf, "- Connection Latency: %u\n", hci_subevent_le_connection_update_complete_get_conn_latency(packet));
cdc_print_str(cdc_buf, cdc_count);
break; break;
default: default:
break; break;
@@ -160,9 +169,10 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
switch (hci_event_hids_meta_get_subevent_code(packet)){ switch (hci_event_hids_meta_get_subevent_code(packet)){
case HIDS_SUBEVENT_INPUT_REPORT_ENABLE: case HIDS_SUBEVENT_INPUT_REPORT_ENABLE:
con_handle = hids_subevent_input_report_enable_get_con_handle(packet); con_handle = hids_subevent_input_report_enable_get_con_handle(packet);
printf("Report Characteristic Subscribed %u\n", hids_subevent_input_report_enable_get_enable(packet)); cdc_count = sprintf(cdc_buf, "Report Characteristic Subscribed %u\n", hids_subevent_input_report_enable_get_enable(packet));
cdc_print_str(cdc_buf, cdc_count);
set_host_state(HOST_START_LISTEN); host_state=HOST_START_LISTEN;
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1); cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
// request connection param update via L2CAP following Apple Bluetooth Design Guidelines // request connection param update via L2CAP following Apple Bluetooth Design Guidelines
// gap_request_connection_parameter_update(con_handle, 12, 12, 4, 100); // 15 ms, 4, 1s // gap_request_connection_parameter_update(con_handle, 12, 12, 4, 100); // 15 ms, 4, 1s
@@ -173,10 +183,11 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
break; break;
case HIDS_SUBEVENT_PROTOCOL_MODE: case HIDS_SUBEVENT_PROTOCOL_MODE:
protocol_mode = hids_subevent_protocol_mode_get_protocol_mode(packet); protocol_mode = hids_subevent_protocol_mode_get_protocol_mode(packet);
printf("Protocol Mode: %s mode\n", hids_subevent_protocol_mode_get_protocol_mode(packet) ? "Report" : "Boot"); cdc_count = sprintf(cdc_buf, "Protocol Mode: %s mode\n", hids_subevent_protocol_mode_get_protocol_mode(packet) ? "Report" : "Boot");
cdc_print_str(cdc_buf, cdc_count);
break; break;
case HIDS_SUBEVENT_CAN_SEND_NOW: case HIDS_SUBEVENT_CAN_SEND_NOW:
printf("HIDS_SUBEVENT_CAN_SEND_NOW\n"); //cdc_print_msg("HIDS_SUBEVENT_CAN_SEND_NOW\n");
send_report(); send_report();
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1-cyw43_arch_gpio_get(CYW43_WL_GPIO_LED_PIN)); cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1-cyw43_arch_gpio_get(CYW43_WL_GPIO_LED_PIN));
break; break;
@@ -194,9 +205,10 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
void update_desc_hid_report(void) { void update_desc_hid_report(void) {
hci_power_control(HCI_POWER_OFF); hci_power_control(HCI_POWER_OFF);
uint16_t len = get_desc_hid_report_len(); if (desc_hid_report_len>0) {
if (len>0) { //cdc_print_msg("Update HID report descriptor: ");
hids_device_init_with_storage(0, get_desc_hid_report(), len, NUM_REPORT_IDS, dev_report_storage); //cdc_print_hex(desc_hid_report, desc_hid_report_len);
hids_device_init_with_storage(0, desc_hid_report, desc_hid_report_len, NUM_REPORT_IDS, dev_report_storage);
hci_power_control(HCI_POWER_ON); hci_power_control(HCI_POWER_ON);
} }
} }
+2
View File
@@ -1,6 +1,8 @@
#ifndef BT_DEVICE_H_ #ifndef BT_DEVICE_H_
#define BT_DEVICE_H_ #define BT_DEVICE_H_
extern uint16_t conn_interval;
void btstack_main(void); void btstack_main(void);
void update_desc_hid_report(void); void update_desc_hid_report(void);
-3
View File
@@ -86,7 +86,4 @@
// To get the audio demos working even with HCI dump at 115200, this truncates long ACL packets // To get the audio demos working even with HCI dump at 115200, this truncates long ACL packets
//#define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100 //#define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100
// enable larger HID descriptor
#define MAX_ATTRIBUTE_VALUE_SIZE 512
#endif // _PICO_BTSTACK_BTSTACK_CONFIG_H #endif // _PICO_BTSTACK_BTSTACK_CONFIG_H
+44 -38
View File
@@ -11,14 +11,19 @@
#include "usb_device.h" #include "usb_device.h"
#include "usb_host.h" #include "usb_host.h"
#include "bt_device.h"
#include "hid_report.h" #include "hid_report.h"
extern hci_con_handle_t con_handle;
uint8_t desc_hid_report[HID_DESCRIPTOR_SIZE];
uint16_t desc_hid_report_len=0;
static uint8_t buffer_storage[REPORT_BUF_SIZE]; static uint8_t buffer_storage[REPORT_BUF_SIZE];
static btstack_ring_buffer_t report_buf; static btstack_ring_buffer_t report_buf;
static uint8_t desc_hid_report[HID_DESCRIPTOR_SIZE]; static struct report_data *report;
static uint16_t desc_hid_report_len=0;
static struct report_desc *descriptors; static struct report_desc *descriptors;
static struct report_desc* report_desc_alloc(void); static struct report_desc* report_desc_alloc(void);
@@ -30,8 +35,6 @@ static void report_dict_init(struct report_dict *mapping);
static void report_dict_free(struct report_dict *mapping, struct report_desc *descriptor); static void report_dict_free(struct report_dict *mapping, struct report_desc *descriptor);
static struct report_dict* find_mapping(uint8_t dev_addr, uint8_t instance, uint8_t report_id); static struct report_dict* find_mapping(uint8_t dev_addr, uint8_t instance, uint8_t report_id);
extern hci_con_handle_t con_handle;
// start listening to HID input reports on all mounted devices // start listening to HID input reports on all mounted devices
bool request_hid_reports_all(void) { bool request_hid_reports_all(void) {
// send request to receive reports on all mounted devices // send request to receive reports on all mounted devices
@@ -39,15 +42,18 @@ bool request_hid_reports_all(void) {
for (current=descriptors; current != NULL; current=current->next) { for (current=descriptors; current != NULL; current=current->next) {
if (! current->listening) { if (! current->listening) {
if(request_hid_report(current->dev_addr, current->instance)) { if(request_hid_report(current->dev_addr, current->instance)) {
char tempbuf[40]; cdc_count = sprintf(cdc_buf, "Listening to input reports on [%u:%u]\n", current->dev_addr, current->instance);
size_t count = sprintf(tempbuf, "Listening to input reports on [%u:%u]\n", current->dev_addr, current->instance); cdc_print_str(cdc_buf, cdc_count);
cdc_print_str(tempbuf, count);
current->listening = true; current->listening = true;
} else { } else {
cdc_print_msg("Error listening to input report(s)\n");
stop_hid_reports_all();
return false; return false;
} }
} }
} }
host_state = HOST_LISTENING;
return true; return true;
} }
@@ -58,15 +64,17 @@ bool stop_hid_reports_all(void) {
for (current=descriptors; current != NULL; current=current->next) { for (current=descriptors; current != NULL; current=current->next) {
if (current->listening) { if (current->listening) {
if(stop_hid_report(current->dev_addr, current->instance)) { if(stop_hid_report(current->dev_addr, current->instance)) {
char tempbuf[40]; cdc_count = sprintf(cdc_buf, "Stopping input reports on [%u:%u]\n", current->dev_addr, current->instance);
size_t count = sprintf(tempbuf, "Stopping input reports on [%u:%u]\n", current->dev_addr, current->instance); cdc_print_str(cdc_buf, cdc_count);
cdc_print_str(tempbuf, count);
current->listening = false; current->listening = false;
} else { } else {
cdc_print_msg("Error stopping input report(s)\n");
return false; return false;
} }
} }
} }
host_state = HOST_INACTIVE;
return true; return true;
} }
@@ -74,47 +82,48 @@ bool stop_hid_reports_all(void) {
void send_report(){ void send_report(){
// process queue and send next report // process queue and send next report
if (btstack_ring_buffer_bytes_available(&report_buf)) { if (btstack_ring_buffer_bytes_available(&report_buf)) {
uint8_t dev_addr;
uint8_t instance;
uint8_t len8[2]; uint8_t len8[2];
uint16_t len;
uint32_t num_bytes_read; uint32_t num_bytes_read;
// retrieve dev_addr from ring_buffer // retrieve dev_addr from ring_buffer
btstack_ring_buffer_read(&report_buf, &dev_addr, 1, &num_bytes_read); btstack_ring_buffer_read(&report_buf, &report->dev_addr, 1, &num_bytes_read);
// retrieve instance from ring buffer // retrieve instance from ring buffer
btstack_ring_buffer_read(&report_buf, &instance, 1, &num_bytes_read); btstack_ring_buffer_read(&report_buf, &report->instance, 1, &num_bytes_read);
// retrieve length as two uint8_t and turn into uint16_t // retrieve length as two uint8_t and turn into uint16_t
btstack_ring_buffer_read(&report_buf, len8, 2, &num_bytes_read); btstack_ring_buffer_read(&report_buf, len8, 2, &num_bytes_read);
memcpy(&len, len8, 2); memcpy(&report->len, len8, 2);
// retrieve report from ring buffer // retrieve report from ring buffer
uint8_t report[len]; btstack_ring_buffer_read(&report_buf, report->report, report->len, &num_bytes_read);
btstack_ring_buffer_read(&report_buf, report, len, &num_bytes_read);
// find report id mapping // find report id mapping
struct report_dict * mapping = find_mapping(dev_addr, instance, report[0]); struct report_dict * mapping = find_mapping(report->dev_addr, report->instance, report->report[0]);
char tempbuf[16]; cdc_count=sprintf(cdc_buf, "[%04x](%u)> ", con_handle, mapping->ble_id);
size_t count=sprintf(tempbuf, "[%04x](%u) ", con_handle, mapping->ble_id); cdc_print_str(cdc_buf, cdc_count);
cdc_print_str(tempbuf, count);
// send hid report to ble interface // send hid report to ble interface
if (mapping != NULL) { if (mapping != NULL) {
if (mapping->report_id==0) { if (mapping->report_id==0) {
hids_device_send_input_report_for_id(con_handle, mapping->ble_id, report, len); hids_device_send_input_report_for_id(con_handle, mapping->ble_id, report->report, report->len);
cdc_print_hex(report, len); cdc_print_hex(report->report, report->len);
} else { } else {
// replace report ID in original report before sending // replace report ID in original report before sending
hids_device_send_input_report_for_id(con_handle, mapping->ble_id, &report[1], len-1); hids_device_send_input_report_for_id(con_handle, mapping->ble_id, &report->report[1], report->len-1);
cdc_print_hex(&report[1], len-1); cdc_print_hex(&report->report[1], report->len-1);
} }
} }
// request send of next report // set host to poll USB
hids_device_request_can_send_now_event(con_handle); if (host_state == HOST_WAIT_POLL) {
host_state = HOST_POLL;
}
// request sending of next report
if (btstack_ring_buffer_bytes_available(&report_buf)) {
hids_device_request_can_send_now_event(con_handle);
}
} }
} }
@@ -125,7 +134,7 @@ void queue_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uin
uint8_t len8[2]; uint8_t len8[2];
memcpy(len8, &len, 2); memcpy(len8, &len, 2);
if (btstack_ring_buffer_bytes_free(&report_buf) >= len+4) { if (btstack_ring_buffer_bytes_free(&report_buf) >= len+5) {
// put instance, length, and report into ring buffer if space available // put instance, length, and report into ring buffer if space available
btstack_ring_buffer_write(&report_buf, &dev_addr, 1); btstack_ring_buffer_write(&report_buf, &dev_addr, 1);
btstack_ring_buffer_write(&report_buf, &instance, 1); btstack_ring_buffer_write(&report_buf, &instance, 1);
@@ -136,11 +145,17 @@ void queue_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uin
// request send on BLE HID interface // request send on BLE HID interface
hids_device_request_can_send_now_event(con_handle); hids_device_request_can_send_now_event(con_handle);
} }
// HID report on device has not been requested, flag so it can be polled
struct report_desc * descriptor;
descriptor = report_desc_find(dev_addr, instance);
descriptor->listening = false;
} }
// allocate memory for HID report ring buffer // allocate memory for HID report ring buffer
void init_report_buf(void) { void init_report_buf(void) {
btstack_ring_buffer_init(&report_buf, buffer_storage, sizeof(buffer_storage)); btstack_ring_buffer_init(&report_buf, buffer_storage, sizeof(buffer_storage));
report = REPORT_DATA_ALLOC();
} }
// allocate memory for USB interface report descriptor // allocate memory for USB interface report descriptor
@@ -358,12 +373,3 @@ static struct report_dict * find_mapping(uint8_t dev_addr, uint8_t instance, uin
return NULL; return NULL;
} }
uint16_t get_desc_hid_report_len(void) {
return desc_hid_report_len;
}
uint8_t const* get_desc_hid_report(void) {
return desc_hid_report;
}
+14 -4
View File
@@ -1,6 +1,7 @@
#ifndef HID_REPORT_H_ #ifndef HID_REPORT_H_
#define HID_REPORT_H_ #define HID_REPORT_H_
#define REPORT_MAX_SIZE 64
#define NUM_REPORT_IDS 16 #define NUM_REPORT_IDS 16
#define REPORT_BUF_SIZE 256 #define REPORT_BUF_SIZE 256
#define DESCRIPTOR_BUF_SIZE 256 #define DESCRIPTOR_BUF_SIZE 256
@@ -22,8 +23,19 @@ struct report_dict {
struct report_dict *next; struct report_dict *next;
}; };
# define REPORT_DESC_ALLOC() (struct report_desc *)malloc(sizeof(struct report_desc)) struct report_data {
# define REPORT_DICT_ALLOC() (struct report_dict *)malloc(sizeof(struct report_dict)) uint8_t dev_addr;
uint8_t instance;
uint8_t report[REPORT_MAX_SIZE];
uint16_t len;
};
#define REPORT_DESC_ALLOC() (struct report_desc *)malloc(sizeof(struct report_desc))
#define REPORT_DICT_ALLOC() (struct report_dict *)malloc(sizeof(struct report_dict))
#define REPORT_DATA_ALLOC() (struct report_data *)malloc(sizeof(struct report_data))
extern uint8_t desc_hid_report[HID_DESCRIPTOR_SIZE];
extern uint16_t desc_hid_report_len;
bool request_hid_reports_all(void); bool request_hid_reports_all(void);
bool stop_hid_reports_all(void); bool stop_hid_reports_all(void);
@@ -33,7 +45,5 @@ void init_report_buf(void);
bool add_descriptor(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len); bool add_descriptor(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len);
void remove_instance(uint8_t dev_addr, uint8_t instance); void remove_instance(uint8_t dev_addr, uint8_t instance);
bool generate_report_descriptor(void); bool generate_report_descriptor(void);
uint16_t get_desc_hid_report_len(void);
uint8_t const* get_desc_hid_report(void);
#endif #endif
+21 -31
View File
@@ -12,61 +12,51 @@
#include "usb_device.h" #include "usb_device.h"
#include "usb_host.h" #include "usb_host.h"
static void usb_main(void);
// main loop // main loop
int main(void) { int main(void) {
set_sys_clock_khz(192000, true); set_sys_clock_khz(144000, true);
sleep_ms(10); sleep_ms(10);
// setup BLE on core 1 // run BLE on core 1
multicore_reset_core1(); multicore_reset_core1();
multicore_launch_core1(btstack_main); multicore_launch_core1(btstack_main);
// run usb on core 0
usb_main();
return 0;
}
static void usb_main(void) {
// init and run usb host // init and run usb host
usb_host_init(); usb_host_init();
// init and run usb device // init and run usb device
//usb_device_init(); usb_device_init();
while (true) { while (true) {
switch ( get_host_state() ) { switch ( host_state ) {
case HOST_NEW_DESCRIPTOR: case HOST_NEW_DESCRIPTOR:
if ( host_ready() ) { host_ready();
if(generate_report_descriptor()) {
if ( get_desc_hid_report_len() > 0 ) {
set_host_state(HOST_MOUNTED);
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
} else {
set_host_state(HOST_INACTIVE);
}
cdc_print_msg("Updating HID report map\n");
update_desc_hid_report();
}
}
break; break;
case HOST_START_LISTEN: case HOST_START_LISTEN:
if (request_hid_reports_all()) { request_hid_reports_all();
set_host_state(HOST_LISTENING);
} else {
cdc_print_msg("Error listening to input report(s)\n");
set_host_state(HOST_INACTIVE);
}
break; break;
case HOST_STOP_LISTEN: case HOST_STOP_LISTEN:
if (stop_hid_reports_all()) { stop_hid_reports_all();
set_host_state(HOST_INACTIVE); break;
} else { case HOST_POLL:
cdc_print_msg("Error stopping input report(s)\n"); poll_devices();
}
break; break;
default: default:
break; break;
} }
tuh_task(); // tinyusb host task tuh_task(); // tinyusb host task
//tud_task(); // tinyusb device task tud_task(); // tinyusb device task
//tud_cdc_write_flush(); tud_cdc_write_flush();
} }
return 0;
} }
+5 -6
View File
@@ -39,8 +39,7 @@
#endif #endif
// Enable device stack // Enable device stack
//#define CFG_TUD_ENABLED 1 #define CFG_TUD_ENABLED 1
#define CFG_TUD_ENABLED 0
// Enable host stack // Enable host stack
#define CFG_TUH_ENABLED 1 #define CFG_TUH_ENABLED 1
@@ -89,10 +88,10 @@
// CDC FIFO size of TX and RX // CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE 32 #define CFG_TUD_CDC_RX_BUFSIZE 32
#define CFG_TUD_CDC_TX_BUFSIZE 64 #define CFG_TUD_CDC_TX_BUFSIZE 128
// CDC Endpoint transfer buffer size, more is faster // CDC Endpoint transfer buffer size, more is faster
#define CFG_TUD_CDC_EP_BUFSIZE 64 #define CFG_TUD_CDC_EP_BUFSIZE 128
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// HOST CONFIGURATION // HOST CONFIGURATION
@@ -122,8 +121,8 @@
#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB*3+1) // hub typically has 4 ports #define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB*3+1) // hub typically has 4 ports
#define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX+1) #define CFG_TUH_HID (3*CFG_TUH_DEVICE_MAX+1)
#define CFG_TUH_HID_EPIN_BUFSIZE 64 #define CFG_TUH_HID_EPIN_BUFSIZE 128
#define CFG_TUH_HID_EPOUT_BUFSIZE 64 #define CFG_TUH_HID_EPOUT_BUFSIZE 128
#ifdef __cplusplus #ifdef __cplusplus
} }
+1
View File
@@ -100,6 +100,7 @@ char const* string_desc_arr [] =
"Raspberry Pi", // 1: Manufacturer "Raspberry Pi", // 1: Manufacturer
"Pico BLE HID", // 2: Product "Pico BLE HID", // 2: Product
NULL, // 3: Serials, should use chip ID NULL, // 3: Serials, should use chip ID
"Pico BLE HID CDC", // 4: Product
}; };
static uint16_t _desc_str[32+1]; static uint16_t _desc_str[32+1];
+10 -8
View File
@@ -9,6 +9,10 @@
#include "usb_device.h" #include "usb_device.h"
char cdc_buf[64];
uint16_t cdc_len;
size_t cdc_count;
void usb_device_init(void) { void usb_device_init(void) {
// run TinyUSB device // run TinyUSB device
tusb_rhport_init_t dev_init = { tusb_rhport_init_t dev_init = {
@@ -46,23 +50,21 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t
void cdc_print_hex(uint8_t const* msg, uint16_t msg_len) { void cdc_print_hex(uint8_t const* msg, uint16_t msg_len) {
(void) msg; (void) msg;
(void) msg_len; (void) msg_len;
/*char tempbuf[8];
size_t count;
for (int i=0; i<msg_len; i++) { for (int i=0; i<msg_len; i++) {
count=sprintf(tempbuf, "%02X ", msg[i]); cdc_count=sprintf(cdc_buf, "%02X ", msg[i]);
tud_cdc_write(tempbuf, count); tud_cdc_write(cdc_buf, cdc_count);
} }
tud_cdc_write_str("\n");*/ tud_cdc_write_str("\n");
} }
// print text message to CDC // print text message to CDC
void cdc_print_str(char const* msg, uint16_t msg_len) { void cdc_print_str(char const* msg, uint16_t msg_len) {
(void) msg; (void) msg;
(void) msg_len; (void) msg_len;
//tud_cdc_write(msg, msg_len); tud_cdc_write(msg, msg_len);
} }
void cdc_print_msg(char const* msg) { void cdc_print_msg(char const* msg) {
uint16_t msg_len = strlen(msg); cdc_len = strlen(msg);
cdc_print_str(msg, msg_len); cdc_print_str(msg, cdc_len);
} }
+6 -2
View File
@@ -1,5 +1,9 @@
#ifndef MAIN_DEVICE_H_ #ifndef USB_DEVICE_H_
#define MAIN_DEVICE_H_ #define USB_DEVICE_H_
extern char cdc_buf[64];
extern uint16_t cdc_len;
extern size_t cdc_count;
void usb_device_init(void); void usb_device_init(void);
void cdc_print_hex(uint8_t const* msg, uint16_t msg_len); void cdc_print_hex(uint8_t const* msg, uint16_t msg_len);
+47 -31
View File
@@ -11,11 +11,14 @@
#include "hid_report.h" #include "hid_report.h"
#include "usb_device.h" #include "usb_device.h"
#include "bt_device.h"
#include "usb_host.h" #include "usb_host.h"
static host_state_t host_state; host_state_t host_state;
static absolute_time_t request_time; static absolute_time_t request_time;
static absolute_time_t last_report;
static uint16_t host_poll_interval=8000;
// initialize usb host // initialize usb host
void usb_host_init(void) { void usb_host_init(void) {
@@ -32,7 +35,7 @@ void usb_host_init(void) {
tuh_hid_set_default_protocol(HID_PROTOCOL_REPORT); tuh_hid_set_default_protocol(HID_PROTOCOL_REPORT);
tusb_init(BOARD_TUH_RHPORT, &host_init); tusb_init(BOARD_TUH_RHPORT, &host_init);
set_host_state(HOST_INACTIVE); host_state=HOST_INACTIVE;
} }
@@ -44,16 +47,12 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
/// send device vid:pid information to CDC for debugging /// send device vid:pid information to CDC for debugging
char tempbuf[CFG_TUD_CDC_TX_BUFSIZE]; cdc_count = sprintf(cdc_buf, "Mount: [%04x:%04x][%u:%u] Protocol = %u\n", vid, pid, dev_addr, instance, itf_protocol);
size_t count = sprintf(tempbuf, "Mount: [%04x:%04x][%u:%u] Protocol = %u\n", vid, pid, dev_addr, instance, itf_protocol); cdc_print_str(cdc_buf, cdc_count);
cdc_print_str(tempbuf, count);
// print descriptor
//cdc_print_hex(desc_report, desc_len);
// add to HID report descriptor // add to HID report descriptor
if ( add_descriptor(dev_addr, instance, desc_report, desc_len)) { if ( add_descriptor(dev_addr, instance, desc_report, desc_len)) {
set_host_state(HOST_NEW_DESCRIPTOR); host_state=HOST_NEW_DESCRIPTOR;
request_time=get_absolute_time(); request_time=get_absolute_time();
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0); cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 0);
} }
@@ -63,58 +62,75 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
{ {
// send device address:instance to CDC for debugging // send device address:instance to CDC for debugging
char tempbuf[CFG_TUD_CDC_TX_BUFSIZE]; cdc_count = sprintf(cdc_buf, "Unmount: [%u:%u]\n", dev_addr, instance);
size_t count = sprintf(tempbuf, "Unmount: [%u:%u]\n", dev_addr, instance); cdc_print_str(cdc_buf, cdc_count);
cdc_print_str(tempbuf, count);
if (stop_hid_report(dev_addr, instance)) { if (stop_hid_report(dev_addr, instance)) {
cdc_print_msg("Successfully stopped receiving reports\n"); cdc_print_msg("Successfully stopped receiving reports\n");
} }
remove_instance(dev_addr, instance); remove_instance(dev_addr, instance);
set_host_state(HOST_NEW_DESCRIPTOR); host_state=HOST_NEW_DESCRIPTOR;
request_time=get_absolute_time(); request_time=get_absolute_time();
} }
// Invoked when received report from device via interrupt endpoint // Invoked when received report from device via interrupt endpoint
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{ {
char tempbuf[32]; cdc_count = sprintf(cdc_buf, "[%u:%u](%u)< ", dev_addr, instance, len);
size_t count = sprintf(tempbuf, "[%04x:%04x](%u) ", dev_addr, instance, len); cdc_print_str(cdc_buf,cdc_count);
cdc_print_str(tempbuf,count);
cdc_print_hex(report, len); cdc_print_hex(report, len);
last_report = get_absolute_time();
host_state = HOST_WAIT_POLL;
queue_report(dev_addr, instance, report, len); queue_report(dev_addr, instance, report, len);
// continue to request to receive report // continue to request to receive report
if ( !tuh_hid_receive_report(dev_addr, instance) ) /*if ( !tuh_hid_receive_report(dev_addr, instance) )
{ {
cdc_print_msg("Error: cannot request report\r\n"); cdc_print_msg("Error: cannot request report\r\n");
}*/
}
// get host ready by updating descriptors
void host_ready(void) {
if (absolute_time_diff_us(request_time, get_absolute_time()) >= 1000000){
if(generate_report_descriptor()) {
if ( desc_hid_report_len > 0 ) {
host_state=HOST_MOUNTED;
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
} else {
host_state=HOST_INACTIVE;
}
cdc_print_msg("Updating HID report map\n");
update_desc_hid_report();
}
} }
} }
// set the state of the host // set devices to listening once polling interval has passed
void set_host_state(host_state_t new_host_state) { void poll_devices(void) {
host_state = new_host_state; if (absolute_time_diff_us(last_report, get_absolute_time()) >= host_poll_interval) {
request_hid_reports_all();
host_state = HOST_LISTENING;
}
} }
// get the current state of the host // set the USB host polling interval based on the BT connection interval
host_state_t get_host_state(void) { void set_host_poll_interval(uint16_t bt_conn_interval) {
return host_state; if (bt_conn_interval*1250 > HOST_POLL_INTERVAL) {
} host_poll_interval = bt_conn_interval*1250;
} else {
// indicate whether host is ready for updating descriptors host_poll_interval = HOST_POLL_INTERVAL;
bool host_ready(void) { }
return (absolute_time_diff_us(request_time, get_absolute_time()) > 1000000);
} }
// request HID input reports on specified device address and instance // request HID input reports on specified device address and instance
bool request_hid_report(uint8_t dev_addr, uint8_t instance) { bool request_hid_report(uint8_t dev_addr, uint8_t instance) {
// request to receive reports HID devices // request to receive reports HID devices
if ( !tuh_hid_receive_report(dev_addr, instance) ) { if ( !tuh_hid_receive_report(dev_addr, instance) ) {
char tempbuf[CFG_TUD_CDC_TX_BUFSIZE]; cdc_count = sprintf(cdc_buf, "Error: cannot request report on [%u:%u]\n", dev_addr, instance);
size_t count = sprintf(tempbuf, "Error: cannot request report on [%u:%u]\n", dev_addr, instance); cdc_print_str(cdc_buf, cdc_count);
cdc_print_str(tempbuf, count);
return false; return false;
} }
return true; return true;
+10 -5
View File
@@ -1,5 +1,7 @@
#ifndef MAIN_HOST_H_ #ifndef USB_HOST_H_
#define MAIN_HOST_H_ #define USB_HOST_H_
#define HOST_POLL_INTERVAL 25000
typedef enum { typedef enum {
HOST_INACTIVE=0, HOST_INACTIVE=0,
@@ -7,14 +9,17 @@ typedef enum {
HOST_MOUNTED, HOST_MOUNTED,
HOST_START_LISTEN, HOST_START_LISTEN,
HOST_LISTENING, HOST_LISTENING,
HOST_WAIT_POLL,
HOST_POLL,
HOST_STOP_LISTEN, HOST_STOP_LISTEN,
} host_state_t; } host_state_t;
extern host_state_t host_state;
void usb_host_init(void); void usb_host_init(void);
void set_host_state(host_state_t new_host_state); void host_ready(void);
host_state_t get_host_state(void); void poll_devices(void);
bool host_ready(void); void set_host_poll_interval(uint16_t bt_conn_interval);
bool request_hid_report(uint8_t dev_addr, uint8_t instance); bool request_hid_report(uint8_t dev_addr, uint8_t instance);
bool stop_hid_report(uint8_t dev_addr, uint8_t instance); bool stop_hid_report(uint8_t dev_addr, uint8_t instance);