Deprecate host stack

This commit is contained in:
sekigon-gonnoc 2024-09-23 11:29:10 +09:00
parent fe9133fc51
commit 528616d809
6 changed files with 1 additions and 737 deletions

View file

@ -56,7 +56,5 @@ jobs:
path: |
examples/build/usb_device/usb_device.uf2
examples/build/usb_device/usb_device.hex
examples/build/capture_hid_report/capture_hid_report.uf2
examples/build/capture_hid_report/capture_hid_report.hex
examples/build/host_hid_to_device_cdc/host_hid_to_device_cdc.uf2
examples/build/host_hid_to_device_cdc/host_hid_to_device_cdc.hex

View file

@ -20,9 +20,8 @@ https://user-images.githubusercontent.com/43873124/146642806-bdf34af6-4342-4a95-
## Examples
- [capture_hid_report.c](examples/capture_hid_report/capture_hid_report.c) is a USB host sample program which print HID reports received from device. Open serial port and connect devices to pico. Default D+/D- is gp0/gp1. Call `pio_usb_add_port()` to use additional ports.
- [host_hid_to_device_cdc.c](examples/host_hid_to_device_cdc/host_hid_to_device_cdc.c) which print mouse/keyboard report from host port to device port's cdc. TinyUSB is used to manage both device (native usb) and host (pio usb) stack.
- [usb_device.c](examples/usb_device/usb_device.c) is a HID USB FS device sample which moves mouse cursor every 0.5s. External 1.5kohm pull-up register is necessary to D+ pin (Default is gp0).
- [host_hid_to_device_cdc.c](examples/host_hid_to_device_cdc/host_hid_to_device_cdc.c) is similar to **capture_hid_report.c** which print mouse/keyboard report from host port to device port's cdc. TinyUSB is used to manage both device (native usb) and host (pio usb) stack.
```bash
cd examples

View file

@ -11,7 +11,6 @@ set(PICO_PIO_USB_DIR "${CMAKE_CURRENT_LIST_DIR}/../")
# a subdirectory, it's out of tree.
add_subdirectory(${PICO_PIO_USB_DIR} pico_pio_usb)
add_subdirectory(capture_hid_report)
add_subdirectory(usb_device)
add_subdirectory(host_hid_to_device_cdc)
add_subdirectory(test_ll)

View file

@ -1,15 +0,0 @@
set(target_name capture_hid_report)
add_executable(${target_name})
pico_enable_stdio_usb(${target_name} 1)
target_sources(${target_name} PRIVATE
capture_hid_report.c
)
# print memory usage, enable all warnings
target_link_options(${target_name} PRIVATE -Xlinker --print-memory-usage)
target_compile_options(${target_name} PRIVATE -Wall -Wextra)
target_link_libraries(${target_name} PRIVATE pico_stdlib pico_multicore pico_pio_usb)
pico_add_extra_outputs(${target_name})

View file

@ -1,77 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "hardware/clocks.h"
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "pico/bootrom.h"
#include "pio_usb.h"
static usb_device_t *usb_device = NULL;
void core1_main() {
sleep_ms(10);
// To run USB SOF interrupt in core1, create alarm pool in core1.
static pio_usb_configuration_t config = PIO_USB_DEFAULT_CONFIG;
config.alarm_pool = (void*)alarm_pool_create(2, 1);
usb_device = pio_usb_host_init(&config);
//// Call pio_usb_host_add_port to use multi port
// const uint8_t pin_dp2 = 8;
// pio_usb_host_add_port(pin_dp2);
while (true) {
pio_usb_host_task();
}
}
int main() {
// default 125MHz is not appropreate. Sysclock should be multiple of 12MHz.
set_sys_clock_khz(120000, true);
stdio_init_all();
printf("hello!");
sleep_ms(10);
multicore_reset_core1();
// all USB task run in core1
multicore_launch_core1(core1_main);
while (true) {
if (usb_device != NULL) {
for (int dev_idx = 0; dev_idx < PIO_USB_DEVICE_CNT; dev_idx++) {
usb_device_t *device = &usb_device[dev_idx];
if (!device->connected) {
continue;
}
// Print received packet to EPs
for (int ep_idx = 0; ep_idx < PIO_USB_DEV_EP_CNT; ep_idx++) {
endpoint_t *ep = pio_usb_get_endpoint(device, ep_idx);
if (ep == NULL) {
break;
}
uint8_t temp[64];
int len = pio_usb_get_in_data(ep, temp, sizeof(temp));
if (len > 0) {
printf("%04x:%04x EP 0x%02x:\t", device->vid, device->pid,
ep->ep_num);
for (int i = 0; i < len; i++) {
printf("%02x ", temp[i]);
}
printf("\n");
}
}
}
}
stdio_flush();
sleep_us(10);
}
}

View file

@ -612,646 +612,6 @@ static int __no_inline_not_in_flash_func(usb_setup_transaction)(
return res;
}
//--------------------------------------------------------------------+
// USB Host Stack
//--------------------------------------------------------------------+
static void on_device_connect(pio_port_t *pp, root_port_t *root,
int device_idx) {
bool fullspeed_flag = false;
if (pio_usb_bus_get_line_state(root) == PORT_PIN_FS_IDLE) {
fullspeed_flag = true;
} else if (pio_usb_bus_get_line_state(root) == PORT_PIN_LS_IDLE) {
fullspeed_flag = false;
}
pio_sm_set_pins_with_mask(pp->pio_usb_tx, pp->sm_tx, 0,
(1 << root->pin_dp) | (1 << root->pin_dm));
pio_sm_set_pindirs_with_mask(pp->pio_usb_tx, pp->sm_tx,
(1 << root->pin_dp) | (1 << root->pin_dm),
(1 << root->pin_dp) | (1 << root->pin_dm));
busy_wait_ms(100);
pio_sm_set_pindirs_with_mask(pp->pio_usb_tx, pp->sm_tx, 0,
(1 << root->pin_dp) | (1 << root->pin_dm));
busy_wait_us(100);
root->suspended = false;
if (fullspeed_flag && pio_usb_bus_get_line_state(root) == PORT_PIN_FS_IDLE) {
root->root_device = &pio_usb_device[device_idx];
if (!root->root_device->connected) {
configure_fullspeed_host(pp, root);
root->root_device->is_fullspeed = true;
root->root_device->is_root = true;
root->root_device->connected = true;
root->root_device->root = root;
root->root_device->event = EVENT_CONNECT;
}
} else if (!fullspeed_flag && pio_usb_bus_get_line_state(root) == PORT_PIN_LS_IDLE) {
root->root_device = &pio_usb_device[device_idx];
if (!root->root_device->connected) {
configure_lowspeed_host(pp, root);
root->root_device->is_fullspeed = false;
root->root_device->is_root = true;
root->root_device->connected = true;
root->root_device->root = root;
root->root_device->event = EVENT_CONNECT;
}
}
endpoint_descriptor_t ep0_desc = {
sizeof(endpoint_descriptor_t), DESC_TYPE_ENDPOINT, 0x00, 0x00, { 0x08, 0x00 }, 0x00
};
pio_usb_host_endpoint_open(root - pio_usb_root_port, 0x00,
(uint8_t const *)&ep0_desc, false);
}
static int __no_inline_not_in_flash_func(control_out_protocol)(
usb_device_t *device, uint8_t *setup_data, uint16_t setup_length,
uint8_t *out_data, uint16_t out_length) {
int res = 0;
control_pipe_t *pipe = &device->control_pipe;
if (pipe->operation == CONTROL_NONE) {
pipe->setup_packet.tx_address = setup_data;
pipe->setup_packet.tx_length = setup_length;
pipe->out_data_packet.tx_address = out_data;
pipe->out_data_packet.tx_length = out_length;
pipe->operation = CONTROL_OUT;
pio_usb_host_send_setup(device->root - pio_usb_root_port, device->address, setup_data);
} else {
return -1;
}
const uint64_t timeout = 5000 * 1000; // 5s
uint64_t start_time = time_us_64();
while (pipe->operation == CONTROL_OUT &&
time_us_64() - start_time < timeout) {
if (!device->connected) {
pipe->operation = CONTROL_NONE;
return -1;
}
}
if (time_us_64() - start_time >= timeout) {
printf("control out[timeout]\n");
res = -2;
} else if (pipe->operation == CONTROL_ERROR) {
printf("control out[error]\n");
res = -1;
} else if (pipe->operation == CONTROL_COMPLETE) {
printf("control out[complete]\n");
res = 0;
}
pipe->operation = CONTROL_NONE;
return res;
}
static int __no_inline_not_in_flash_func(control_in_protocol)(
usb_device_t *device, uint8_t *tx_data, uint16_t tx_length,
uint8_t *rx_buffer, uint16_t request_length) {
int res = 0;
control_pipe_t *pipe = &device->control_pipe;
if (pipe->operation == CONTROL_NONE) {
pipe->setup_packet.tx_address = tx_data;
pipe->setup_packet.tx_length = tx_length;
pipe->rx_buffer = rx_buffer;
pipe->request_length = request_length;
pipe->operation = CONTROL_IN;
pio_usb_host_send_setup(device->root - pio_usb_root_port, device->address, tx_data);
} else {
return -1;
}
const uint64_t timeout = 5000 * 1000; // 5s
uint64_t start_time = time_us_64();
while (pipe->operation == CONTROL_IN &&
time_us_64() - start_time < timeout) {
if (!device->connected) {
pipe->operation = CONTROL_NONE;
return -1;
}
}
if (time_us_64() - start_time >= timeout) {
printf("control in[timeout]\n");
res = -2;
} else if (pipe->operation == CONTROL_ERROR) {
printf("control in[error]\n");
res = -1;
} else if (pipe->operation == CONTROL_COMPLETE) {
printf("control in[complete]\n");
res = 0;
}
pipe->operation = CONTROL_NONE;
return res;
}
static int set_hub_feature(usb_device_t *device, uint8_t port, uint8_t value) {
usb_setup_packet_t req = SET_HUB_FEATURE_REQUEST;
req.index_lsb = port + 1;
req.value_lsb = value;
return control_out_protocol(device, (uint8_t *)&req, sizeof(req), NULL, 0);
}
static int clear_hub_feature(usb_device_t *device, uint8_t port,
uint8_t value) {
usb_setup_packet_t req = CLEAR_HUB_FEATURE_REQUEST;
req.index_lsb = port + 1;
req.value_lsb = value;
return control_out_protocol(device, (uint8_t *)&req, sizeof(req), NULL, 0);
}
static int get_hub_port_status(usb_device_t *device, uint8_t port,
hub_port_status_t *status) {
usb_setup_packet_t req = GET_HUB_PORT_STATUS_REQUEST;
req.index_lsb = port + 1;
return control_in_protocol(device, (uint8_t *)&req, sizeof(req), (uint8_t*)status,
sizeof(*status));
}
static int initialize_hub(usb_device_t *device) {
uint8_t rx_buffer[16];
int res = 0;
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");
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");
break;
}
}
busy_wait_ms(500);
return res;
}
static int get_string_descriptor(usb_device_t *device, uint8_t idx,
uint8_t *rx_buffer, uint8_t *str_buffer) {
int res = -1;
usb_setup_packet_t req = GET_DEVICE_DESCRIPTOR_REQ_DEFAULT;
req.value_msb = DESC_TYPE_STRING;
req.value_lsb = idx;
req.length_lsb = 1;
req.length_msb = 0;
res = control_in_protocol(device, (uint8_t *)&req, sizeof(req), rx_buffer, 1);
if (res != 0) {
return res;
}
uint8_t len = rx_buffer[0];
req.length_lsb = len;
req.length_msb = 0;
res =
control_in_protocol(device, (uint8_t *)&req, sizeof(req), rx_buffer, len);
if (res != 0) {
return res;
}
uint16_t *wchar_buffer = (uint16_t *)(uintptr_t) rx_buffer;
for (int i = 0; i < (len - 2) / 2; i++) {
str_buffer[i] = wchar_buffer[i + 1];
}
str_buffer[(len - 2) / 2] = '\0';
return res;
}
static int enumerate_device(usb_device_t *device, uint8_t address) {
int res = 0;
uint8_t rx_buffer[512];
usb_setup_packet_t get_device_descriptor_request =
GET_DEVICE_DESCRIPTOR_REQ_DEFAULT;
res = control_in_protocol(device, (uint8_t *)&get_device_descriptor_request,
sizeof(get_device_descriptor_request), rx_buffer, 18);
if (res != 0) {
pio_usb_host_close_device(device->root - pio_usb_root_port, 0);
return res;
}
const device_descriptor_t *desc =
(device_descriptor_t *)device->control_pipe.rx_buffer;
device->vid = desc->vid[0] | (desc->vid[1] << 8);
device->pid = desc->pid[0] | (desc->pid[1] << 8);
device->device_class = desc->device_class;
uint8_t idx_manufacture = desc->manufacture;
uint8_t idx_product = desc->product;
uint8_t idx_serial = desc->serial;
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;
set_address_request.value_lsb = address;
set_address_request.value_msb = 0;
res = control_out_protocol(device, (uint8_t *)&set_address_request,
sizeof(set_address_request), NULL, 0);
pio_usb_host_close_device(device->root - pio_usb_root_port, 0);
if (res != 0) {
return res;
}
device->address = address;
endpoint_descriptor_t ep0_desc = {
sizeof(endpoint_descriptor_t), DESC_TYPE_ENDPOINT, 0x00, 0x00, { desc->max_packet_size, 0x00 }, 0x00
};
pio_usb_host_endpoint_open(device->root - pio_usb_root_port, address,
(uint8_t const *)&ep0_desc,
!device->is_root && !device->is_fullspeed);
uint8_t str[64];
if (idx_manufacture != 0) {
res = get_string_descriptor(device, idx_manufacture, rx_buffer, str);
if (res == 0) {
printf("Manufacture:%s\n", str);
} else {
printf("Failed to get string descriptor (Manufacture)\n");
}
stdio_flush();
}
if (idx_product != 0) {
res = get_string_descriptor(device, idx_product, rx_buffer, str);
if (res == 0) {
printf("Product:%s\n", str);
} else {
printf("Failed to get string descriptor (Product)\n");
}
stdio_flush();
}
if (idx_serial != 0) {
res = get_string_descriptor(device, idx_serial, rx_buffer, str);
if (res == 0) {
printf("Serial:%s\n", str);
} else {
printf("Failed to get string descriptor (Serial)\n");
}
stdio_flush();
}
usb_setup_packet_t get_configuration_descriptor_request =
GET_CONFIGURATION_DESCRIPTOR_REQ_DEFAULT;
get_configuration_descriptor_request.length_lsb = 9;
get_configuration_descriptor_request.length_msb = 0;
res = control_in_protocol(
device, (uint8_t *)&get_configuration_descriptor_request,
sizeof(get_configuration_descriptor_request), rx_buffer, 9);
if (res != 0) {
return res;
}
get_configuration_descriptor_request.length_lsb =
((configuration_descriptor_t *)(device->control_pipe.rx_buffer))
->total_length_lsb;
get_configuration_descriptor_request.length_msb =
((configuration_descriptor_t *)(device->control_pipe.rx_buffer))
->total_length_msb;
uint16_t request_length =
get_configuration_descriptor_request.length_lsb |
(get_configuration_descriptor_request.length_msb << 8);
res = control_in_protocol(
device, (uint8_t *)&get_configuration_descriptor_request,
sizeof(get_configuration_descriptor_request), rx_buffer, request_length);
if (res != 0) {
return res;
}
uint8_t configuration_descrptor_data[512];
int16_t configuration_descrptor_length =
request_length > 512 ? 512 : request_length;
memcpy(configuration_descrptor_data,
(const void *)device->control_pipe.rx_buffer,
configuration_descrptor_length);
usb_setup_packet_t set_usb_configuration_request =
SET_CONFIGURATION_REQ_DEFAULT;
set_usb_configuration_request.value_lsb =
((configuration_descriptor_t *)(device->control_pipe.rx_buffer))
->configuration_value;
res = control_out_protocol(device, (uint8_t *)&set_usb_configuration_request,
sizeof(set_usb_configuration_request), NULL, 0);
if (res != 0) {
return res;
}
volatile uint8_t ep_id_idx = 0;
volatile uint8_t interface = 0;
volatile uint8_t class = 0;
uint8_t *descriptor = configuration_descrptor_data;
while (configuration_descrptor_length > 0) {
switch (descriptor[1]) {
case DESC_TYPE_INTERFACE: {
const interface_descriptor_t *d =
(const interface_descriptor_t *)descriptor;
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,
d->iprotocol, d->iface);
interface = d->inum;
class = d->iclass;
} break;
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",
d->epaddr, d->attr, d->max_size[0] | (d->max_size[1] << 8),
d->interval);
if ((class == CLASS_HID || class == CLASS_HUB) &&
d->attr == EP_ATTR_INTERRUPT) {
volatile endpoint_t *ep = NULL;
for (int ep_pool_idx = 0; ep_pool_idx < PIO_USB_EP_POOL_CNT;
ep_pool_idx++) {
if (pio_usb_ep_pool[ep_pool_idx].size == 0) {
ep = &pio_usb_ep_pool[ep_pool_idx];
device->endpoint_id[ep_id_idx] = ep_pool_idx + 1;
ep_id_idx++;
break;
}
}
if (ep != NULL) {
ep->interval = d->interval;
ep->interval_counter = 0;
ep->size = d->max_size[0] | (d->max_size[1] << 8);
ep->attr = d->attr | EP_ATTR_ENUMERATING;
ep->ep_num = d->epaddr;
ep->root_idx = device->root - pio_usb_root_port;
ep->dev_addr = device->address;
ep->need_pre = !device->is_root && !device->is_fullspeed;
ep->is_tx = (d->epaddr & 0x80) ? false : true;
} else {
printf("No empty EP\n");
}
}
} break;
case DESC_TYPE_HID: {
const hid_descriptor_t *d = (const hid_descriptor_t *)descriptor;
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,
d->desc_type, d->desc_len[0] | (d->desc_len[1] << 8));
usb_setup_packet_t set_hid_idle_request = SET_HID_IDLE_REQ_DEFAULT;
set_hid_idle_request.value_lsb = interface;
set_hid_idle_request.value_msb = 0;
control_out_protocol(device, (uint8_t *)&set_hid_idle_request,
sizeof(set_hid_idle_request), NULL, 0);
usb_setup_packet_t get_hid_report_descrpitor_request =
GET_HID_REPORT_DESCRIPTOR_DEFAULT;
get_hid_report_descrpitor_request.index_lsb = interface;
get_hid_report_descrpitor_request.index_msb = 0;
get_hid_report_descrpitor_request.length_lsb = d->desc_len[0];
get_hid_report_descrpitor_request.length_msb = d->desc_len[1];
uint16_t desc_len = d->desc_len[0] | (d->desc_len[1] << 8);
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:");
for (int i = 0; i < desc_len; i++) {
printf("%02x ", device->control_pipe.rx_buffer[i]);
}
printf("\n");
stdio_flush();
} break;
default:
break;
}
configuration_descrptor_length -= descriptor[0];
descriptor += descriptor[0];
}
for (int epidx = 0; epidx < PIO_USB_DEV_EP_CNT; epidx++) {
endpoint_t *ep = pio_usb_get_endpoint(device, epidx);
if (ep == NULL) {
break;
}
ep->attr &= ~EP_ATTR_ENUMERATING;
// prepare transfer
if (ep->ep_num & EP_IN) {
pio_usb_ll_transfer_start(ep, ep->buffer, ep->size);
}
}
return res;
}
static void device_disconnect(usb_device_t *device) {
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]]);
}
}
for (int ep_idx = 0; ep_idx < PIO_USB_DEV_EP_CNT; ep_idx++) {
endpoint_t *ep = pio_usb_get_endpoint(device, ep_idx);
if (ep == NULL) {
break;
}
memset(ep, 0, sizeof(*ep));
}
if (device->address == 0 && device->root != NULL) {
device->root->addr0_exists = false;
}
memset(device, 0, sizeof(*device));
}
static int device_pool_vacant(void) {
for (int idx = 0; idx < PIO_USB_DEVICE_CNT; idx++) {
if (!pio_usb_device[idx].connected) {
return idx;
}
}
return -1;
}
static int assign_new_device_to_port(usb_device_t *hub_device, uint8_t port, bool is_ls) {
int idx = device_pool_vacant();
if (idx >= 0) {
hub_device->child_devices[port] = idx;
pio_usb_device[idx].parent_device = hub_device;
pio_usb_device[idx].parent_port = port;
pio_usb_device[idx].root = hub_device->root;
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);
endpoint_descriptor_t ep0_desc = {
sizeof(endpoint_descriptor_t), DESC_TYPE_ENDPOINT, 0x00, 0x00, { 0x08, 0x00 }, 0x00
};
pio_usb_host_endpoint_open(hub_device->root - pio_usb_root_port, 0x00,
(uint8_t const *)&ep0_desc, is_ls);
return 0;
}
printf("Failed to assign device\n");
return -1;
}
static void __no_inline_not_in_flash_func(process_hub_event)(
usb_device_t *device) {
volatile endpoint_t *ep = pio_usb_get_endpoint(device, 0);
uint8_t bitmap = ep->buffer[0];
for (int bit = 1; bit < 8; bit++) {
if (!(bitmap & (1 << bit))) {
continue;
}
uint8_t port = bit - 1;
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);
continue;
}
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);
if (device->child_devices[port] != 0) {
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");
continue;
}
if (device_pool_vacant() >= 0) {
set_hub_feature(device, port, HUB_SET_PORT_RESET);
device->root->addr0_exists = true;
} else {
printf("No vacant in device pool\n");
}
} else {
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);
res = clear_hub_feature(device, port, HUB_CLR_PORT_RESET);
if (res == 0) {
assign_new_device_to_port(device, port,
status.port_status & HUB_STAT_PORT_LOWSPEED);
}
} else if (status.port_change & HUB_CHANGE_PORT_ENABLE) {
clear_hub_feature(device, port, HUB_CLR_PORT_ENABLE);
}
}
device->event = EVENT_NONE;
}
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);
int dev_idx = device_pool_vacant();
if (dev_idx >= 0) {
on_device_connect(&pio_port[0], &pio_usb_root_port[root_idx], dev_idx);
pio_usb_root_port[root_idx].addr0_exists = true;
}
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);
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;
pio_usb_root_port[root_idx].root_device->event = EVENT_DISCONNECT;
pio_usb_root_port[root_idx].root_device = NULL;
pio_usb_root_port[root_idx].event = EVENT_NONE;
}
}
for (int idx = 0; idx < PIO_USB_DEVICE_CNT; idx++) {
usb_device_t *device = &pio_usb_device[idx];
if (device->event == EVENT_CONNECT) {
device->event = EVENT_NONE;
printf("Device %d Connected\n", idx);
int res = enumerate_device(device, idx + 1);
if (res == 0) {
device->enumerated = true;
device->root->addr0_exists = false;
if (device->device_class == CLASS_HUB) {
res = initialize_hub(device);
}
}
if (res != 0) {
printf("Enumeration failed(%d)\n", res);
// retry
if (device->is_root) {
device->root->event = EVENT_DISCONNECT;
} else {
set_hub_feature(device->parent_device, device->parent_port,
HUB_SET_PORT_RESET);
device_disconnect(device);
}
}
} else if (device->event == EVENT_DISCONNECT) {
device->event = EVENT_NONE;
printf("Disconnect\n");
device_disconnect(device);
} else if (device->event == EVENT_HUB_PORT_CHANGE) {
process_hub_event(device);
}
}
if (cancel_timer_flag) {
int_stat = save_and_disable_interrupts();
stop_timer();
if (pio_usb_root_port->root_device != NULL) {
device_disconnect(pio_usb_root_port->root_device);
}
cancel_timer_flag = false;
}
if (start_timer_flag) {
start_timer(_alarm_pool);
restore_interrupts(int_stat);
start_timer_flag = false;
}
}
static void __no_inline_not_in_flash_func(handle_endpoint_irq)(
root_port_t *root, uint32_t flag, volatile uint32_t *ep_reg) {