Skip to content

Commit c73ebba

Browse files
authored
Merge pull request #1409 from NickeZ/nickez/usb-processing-in-mainloop
usb: Move usb handling out into main loop
2 parents 3153156 + 2e5010e commit c73ebba

File tree

14 files changed

+194
-129
lines changed

14 files changed

+194
-129
lines changed

src/bootloader/startup.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "mpu_regions.h"
1717
#include "platform_config.h"
1818
#include "platform_init.h"
19+
#include "usb/class/hid/hww/hid_hww.h"
1920

2021
#include <driver_init.h>
2122
#include <hardfault.h>
@@ -56,8 +57,22 @@ int main(void)
5657
#endif
5758
bootloader_jump();
5859

60+
const uint8_t* hww_data = NULL;
61+
uint8_t hww_frame[USB_REPORT_SIZE] = {0};
62+
5963
// If did not jump to firmware code, begin USB processing
6064
while (1) {
65+
if (hid_hww_read(&hww_frame[0])) {
66+
usb_packet_process((const USB_FRAME*)hww_frame);
67+
}
68+
if (!hww_data) {
69+
hww_data = queue_pull(queue_hww_queue());
70+
}
71+
if (hww_data) {
72+
if (hid_hww_write_poll(hww_data)) {
73+
hww_data = NULL;
74+
}
75+
}
6176
usb_processing_process(usb_processing_hww());
6277
}
6378
return 0;

src/firmware_main_loop.c

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,94 @@
1515
#include "firmware_main_loop.h"
1616

1717
#include "hardfault.h"
18+
#include "hid_hww.h"
1819
#include "hww.h"
1920
#include "touch/gestures.h"
20-
#include "u2f.h"
2121
#include "ui/screen_process.h"
2222
#include "ui/screen_stack.h"
23+
#include "usb/class/hid/hww/hid_hww.h"
2324
#include "usb/usb.h"
25+
#include "usb/usb_frame.h"
2426
#include "usb/usb_processing.h"
2527
#include "workflow/orientation_screen.h"
2628
#include <rust/rust.h>
29+
#if APP_U2F == 1
30+
#include "u2f.h"
31+
#include "u2f/u2f_packet.h"
32+
#include "usb/class/hid/u2f/hid_u2f.h"
33+
#endif
2734

