Compare commits
3 Commits
v0.2.1
...
cb7421eab7
| Author | SHA1 | Date | |
|---|---|---|---|
|
cb7421eab7
|
|||
|
a1a0723e89
|
|||
|
c430a53755
|
+5
-1
@@ -2,7 +2,9 @@ set(PROJECT ble_hid)
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
set(PICO_SDK_PATH /home/kenji/programming/pico/c/pico-sdk)
|
set(PICO_SDK_PATH /home/kenji/programming/pico/c/pico-sdk)
|
||||||
set(PICO_PIO_USB_PATH /home/kenji/programming/pico/c/Pico-PIO-USB)
|
set(PICO_PIO_USB_PATH /home/kenji/programming/pico/c/Pico-PIO-USB)
|
||||||
set(PICO_BOARD pico_w)
|
if (NOT DEFINED PICO_BOARD)
|
||||||
|
set(PICO_BOARD pico_w)
|
||||||
|
endif()
|
||||||
include (${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
|
include (${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
|
||||||
project(${PROJECT} C CXX ASM)
|
project(${PROJECT} C CXX ASM)
|
||||||
|
|
||||||
@@ -45,5 +47,7 @@ target_link_libraries(${PROJECT} PRIVATE
|
|||||||
|
|
||||||
pico_btstack_make_gatt_header(ble_hid PRIVATE "${CMAKE_CURRENT_LIST_DIR}/ble_hid.gatt")
|
pico_btstack_make_gatt_header(ble_hid PRIVATE "${CMAKE_CURRENT_LIST_DIR}/ble_hid.gatt")
|
||||||
|
|
||||||
|
set_target_properties(${PROJECT} PROPERTIES OUTPUT_NAME "${PROJECT}-${PICO_BOARD}")
|
||||||
|
|
||||||
pico_add_extra_outputs(${PROJECT})
|
pico_add_extra_outputs(${PROJECT})
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ over BLE using HID over GATT Profile.
|
|||||||
You will need the following hardware to make the device:
|
You will need the following hardware to make the device:
|
||||||
- Raspberry Pi Pico W
|
- Raspberry Pi Pico W
|
||||||
- USB extension cable
|
- USB extension cable
|
||||||
|
- (Optional) Momentary push button
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
You will need to cut the USB extension in half and connect the wires from the
|
You will need to cut the USB extension in half and connect the wires from the
|
||||||
female end to the Raspberry Pi Pico W. The default configuration is to attach
|
female end to the Raspberry Pi Pico W. The default configuration is to attach
|
||||||
@@ -32,6 +34,10 @@ respectively. For the data wires, you can solder them to the two test points
|
|||||||
TP2 and TP3 on the back of the Raspberry Pi Pico. The white cable goes to TP2
|
TP2 and TP3 on the back of the Raspberry Pi Pico. The white cable goes to TP2
|
||||||
and the green cable to TP3.
|
and the green cable to TP3.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Optionally, a momentary push button can be wired to GP5 and GND to switch between Bluetooth and USB passthrough mode.
|
||||||
|
|
||||||
The individual wires on the USB can be fragile, so hot glue or other strain
|
The individual wires on the USB can be fragile, so hot glue or other strain
|
||||||
relief is a good idea.
|
relief is a good idea.
|
||||||
|
|
||||||
@@ -61,6 +67,11 @@ with many LEDs, the sudden power draw when plugging in can cause issues, so it
|
|||||||
is recommended to turn off the LEDs before connecting to the Raspberry Pi Pico
|
is recommended to turn off the LEDs before connecting to the Raspberry Pi Pico
|
||||||
W.
|
W.
|
||||||
|
|
||||||
|
If you connected a push button to GP5, then pressing the button will switch
|
||||||
|
between Bluetooth connection mode and USB passthrough mode. In USB passthrough
|
||||||
|
mode, the inputs will be passed through from the host to the USB connection made
|
||||||
|
through the test points or the Micro USB port.
|
||||||
|
|
||||||
In principle, the Pico BLE HID will work with peripherals plugged into
|
In principle, the Pico BLE HID will work with peripherals plugged into
|
||||||
a USB hub, but compatibility will vary with the specific hardware used,
|
a USB hub, but compatibility will vary with the specific hardware used,
|
||||||
including the peripherals, USB hub, and operating system. This is because the
|
including the peripherals, USB hub, and operating system. This is because the
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef BLEHID_CONFIG_H_
|
||||||
|
#define BLEHID_CONFIG_H_
|
||||||
|
|
||||||
|
#define BUTTON_PIN 5
|
||||||
|
#define BUTTON_DEBOUNCE 20000
|
||||||
|
#define BUTTON_LONG_PRESS 3000000
|
||||||
|
|
||||||
|
#endif
|
||||||
+23
-12
@@ -28,6 +28,8 @@ 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;
|
uint16_t conn_interval=1000;
|
||||||
static uint8_t protocol_mode = 1;
|
static uint8_t protocol_mode = 1;
|
||||||
|
bt_state_t bt_state;
|
||||||
|
bt_device_command_t bt_device_command;
|
||||||
|
|
||||||
static hids_device_report_t *dev_report_storage;
|
static hids_device_report_t *dev_report_storage;
|
||||||
|
|
||||||
@@ -109,14 +111,20 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
|||||||
(void) size;
|
(void) size;
|
||||||
|
|
||||||
|
|
||||||
if (packet_type != HCI_EVENT_PACKET) return;
|
if (packet_type != HCI_EVENT_PACKET) {
|
||||||
|
cdc_count = sprintf(cdc_buf, "Unexpected packet type %02X\n", packet_type);
|
||||||
|
cdc_print_str(cdc_buf, cdc_count);
|
||||||
|
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;
|
||||||
cdc_print_msg("Disconnected\n");
|
cdc_print_msg("Disconnected\n");
|
||||||
|
|
||||||
host_state=HOST_STOP_LISTEN;
|
if ( device_state == DEVICE_INACTIVE) {
|
||||||
|
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:
|
||||||
@@ -133,6 +141,8 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
|||||||
cdc_count = sprintf(cdc_buf, "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);
|
cdc_print_str(cdc_buf, cdc_count);
|
||||||
break;
|
break;
|
||||||
|
case SM_EVENT_IDENTITY_RESOLVING_STARTED:
|
||||||
|
break;
|
||||||
case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE:
|
case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE:
|
||||||
cdc_count = sprintf(cdc_buf, "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);
|
cdc_print_str(cdc_buf, cdc_count);
|
||||||
@@ -160,6 +170,8 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
|||||||
cdc_print_str(cdc_buf, cdc_count);
|
cdc_print_str(cdc_buf, cdc_count);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
//cdc_count = sprintf(cdc_buf,"LE packet unknown %02X\n", hci_event_le_meta_get_subevent_code(packet));
|
||||||
|
//cdc_print_str(cdc_buf, cdc_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -170,13 +182,10 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
|||||||
cdc_count = sprintf(cdc_buf, "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);
|
cdc_print_str(cdc_buf, cdc_count);
|
||||||
|
|
||||||
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 update to max 125Hz polling
|
||||||
// gap_request_connection_parameter_update(con_handle, 12, 12, 4, 100); // 15 ms, 4, 1s
|
gap_request_connection_parameter_update(con_handle, 6,6,0,100);
|
||||||
|
|
||||||
// directly update connection params via HCI following Apple Bluetooth Design Guidelines
|
|
||||||
// gap_update_connection_parameters(con_handle, 12, 12, 4, 100); // 60-75 ms, 4, 1s
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case HIDS_SUBEVENT_PROTOCOL_MODE:
|
case HIDS_SUBEVENT_PROTOCOL_MODE:
|
||||||
@@ -185,27 +194,29 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
|
|||||||
cdc_print_str(cdc_buf, cdc_count);
|
cdc_print_str(cdc_buf, cdc_count);
|
||||||
break;
|
break;
|
||||||
case HIDS_SUBEVENT_CAN_SEND_NOW:
|
case HIDS_SUBEVENT_CAN_SEND_NOW:
|
||||||
//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;
|
||||||
default:
|
default:
|
||||||
|
//cdc_count = sprintf(cdc_buf, "Unknown HID event %02X\n", hci_event_hids_meta_get_subevent_code(packet));
|
||||||
|
//cdc_print_str(cdc_buf, cdc_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
//cdc_count = sprintf(cdc_buf, "Unknown HCI event %02X\n", hci_event_packet_get_type(packet));
|
||||||
|
//cdc_print_str(cdc_buf, cdc_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// called to update the report map aka HID report descriptor on the BT interface
|
// called to update the report map aka HID report descriptor on the BT interface
|
||||||
void update_desc_hid_report(void) {
|
void update_desc_hid_report(void) {
|
||||||
|
con_handle = HCI_CON_HANDLE_INVALID;
|
||||||
hci_power_control(HCI_POWER_OFF);
|
hci_power_control(HCI_POWER_OFF);
|
||||||
|
|
||||||
if (desc_hid_report_len>0) {
|
if (bt_state == BT_STATE_ACTIVE && desc_hid_report_len>0) {
|
||||||
//cdc_print_msg("Update HID report descriptor: ");
|
|
||||||
//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);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
+18
@@ -1,6 +1,24 @@
|
|||||||
#ifndef BT_DEVICE_H_
|
#ifndef BT_DEVICE_H_
|
||||||
#define BT_DEVICE_H_
|
#define BT_DEVICE_H_
|
||||||
|
|
||||||
|
#define BT_LOOP_POLL_INTERVAL 100
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BT_STATE_INACTIVE=0,
|
||||||
|
BT_STATE_STOP,
|
||||||
|
BT_STATE_START,
|
||||||
|
BT_STATE_ACTIVE
|
||||||
|
} bt_state_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BT_DEVICE_COMMAND_NONE=0,
|
||||||
|
BT_DEVICE_COMMAND_SWITCH,
|
||||||
|
BT_DEVICE_COMMAND_UNPAIR,
|
||||||
|
BT_DEVICE_COMMAND_UPDATE,
|
||||||
|
} bt_device_command_t;
|
||||||
|
|
||||||
|
extern bt_state_t bt_state;
|
||||||
|
extern bt_device_command_t bt_device_command;
|
||||||
extern uint16_t conn_interval;
|
extern uint16_t conn_interval;
|
||||||
|
|
||||||
void btstack_main(void);
|
void btstack_main(void);
|
||||||
|
|||||||
+74
-30
@@ -19,6 +19,7 @@ extern hci_con_handle_t con_handle;
|
|||||||
|
|
||||||
uint8_t desc_hid_report[HID_DESCRIPTOR_SIZE];
|
uint8_t desc_hid_report[HID_DESCRIPTOR_SIZE];
|
||||||
uint16_t desc_hid_report_len=0;
|
uint16_t desc_hid_report_len=0;
|
||||||
|
uint8_t num_mounted=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;
|
||||||
@@ -29,7 +30,7 @@ static struct report_desc *descriptors;
|
|||||||
static struct report_desc* report_desc_alloc(void);
|
static struct report_desc* report_desc_alloc(void);
|
||||||
static void report_desc_init(struct report_desc *descriptor);
|
static void report_desc_init(struct report_desc *descriptor);
|
||||||
static void report_desc_free(struct report_desc *descriptor);
|
static void report_desc_free(struct report_desc *descriptor);
|
||||||
static struct report_desc* report_desc_find(uint8_t dev_addr, uint8_t instance);
|
static struct report_desc * report_desc_find(uint8_t dev_addr, uint8_t instance);
|
||||||
static struct report_dict* report_dict_alloc(struct report_desc *descriptor);
|
static struct report_dict* report_dict_alloc(struct report_desc *descriptor);
|
||||||
static void report_dict_init(struct report_dict *mapping);
|
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);
|
||||||
@@ -74,7 +75,11 @@ bool stop_hid_reports_all(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
host_state = HOST_INACTIVE;
|
if (num_mounted > 0) {
|
||||||
|
host_state = HOST_MOUNTED;
|
||||||
|
} else {
|
||||||
|
host_state = HOST_INACTIVE;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,38 +103,51 @@ void send_report(){
|
|||||||
// retrieve report from ring buffer
|
// retrieve report from ring buffer
|
||||||
btstack_ring_buffer_read(&report_buf, report->report, report->len, &num_bytes_read);
|
btstack_ring_buffer_read(&report_buf, report->report, report->len, &num_bytes_read);
|
||||||
|
|
||||||
// find report id mapping
|
// send over BLE if connected
|
||||||
struct report_dict * mapping = find_mapping(report->dev_addr, report->instance, report->report[0]);
|
if (con_handle != HCI_CON_HANDLE_INVALID) {
|
||||||
|
// find report id mapping
|
||||||
|
struct report_dict * mapping = find_mapping(report->dev_addr, report->instance, report->report[0]);
|
||||||
|
|
||||||
cdc_count=sprintf(cdc_buf, "[%04x](%u)> ", con_handle, mapping->ble_id);
|
cdc_count=sprintf(cdc_buf, "[%04x](%u)> ", con_handle, mapping->ble_id);
|
||||||
cdc_print_str(cdc_buf, cdc_count);
|
cdc_print_str(cdc_buf, cdc_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->report, report->len);
|
hids_device_send_input_report_for_id(con_handle, mapping->ble_id, report->report, report->len);
|
||||||
cdc_print_hex(report->report, 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->report[1], report->len-1);
|
hids_device_send_input_report_for_id(con_handle, mapping->ble_id, &report->report[1], report->len-1);
|
||||||
cdc_print_hex(&report->report[1], report->len-1);
|
cdc_print_hex(&report->report[1], report->len-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// request sending of next report
|
||||||
|
if (btstack_ring_buffer_bytes_available(&report_buf)) {
|
||||||
|
hids_device_request_can_send_now_event(con_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send over USB if enabled
|
||||||
|
if ( device_state == DEVICE_ACTIVE ) {
|
||||||
|
struct report_desc *descriptor = report_desc_find(report->dev_addr, report->instance);
|
||||||
|
cdc_count=sprintf(cdc_buf, "[%u]> ", descriptor->dev_instance);
|
||||||
|
cdc_print_str(cdc_buf, cdc_count);
|
||||||
|
|
||||||
|
forward_report(descriptor->dev_instance, report->report, report->len);
|
||||||
|
cdc_print_hex(report->report, report->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set host to poll USB
|
// set host to poll USB
|
||||||
if (host_state == HOST_WAIT_POLL) {
|
if (host_state == HOST_WAIT_POLL) {
|
||||||
host_state = HOST_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add report to the BTstack ring buffer for sending
|
// add report to the BTstack ring buffer for sending
|
||||||
void queue_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
|
void queue_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) {
|
||||||
if (con_handle != HCI_CON_HANDLE_INVALID) {
|
if (con_handle != HCI_CON_HANDLE_INVALID || device_state == DEVICE_ACTIVE ) {
|
||||||
// convert len to array of two uint8_t from single uint16_t
|
// convert len to array of two uint8_t from single uint16_t
|
||||||
uint8_t len8[2];
|
uint8_t len8[2];
|
||||||
memcpy(len8, &len, 2);
|
memcpy(len8, &len, 2);
|
||||||
@@ -142,8 +160,13 @@ void queue_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uin
|
|||||||
btstack_ring_buffer_write(&report_buf, report, len);
|
btstack_ring_buffer_write(&report_buf, report, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// request send on BLE HID interface
|
if (con_handle != HCI_CON_HANDLE_INVALID) {
|
||||||
hids_device_request_can_send_now_event(con_handle);
|
// request send on BLE HID interface
|
||||||
|
hids_device_request_can_send_now_event(con_handle);
|
||||||
|
} else {
|
||||||
|
// BLE is not active, send over USB
|
||||||
|
send_report();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HID report on device has not been requested, flag so it can be polled
|
// HID report on device has not been requested, flag so it can be polled
|
||||||
@@ -215,6 +238,7 @@ bool add_descriptor(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_repo
|
|||||||
descriptor->desc_len = desc_len;
|
descriptor->desc_len = desc_len;
|
||||||
descriptor->dev_addr = dev_addr;
|
descriptor->dev_addr = dev_addr;
|
||||||
descriptor->instance = instance;
|
descriptor->instance = instance;
|
||||||
|
descriptor->dev_instance = instance;
|
||||||
descriptor->listening = false;
|
descriptor->listening = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -226,7 +250,8 @@ bool generate_report_descriptor(void) {
|
|||||||
memset(desc_hid_report, 0, sizeof(desc_hid_report));
|
memset(desc_hid_report, 0, sizeof(desc_hid_report));
|
||||||
desc_hid_report_len=0;
|
desc_hid_report_len=0;
|
||||||
|
|
||||||
uint8_t num_mounted = 0;
|
uint8_t id_counter = 0;
|
||||||
|
uint8_t instance_counter = 0;
|
||||||
|
|
||||||
struct report_desc * current;
|
struct report_desc * current;
|
||||||
for (current=descriptors; current != NULL; current=current->next) {
|
for (current=descriptors; current != NULL; current=current->next) {
|
||||||
@@ -251,11 +276,11 @@ bool generate_report_descriptor(void) {
|
|||||||
if (report_map == NULL) {
|
if (report_map == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
num_mounted++;
|
id_counter++;
|
||||||
report_map->report_id = current->descriptor[i];
|
report_map->report_id = current->descriptor[i];
|
||||||
report_map->ble_id = num_mounted;
|
report_map->ble_id = id_counter;
|
||||||
|
|
||||||
desc_hid_report[desc_hid_report_len+i]=num_mounted;
|
desc_hid_report[desc_hid_report_len+i]=id_counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,30 +295,49 @@ bool generate_report_descriptor(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
desc_hid_report[desc_hid_report_len+col_pos+2] = 0x85;
|
desc_hid_report[desc_hid_report_len+col_pos+2] = 0x85;
|
||||||
desc_hid_report[desc_hid_report_len+col_pos+3] = num_mounted+1;
|
desc_hid_report[desc_hid_report_len+col_pos+3] = id_counter+1;
|
||||||
memcpy(&desc_hid_report[desc_hid_report_len+col_pos+4], ¤t->descriptor[col_pos+2], current->desc_len-col_pos);
|
memcpy(&desc_hid_report[desc_hid_report_len+col_pos+4], ¤t->descriptor[col_pos+2], current->desc_len-col_pos);
|
||||||
desc_hid_report_len += current->desc_len+2;
|
desc_hid_report_len += current->desc_len+2;
|
||||||
|
|
||||||
// store mapping with report ID of 0
|
// store mapping with report ID of 0
|
||||||
struct report_dict * report_map = report_dict_alloc(current);
|
struct report_dict * report_map = report_dict_alloc(current);
|
||||||
num_mounted++;
|
id_counter++;
|
||||||
report_map->report_id = 0;
|
report_map->report_id = 0;
|
||||||
report_map->ble_id = num_mounted;
|
report_map->ble_id = id_counter;
|
||||||
} else {
|
} else {
|
||||||
desc_hid_report_len += current->desc_len;
|
desc_hid_report_len += current->desc_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store mapping for host instance to device instance
|
||||||
|
current->dev_instance = instance_counter;
|
||||||
|
instance_counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_mounted > NUM_REPORT_IDS) {
|
if (id_counter > NUM_REPORT_IDS) {
|
||||||
cdc_print_msg("Error: too many report IDs\n");
|
cdc_print_msg("Error: too many report IDs\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update number of instances mounted
|
||||||
|
num_mounted = instance_counter;
|
||||||
|
|
||||||
btstack_ring_buffer_reset(&report_buf);
|
btstack_ring_buffer_reset(&report_buf);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// find a return the report descriptor by dvice address and device instance
|
||||||
|
struct report_desc * get_report_desc(uint8_t dev_instance) {
|
||||||
|
struct report_desc *descriptor;
|
||||||
|
for (descriptor = descriptors; descriptor != NULL; descriptor = descriptor->next) {
|
||||||
|
if (descriptor->dev_instance==dev_instance) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptor;
|
||||||
|
|
||||||
|
}
|
||||||
// remove report descriptor for HID interface
|
// remove report descriptor for HID interface
|
||||||
void remove_instance(uint8_t dev_addr, uint8_t instance) {
|
void remove_instance(uint8_t dev_addr, uint8_t instance) {
|
||||||
struct report_desc *descriptor = report_desc_find(dev_addr, instance);
|
struct report_desc *descriptor = report_desc_find(dev_addr, instance);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ struct report_desc {
|
|||||||
uint8_t instance;
|
uint8_t instance;
|
||||||
uint8_t descriptor[DESCRIPTOR_BUF_SIZE];
|
uint8_t descriptor[DESCRIPTOR_BUF_SIZE];
|
||||||
uint16_t desc_len;
|
uint16_t desc_len;
|
||||||
|
uint8_t dev_instance;
|
||||||
struct report_desc *next;
|
struct report_desc *next;
|
||||||
struct report_dict *mappings;
|
struct report_dict *mappings;
|
||||||
bool listening;
|
bool listening;
|
||||||
@@ -36,6 +37,7 @@ struct report_data {
|
|||||||
|
|
||||||
extern uint8_t desc_hid_report[HID_DESCRIPTOR_SIZE];
|
extern uint8_t desc_hid_report[HID_DESCRIPTOR_SIZE];
|
||||||
extern uint16_t desc_hid_report_len;
|
extern uint16_t desc_hid_report_len;
|
||||||
|
extern uint8_t num_mounted;
|
||||||
|
|
||||||
bool request_hid_reports_all(void);
|
bool request_hid_reports_all(void);
|
||||||
bool stop_hid_reports_all(void);
|
bool stop_hid_reports_all(void);
|
||||||
@@ -45,5 +47,6 @@ 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);
|
||||||
|
struct report_desc * get_report_desc(uint8_t dev_instance);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "pico/multicore.h"
|
#include "pico/multicore.h"
|
||||||
#include "pico/bootrom.h"
|
#include "pico/bootrom.h"
|
||||||
#include "hardware/clocks.h"
|
#include "hardware/clocks.h"
|
||||||
|
#include "hardware/gpio.h"
|
||||||
#include "pio_usb.h"
|
#include "pio_usb.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
@@ -12,8 +13,16 @@
|
|||||||
#include "usb_device.h"
|
#include "usb_device.h"
|
||||||
#include "usb_host.h"
|
#include "usb_host.h"
|
||||||
|
|
||||||
|
#include "blehid_config.h"
|
||||||
|
|
||||||
static void usb_main(void);
|
static void usb_main(void);
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN
|
||||||
|
static absolute_time_t last_button_time;
|
||||||
|
static uint32_t last_button_event;
|
||||||
|
static void gpio_callback(uint pin, uint32_t events);
|
||||||
|
#endif
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// for PIO USB, we want clock speed to be multiple of 12MHz
|
// for PIO USB, we want clock speed to be multiple of 12MHz
|
||||||
@@ -35,12 +44,24 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void usb_main(void) {
|
static void usb_main(void) {
|
||||||
|
// setup GPIO button for pair selection
|
||||||
|
#ifdef BUTTON_PIN
|
||||||
|
gpio_init(BUTTON_PIN);
|
||||||
|
gpio_pull_up(BUTTON_PIN);
|
||||||
|
gpio_set_irq_enabled_with_callback(BUTTON_PIN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// 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();
|
||||||
|
|
||||||
|
// set initial state
|
||||||
|
bt_state = BT_STATE_ACTIVE;
|
||||||
|
device_state = DEVICE_INACTIVE;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
switch ( host_state ) {
|
switch ( host_state ) {
|
||||||
case HOST_NEW_DESCRIPTOR:
|
case HOST_NEW_DESCRIPTOR:
|
||||||
@@ -58,8 +79,77 @@ static void usb_main(void) {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch ( device_state ) {
|
||||||
|
case DEVICE_STOP:
|
||||||
|
case DEVICE_START:
|
||||||
|
if ( tud_disconnect() ) {
|
||||||
|
sleep_ms(10);
|
||||||
|
tud_connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( device_state == DEVICE_STOP ) {
|
||||||
|
device_state = DEVICE_INACTIVE;
|
||||||
|
host_state = HOST_STOP_LISTEN;
|
||||||
|
} else if (device_state == DEVICE_START ) {
|
||||||
|
device_state = DEVICE_ACTIVE;
|
||||||
|
if ( num_mounted > 0 ) {
|
||||||
|
set_host_poll_interval(1);
|
||||||
|
host_state = HOST_START_LISTEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( bt_state ) {
|
||||||
|
case BT_STATE_STOP:
|
||||||
|
bt_state = BT_STATE_INACTIVE;
|
||||||
|
update_desc_hid_report();
|
||||||
|
break;
|
||||||
|
case BT_STATE_START:
|
||||||
|
bt_state = BT_STATE_ACTIVE;
|
||||||
|
update_desc_hid_report();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN
|
||||||
|
static void gpio_callback(uint pin, uint32_t events) {
|
||||||
|
uint64_t diff = absolute_time_diff_us(last_button_time, get_absolute_time());
|
||||||
|
if (pin == BUTTON_PIN && diff >= BUTTON_DEBOUNCE) {
|
||||||
|
if (events & GPIO_IRQ_EDGE_FALL) {
|
||||||
|
// button pressed
|
||||||
|
last_button_time = get_absolute_time();
|
||||||
|
} else if (events & GPIO_IRQ_EDGE_RISE) {
|
||||||
|
// button released
|
||||||
|
if (diff >= BUTTON_LONG_PRESS) {
|
||||||
|
//bt_device_command = BT_DEVICE_COMMAND_UNPAIR;
|
||||||
|
} else {
|
||||||
|
if ( bt_state == BT_STATE_ACTIVE ) {
|
||||||
|
bt_state = BT_STATE_STOP;
|
||||||
|
} else if ( bt_state == BT_STATE_INACTIVE ) {
|
||||||
|
bt_state = BT_STATE_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( device_state == DEVICE_ACTIVE ) {
|
||||||
|
device_state = DEVICE_STOP;
|
||||||
|
} else if ( device_state == DEVICE_INACTIVE ) {
|
||||||
|
device_state = DEVICE_START;
|
||||||
|
}
|
||||||
|
//bt_device_command = BT_DEVICE_COMMAND_SWITCH;
|
||||||
|
}
|
||||||
|
last_button_time = get_absolute_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
+14111
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 255 KiB |
+5
-4
@@ -84,14 +84,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//------------- Driver configuration -------------//
|
//------------- Driver configuration -------------//
|
||||||
#define CFG_TUD_CDC 1
|
#define CFG_TUD_CDC 1
|
||||||
|
#define CFG_TUD_HID 8
|
||||||
|
|
||||||
// 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 128
|
#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 128
|
#define CFG_TUD_CDC_EP_BUFSIZE 128
|
||||||
|
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
// HOST CONFIGURATION
|
// HOST CONFIGURATION
|
||||||
|
|||||||
+65
-62
@@ -1,37 +1,16 @@
|
|||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019 Ha Thach (tinyusb.org)
|
|
||||||
* sekigon-gonnoc
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
#include "bsp/board_api.h"
|
#include "bsp/board_api.h"
|
||||||
|
|
||||||
|
#include "hid_report.h"
|
||||||
|
#include "usb_device.h"
|
||||||
|
|
||||||
#include "usb_descriptors.h"
|
#include "usb_descriptors.h"
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
// reserve space for HID descriptor
|
||||||
// Device Descriptors
|
static uint8_t desc_configuration[DESC_CFG_MAX];
|
||||||
//--------------------------------------------------------------------+
|
static uint16_t _desc_str[32+1];
|
||||||
|
|
||||||
|
// USB device descriptor
|
||||||
tusb_desc_device_t const desc_device =
|
tusb_desc_device_t const desc_device =
|
||||||
{
|
{
|
||||||
.bLength = sizeof(tusb_desc_device_t),
|
.bLength = sizeof(tusb_desc_device_t),
|
||||||
@@ -57,6 +36,17 @@ tusb_desc_device_t const desc_device =
|
|||||||
.bNumConfigurations = 0x01
|
.bNumConfigurations = 0x01
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// string labels for device
|
||||||
|
char const* string_desc_arr [] =
|
||||||
|
{
|
||||||
|
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||||
|
"Raspberry Pi", // 1: Manufacturer
|
||||||
|
"Pico BLE HID", // 2: Product
|
||||||
|
NULL, // 3: Serials, should use chip ID
|
||||||
|
"Pico BLE HID CDC", // 4: CDC
|
||||||
|
"Pico USB HID", // 5: USB HID Device
|
||||||
|
};
|
||||||
|
|
||||||
// Invoked when received GET DEVICE DESCRIPTOR
|
// Invoked when received GET DEVICE DESCRIPTOR
|
||||||
// Application return pointer to descriptor
|
// Application return pointer to descriptor
|
||||||
uint8_t const * tud_descriptor_device_cb(void)
|
uint8_t const * tud_descriptor_device_cb(void)
|
||||||
@@ -64,47 +54,46 @@ uint8_t const * tud_descriptor_device_cb(void)
|
|||||||
return (uint8_t const *) &desc_device;
|
return (uint8_t const *) &desc_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
// Configuration Descriptor
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
|
|
||||||
// full speed configuration
|
|
||||||
uint8_t const desc_fs_configuration[] =
|
|
||||||
{
|
|
||||||
// Config number, interface count, string index, total length, attribute, power in mA
|
|
||||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
|
||||||
|
|
||||||
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
|
||||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||||
// Application return pointer to descriptor
|
// Application return pointer to descriptor
|
||||||
// Descriptor contents must exist long enough for transfer to complete
|
// Descriptor contents must exist long enough for transfer to complete
|
||||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||||
{
|
{
|
||||||
(void) index; // for multiple configurations
|
(void) index; // for multiple configurations
|
||||||
return desc_fs_configuration;
|
// set configuration descriptor and CDC descriptor
|
||||||
|
memset(desc_configuration, 0, sizeof(desc_configuration));
|
||||||
|
|
||||||
|
if ( device_state == DEVICE_ACTIVE ) {
|
||||||
|
uint8_t desc_initial[TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+1] = {
|
||||||
|
TUD_CONFIG_DESCRIPTOR(1, 4+num_mounted, 0, TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+num_mounted*TUD_HID_DESC_LEN, 0x00, 100),
|
||||||
|
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||||
|
};
|
||||||
|
memcpy(desc_configuration, desc_initial, TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN);
|
||||||
|
} else {
|
||||||
|
uint8_t desc_initial[TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+1] = {
|
||||||
|
TUD_CONFIG_DESCRIPTOR(1, 4, 0, TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN, 0x00, 100),
|
||||||
|
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
|
||||||
|
};
|
||||||
|
memcpy(desc_configuration, desc_initial, TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add a HID descriptor for each interface mounted on host
|
||||||
|
if ( device_state == DEVICE_ACTIVE ) {
|
||||||
|
struct report_desc * descriptor;
|
||||||
|
for (uint8_t i=0; i<num_mounted;i++) {
|
||||||
|
descriptor = get_report_desc(i);
|
||||||
|
if ( descriptor != NULL ) {
|
||||||
|
uint8_t hid_desc[TUD_HID_DESC_LEN+1] = {
|
||||||
|
TUD_HID_DESCRIPTOR(ITF_NUM_HID+i, 5, HID_ITF_PROTOCOL_NONE, descriptor->desc_len, EPNUM_HID+i, CFG_TUD_HID_EP_BUFSIZE, 1)
|
||||||
|
};
|
||||||
|
memcpy(&desc_configuration[TUD_CONFIG_DESC_LEN+TUD_CDC_DESC_LEN+i*TUD_HID_DESC_LEN], hid_desc, TUD_HID_DESC_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc_configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
// String Descriptors
|
|
||||||
//--------------------------------------------------------------------+
|
|
||||||
|
|
||||||
// array of pointer to string descriptors
|
|
||||||
char const* string_desc_arr [] =
|
|
||||||
{
|
|
||||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
|
||||||
"Raspberry Pi", // 1: Manufacturer
|
|
||||||
"Pico BLE HID", // 2: Product
|
|
||||||
NULL, // 3: Serials, should use chip ID
|
|
||||||
"Pico BLE HID CDC", // 4: Product
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint16_t _desc_str[32+1];
|
|
||||||
|
|
||||||
// Invoked when received GET STRING DESCRIPTOR request
|
// Invoked when received GET STRING DESCRIPTOR request
|
||||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||||
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||||
@@ -145,3 +134,17 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
|||||||
|
|
||||||
return _desc_str;
|
return _desc_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invoked when received GET HID REPORT DESCRIPTOR
|
||||||
|
// Application return pointer to descriptor
|
||||||
|
// Descriptor contents must exist long enough for transfer to complete
|
||||||
|
uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf)
|
||||||
|
{
|
||||||
|
// find HID report descriptor for indicated interface on the host and forward to device
|
||||||
|
struct report_desc * descriptor = get_report_desc(itf);
|
||||||
|
if ( descriptor != NULL ) {
|
||||||
|
return descriptor->descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|||||||
+3
-1
@@ -5,6 +5,7 @@ enum
|
|||||||
{
|
{
|
||||||
ITF_NUM_CDC=0,
|
ITF_NUM_CDC=0,
|
||||||
ITF_NUM_CDC_DATA,
|
ITF_NUM_CDC_DATA,
|
||||||
|
ITF_NUM_HID,
|
||||||
ITF_NUM_TOTAL
|
ITF_NUM_TOTAL
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -15,7 +16,8 @@ enum
|
|||||||
#define EPNUM_CDC_NOTIF 0x81
|
#define EPNUM_CDC_NOTIF 0x81
|
||||||
#define EPNUM_CDC_OUT 0x02
|
#define EPNUM_CDC_OUT 0x02
|
||||||
#define EPNUM_CDC_IN 0x82
|
#define EPNUM_CDC_IN 0x82
|
||||||
|
#define EPNUM_HID 0x83
|
||||||
|
|
||||||
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
|
#define DESC_CFG_MAX (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + CFG_TUD_HID*TUD_HID_DESC_LEN)
|
||||||
|
|
||||||
#endif /* USB_DESCRIPTORS_H_ */
|
#endif /* USB_DESCRIPTORS_H_ */
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ char cdc_buf[64];
|
|||||||
uint16_t cdc_len;
|
uint16_t cdc_len;
|
||||||
size_t cdc_count;
|
size_t cdc_count;
|
||||||
|
|
||||||
|
device_state_t device_state;
|
||||||
|
|
||||||
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,6 +48,10 @@ uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool forward_report(uint8_t instance, uint8_t const* report, uint16_t len) {
|
||||||
|
return tud_hid_n_report(instance, 0, report, len);
|
||||||
|
}
|
||||||
|
|
||||||
// print message to CDC in raw hex
|
// print message to CDC in raw hex
|
||||||
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;
|
||||||
|
|||||||
@@ -1,11 +1,20 @@
|
|||||||
#ifndef USB_DEVICE_H_
|
#ifndef USB_DEVICE_H_
|
||||||
#define USB_DEVICE_H_
|
#define USB_DEVICE_H_
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEVICE_INACTIVE=0,
|
||||||
|
DEVICE_START,
|
||||||
|
DEVICE_STOP,
|
||||||
|
DEVICE_ACTIVE
|
||||||
|
} device_state_t;
|
||||||
|
|
||||||
extern char cdc_buf[64];
|
extern char cdc_buf[64];
|
||||||
extern uint16_t cdc_len;
|
extern uint16_t cdc_len;
|
||||||
extern size_t cdc_count;
|
extern size_t cdc_count;
|
||||||
|
extern device_state_t device_state;
|
||||||
|
|
||||||
void usb_device_init(void);
|
void usb_device_init(void);
|
||||||
|
bool forward_report(uint8_t instance, uint8_t const* report, uint16_t len);
|
||||||
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 cdc_print_str(char const* msg, uint16_t msg_len);
|
void cdc_print_str(char const* msg, uint16_t msg_len);
|
||||||
void cdc_print_msg(char const* msg);
|
void cdc_print_msg(char const* msg);
|
||||||
|
|||||||
+9
-10
@@ -84,26 +84,25 @@ void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t cons
|
|||||||
last_report = get_absolute_time();
|
last_report = get_absolute_time();
|
||||||
host_state = HOST_WAIT_POLL;
|
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
|
|
||||||
/*if ( !tuh_hid_receive_report(dev_addr, instance) )
|
|
||||||
{
|
|
||||||
cdc_print_msg("Error: cannot request report\r\n");
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get host ready by updating descriptors
|
// get host ready by updating descriptors
|
||||||
void host_ready(void) {
|
void host_ready(void) {
|
||||||
if (absolute_time_diff_us(request_time, get_absolute_time()) >= 1000000){
|
if (absolute_time_diff_us(request_time, get_absolute_time()) >= 1000000){
|
||||||
if(generate_report_descriptor()) {
|
if ( generate_report_descriptor() ) {
|
||||||
if ( desc_hid_report_len > 0 ) {
|
if ( num_mounted > 0 ) {
|
||||||
host_state=HOST_MOUNTED;
|
host_state = HOST_MOUNTED;
|
||||||
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
|
cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1);
|
||||||
} else {
|
} else {
|
||||||
host_state=HOST_INACTIVE;
|
host_state = HOST_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdc_print_msg("Updating HID report map\n");
|
cdc_print_msg("Updating HID report map\n");
|
||||||
update_desc_hid_report();
|
update_desc_hid_report();
|
||||||
|
|
||||||
|
if ( device_state == DEVICE_ACTIVE ) {
|
||||||
|
device_state = DEVICE_START;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#ifndef USB_HOST_H_
|
#ifndef USB_HOST_H_
|
||||||
#define USB_HOST_H_
|
#define USB_HOST_H_
|
||||||
|
|
||||||
#define HOST_POLL_INTERVAL 8000
|
#define HOST_POLL_INTERVAL 7500
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HOST_INACTIVE=0,
|
HOST_INACTIVE=0,
|
||||||
|
|||||||
Reference in New Issue
Block a user