2835
void firmware_main_loop(void)
2936
{
3037
// This starts the async orientation screen workflow, which is processed by the loop below.
3138
orientation_screen();
3239

33-
while (1) {
34-
screen_process();
35-
/* And finally, run the high-level event processing. */
36-
37-
rust_workflow_spin();
40+
const uint8_t* hww_data = NULL;
41+
uint8_t hww_frame[USB_REPORT_SIZE] = {0};
3842

39-
if (usb_is_enabled()) {
40-
rust_async_usb_spin();
43+
#if APP_U2F == 1
44+
u2f_packet_init();
45+
const uint8_t* u2f_data = NULL;
46+
uint8_t u2f_frame[USB_REPORT_SIZE] = {0};
47+
#endif
4148

42-
/* First, process all the incoming USB traffic. */
43-
usb_processing_process(usb_processing_hww());
49+
while (1) {
50+
// Do USB I/O
51+
if (!hww_data) {
52+
hww_data = queue_pull(queue_hww_queue());
53+
}
4454
#if APP_U2F == 1
45-
usb_processing_process(usb_processing_u2f());
55+
// Generate timeout packets
56+
uint32_t timeout_cid;
57+
while (u2f_packet_timeout_get(&timeout_cid)) {
58+
u2f_packet_timeout(timeout_cid);
59+
}
60+
if (!u2f_data) {
61+
u2f_data = queue_pull(queue_u2f_queue());
62+
}
4663
#endif
47-
/*
48-
* If USB has generated events at the application level,
49-
* process them now.
50-
*/
51-
hww_process();
64+
// Only read new messages if we have nothing to send
65+
if (!hww_data && hid_hww_read(&hww_frame[0])) {
66+
usb_packet_process((const USB_FRAME*)hww_frame);
67+
}
5268
#if APP_U2F == 1
53-
u2f_process();
69+
if (!u2f_data && hid_u2f_read(&u2f_frame[0])) {
70+
u2f_packet_process((const USB_FRAME*)u2f_frame);
71+
}
5472
#endif
73+
74+
if (hww_data) {
75+
if (hid_hww_write_poll(hww_data)) {
76+
hww_data = NULL;
77+
}
78+
}
79+
#if APP_U2F == 1
80+
if (u2f_data) {
81+
if (hid_u2f_write_poll(u2f_data)) {
82+
u2f_data = NULL;
83+
}
5584
}
85+
#endif
86+
87+
/* First, process all the incoming USB traffic. */
88+
usb_processing_process(usb_processing_hww());
89+
#if APP_U2F == 1
90+
usb_processing_process(usb_processing_u2f());
91+
#endif
92+
/*
93+
* If USB has generated events at the application level,
94+
* process them now.
95+
*/
96+
hww_process();
97+
#if APP_U2F == 1
98+
u2f_process();
99+
#endif
100+
101+
screen_process();
102+
/* And finally, run the high-level event processing. */
103+
104+
rust_workflow_spin();
105+
106+
rust_async_usb_spin();
56107
}
57108
}

src/u2f/u2f_packet.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ static void _reset_state(void)
6565
queue_clear(queue_u2f_queue());
6666
_timeout_disable(_in_state.cid);
6767
memset(&_in_state, 0, sizeof(_in_state));
68+
_in_state.buf_ptr = _in_state.data;
6869
}
6970

7071
/**
@@ -180,3 +181,8 @@ bool u2f_packet_process(const USB_FRAME* frame)
180181
}
181182
return false;
182183
}
184+
185+
void u2f_packet_init(void)
186+
{
187+
_reset_state();
188+
}

src/u2f/u2f_packet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,6 @@ void u2f_packet_timeout_enable(uint32_t cid);
5454
*/
5555
void u2f_invalid_endpoint(struct queue* queue, uint32_t cid);
5656

57+
void u2f_packet_init(void);
58+
5759
#endif

src/usb/class/hid/hid.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
struct usbdc_handler;
2727
struct usbdf_handler;
2828
struct usbdf_driver;
29+
struct usb_req;
30+
enum usb_ctrl_stage { USB_SETUP_STAGE = 0, USB_DATA_STAGE = 1, USB_STATUS_STAGE = 2 };
2931
typedef void (*FUNC_PTR)(void);
3032
#endif
3133

src/usb/class/hid/hww/hid_hww.c

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -51,68 +51,66 @@ static int32_t _request(uint8_t ep, struct usb_req* req, enum usb_ctrl_stage sta
5151
*/
5252
static struct usbdc_handler _request_handler = {NULL, (FUNC_PTR)_request};
5353

54-
// Stores the reports for the HWW interface.
55-
static uint8_t _out_report[USB_HID_REPORT_OUT_SIZE];
56-
57-
/**
58-
* Sets the buffer address for the incoming endpoint to `_out_report`.
54+
/*
55+
* Flags for communication between main loop and ISR
5956
*/
60-
static int32_t _read(void)
57+
static volatile bool _send_busy = false;
58+
static volatile bool _has_data = false;
59+
static volatile bool _request_in_flight = false;
60+
61+
// First time this function is called it initiates a transfer. Call it multiple times to poll for
62+
// completion. Once it returns true, there is data in the buffer.
63+
bool hid_hww_read(uint8_t* data)
6164
{
62-
return hid_read(&_func_data, _out_report, USB_HID_REPORT_OUT_SIZE);
65+
if (_request_in_flight && _has_data) {
66+
_request_in_flight = false;
67+
return true;
68+
}
69+
if (_request_in_flight) {
70+
return false;
71+
}
72+
if (hid_read(&_func_data, data, USB_HID_REPORT_OUT_SIZE) == ERR_NONE) {
73+
_has_data = false;
74+
_request_in_flight = true;
75+
}
76+
return false;
6377
}
6478

65-
/** Set when the send channel is busy sending data. */
66-
static bool _send_busy = false;
67-
6879
/**
6980
* Sends the next frame, if the USB interface is ready.
7081
*/
71-
static void _send_next(void)
82+
bool hid_hww_write_poll(const uint8_t* data)
7283
{
84+
ASSERT(data);
7385
if (_send_busy) {
74-
/*
75-
* We can't send yet. Whenever the current sender finished, it will
76-
* flush anything that's still queued.
77-
*/
78-
return;
86+
return false;
7987
}
80-
const uint8_t* data = queue_pull(queue_hww_queue());
81-
if (data != NULL) {
88+
if (hid_write(&_func_data, data, USB_HID_REPORT_OUT_SIZE) == ERR_NONE) {
8289
_send_busy = true;
83-
hid_write(&_func_data, data, USB_HID_REPORT_OUT_SIZE);
90+
return true;
8491
}
92+
return false;
8593
}
8694

8795
/**
8896
* The callback function is called after usb data has been received (endpoint = OUT).
89-
* This is a result of calling _read().
90-
* The received data is stored in '_out_report'.
9197
*/
92-
static uint8_t _out(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
98+
static uint8_t _rx_cb(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
9399
{
94100
(void)ep;
95101
(void)rc;
96102
(void)count;
97-
usb_packet_process((const USB_FRAME*)_out_report);
98-
/* Incoming data has been processed completely. Start a new read. */
99-
_read();
103+
_has_data = true;
100104
return ERR_NONE;
101105
}
102106

103107
/**
104108
* Called when a usb frame has been replied to the host via the HWW interface
105109
* and the device is ready to send the next frame.
106110
*/
107-
static void _sent_done(void)
111+
static void _tx_cb(void)
108112
{
109113
_send_busy = false;
110-
/*
111-
* If there is more data queued, push it immediately to save some time.
112-
* Otherwise, sending will stop until somebody explicitely queues
113-
* a frame again.
114-
*/
115-
_send_next();
116114
}
117115

118116
/**
@@ -135,14 +133,10 @@ int32_t hid_hww_init(void (*callback)(void))
135133
*/
136134
void hid_hww_setup(void)
137135
{
138-
hid_hww_register_callback(HID_CB_READ, (FUNC_PTR)_out);
139-
// usb_report_sent is called when the outgoing usb frame is fully transmitted.
140-
hid_hww_register_callback(HID_CB_WRITE, (FUNC_PTR)_sent_done);
141-
142-
usb_processing_set_send(usb_processing_hww(), _send_next);
143-
144-
// Wait for data
145-
_read();
136+
// RX callback is called when there is data available to read
137+
hid_hww_register_callback(HID_CB_READ, (FUNC_PTR)_rx_cb);
138+
// TX callback is called when data has been sent
139+
hid_hww_register_callback(HID_CB_WRITE, (FUNC_PTR)_tx_cb);
146140
}
147141

148142
/**

src/usb/class/hid/hww/hid_hww.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,20 @@ int32_t hid_hww_register_callback(enum hid_trans_type trans_type, FUNC_PTR func)
6060
*/
6161
void hid_hww_setup(void);
6262

63+
/**
64+
* Send out data
65+
* returns true if data sent out, false if busy (need retry)
66+
*/
67+
bool hid_hww_write_poll(const uint8_t* data);
68+
69+
/**
70+
* Read data
71+
*
72+
* data must fit 64 bytes data.
73+
* Returns true if there is valid data in the buffer. data is invalidated when this is called again.
74+
* Returns false if USB subsystem was not ready to receive or there is a request in flight and data
75+
* is not.
76+
*/
77+
bool hid_hww_read(uint8_t* data);
78+
6379
#endif

0 commit comments

Comments
 (0)