Skip to content

Commit 2525d5d

Browse files
committed
Chibios: Update to new USB API.
1 parent 2fc5cd6 commit 2525d5d

File tree

1 file changed

+73
-58
lines changed

1 file changed

+73
-58
lines changed

protocol/chibios/usb_main.c

Lines changed: 73 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ uint8_t extra_report_blank[3] = {0};
5252
#endif /* EXTRAKEY_ENABLE */
5353

5454
#ifdef CONSOLE_ENABLE
55-
/* The emission queue */
56-
output_queue_t console_queue;
57-
static uint8_t console_queue_buffer[CONSOLE_QUEUE_BUFFER_SIZE];
55+
/* The emission buffers queue */
56+
output_buffers_queue_t console_buf_queue;
57+
static uint8_t console_queue_buffer[BQ_BUFFER_SIZE(CONSOLE_QUEUE_CAPACITY, CONSOLE_EPSIZE)];
58+
5859
static virtual_timer_t console_flush_timer;
59-
void console_queue_onotify(io_queue_t *qp);
60+
void console_queue_onotify(io_buffers_queue_t *bqp);
6061
static void console_flush_cb(void *arg);
6162
#endif /* CONSOLE_ENABLE */
6263

@@ -1019,7 +1020,7 @@ void init_usb_driver(USBDriver *usbp) {
10191020

10201021
chVTObjectInit(&keyboard_idle_timer);
10211022
#ifdef CONSOLE_ENABLE
1022-
oqObjectInit(&console_queue, console_queue_buffer, sizeof(console_queue_buffer), console_queue_onotify, (void *)usbp);
1023+
obqObjectInit(&console_buf_queue, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
10231024
chVTObjectInit(&console_flush_timer);
10241025
#endif
10251026
}
@@ -1093,10 +1094,7 @@ static void keyboard_idle_timer_cb(void *arg) {
10931094
if(keyboard_idle) {
10941095
#endif /* NKRO_ENABLE */
10951096
/* TODO: are we sure we want the KBD_ENDPOINT? */
1096-
osalSysUnlockFromISR();
1097-
usbPrepareTransmit(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent));
1098-
osalSysLockFromISR();
1099-
usbStartTransmitI(usbp, KBD_ENDPOINT);
1097+
usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent));
11001098
/* rearm the timer */
11011099
chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
11021100
}
@@ -1121,26 +1119,28 @@ void send_keyboard(report_keyboard_t *report) {
11211119
}
11221120
osalSysUnlock();
11231121

1124-
bool ep_not_ready;
11251122
#ifdef NKRO_ENABLE
11261123
if(keyboard_nkro) { /* NKRO protocol */
1127-
usbPrepareTransmit(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
11281124
/* need to wait until the previous packet has made it through */
1129-
do {
1130-
osalSysLock();
1131-
ep_not_ready = usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT);
1132-
osalSysUnlock();
1133-
} while (ep_not_ready);
1125+
/* can rewrite this using the synchronous API, then would wait
1126+
* until *after* the packet has been transmitted. I think
1127+
* this is more efficient */
1128+
/* busy wait, should be short and not very common */
1129+
osalSysLock();
1130+
while(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT))
1131+
;
1132+
usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
1133+
osalSysUnlock();
11341134
} else
11351135
#endif /* NKRO_ENABLE */
11361136
{ /* boot protocol */
1137-
usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
11381137
/* need to wait until the previous packet has made it through */
1139-
do {
1140-
osalSysLock();
1141-
ep_not_ready = usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT);
1142-
osalSysUnlock();
1143-
} while (ep_not_ready);
1138+
/* busy wait, should be short and not very common */
1139+
osalSysLock();
1140+
while(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT))
1141+
;
1142+
usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
1143+
osalSysUnlock();
11441144
}
11451145
keyboard_report_sent = *report;
11461146
}
@@ -1171,9 +1171,8 @@ void send_mouse(report_mouse_t *report) {
11711171
* is this really needed?
11721172
*/
11731173

1174-
usbPrepareTransmit(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
11751174
osalSysLock();
1176-
usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT);
1175+
usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
11771176
osalSysUnlock();
11781177
}
11791178

@@ -1209,10 +1208,7 @@ static void send_extra_report(uint8_t report_id, uint16_t data) {
12091208
.usage = data
12101209
};
12111210

1212-
osalSysUnlock();
1213-
usbPrepareTransmit(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t));
1214-
osalSysLock();
1215-
usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT);
1211+
usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t));
12161212
osalSysUnlock();
12171213
}
12181214

@@ -1240,48 +1236,62 @@ void send_consumer(uint16_t data) {
12401236

12411237
#ifdef CONSOLE_ENABLE
12421238

1243-
/* debug IN callback hander */
1239+
/* console IN callback hander */
12441240
void console_in_cb(USBDriver *usbp, usbep_t ep) {
1245-
(void)ep;
1241+
(void)ep; /* should have ep == CONSOLE_ENDPOINT, so use that to save time/space */
1242+
uint8_t *buf;
1243+
size_t n;
1244+
12461245
osalSysLockFromISR();
12471246

12481247
/* rearm the timer */
12491248
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
12501249

1251-
/* Check if there is data to send left in the output queue */
1252-
if(chOQGetFullI(&console_queue) >= CONSOLE_EPSIZE) {
1253-
osalSysUnlockFromISR();
1254-
usbPrepareQueuedTransmit(usbp, CONSOLE_ENDPOINT, &console_queue, CONSOLE_EPSIZE);
1255-
osalSysLockFromISR();
1256-
usbStartTransmitI(usbp, CONSOLE_ENDPOINT);
1250+
/* Freeing the buffer just transmitted, if it was not a zero size packet.*/
1251+
if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) {
1252+
obqReleaseEmptyBufferI(&console_buf_queue);
1253+
}
1254+
1255+
/* Checking if there is a buffer ready for transmission.*/
1256+
buf = obqGetFullBufferI(&console_buf_queue, &n);
1257+
1258+
if (buf != NULL) {
1259+
/* The endpoint cannot be busy, we are in the context of the callback,
1260+
so it is safe to transmit without a check.*/
1261+
/* Should have n == CONSOLE_EPSIZE; check it? */
1262+
usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1263+
} else {
1264+
/* Nothing to transmit.*/
12571265
}
12581266

12591267
osalSysUnlockFromISR();
12601268
}
12611269

12621270
/* Callback when data is inserted into the output queue
12631271
* Called from a locked state */
1264-
void console_queue_onotify(io_queue_t *qp) {
1265-
USBDriver *usbp = qGetLink(qp);
1272+
void console_queue_onotify(io_buffers_queue_t *bqp) {
1273+
size_t n;
1274+
USBDriver *usbp = bqGetLinkX(bqp);
12661275

12671276
if(usbGetDriverStateI(usbp) != USB_ACTIVE)
12681277
return;
12691278

1270-
if(!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)
1271-
&& (chOQGetFullI(&console_queue) >= CONSOLE_EPSIZE)) {
1272-
osalSysUnlock();
1273-
usbPrepareQueuedTransmit(usbp, CONSOLE_ENDPOINT, &console_queue, CONSOLE_EPSIZE);
1274-
osalSysLock();
1275-
usbStartTransmitI(usbp, CONSOLE_ENDPOINT);
1279+
/* Checking if there is already a transaction ongoing on the endpoint.*/
1280+
if (!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
1281+
/* Trying to get a full buffer.*/
1282+
uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
1283+
if (buf != NULL) {
1284+
/* Buffer found, starting a new transaction.*/
1285+
/* Should have n == CONSOLE_EPSIZE; check this? */
1286+
usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1287+
}
12761288
}
12771289
}
12781290

12791291
/* Flush timer code
12801292
* callback (called from ISR, unlocked state) */
12811293
static void console_flush_cb(void *arg) {
12821294
USBDriver *usbp = (USBDriver *)arg;
1283-
size_t i, n;
1284-
uint8_t buf[CONSOLE_EPSIZE]; /* TODO: a solution without extra buffer? */
12851295
osalSysLockFromISR();
12861296

12871297
/* check that the states of things are as they're supposed to */
@@ -1292,23 +1302,28 @@ static void console_flush_cb(void *arg) {
12921302
return;
12931303
}
12941304

1295-
/* don't do anything if the queue is empty or has enough stuff in it */
1296-
if(((n = oqGetFullI(&console_queue)) == 0) || (n >= CONSOLE_EPSIZE)) {
1305+
/* If there is already a transaction ongoing then another one cannot be
1306+
started.*/
1307+
if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
12971308
/* rearm the timer */
12981309
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
12991310
osalSysUnlockFromISR();
13001311
return;
13011312
}
13021313

1303-
/* there's stuff hanging in the queue - so dequeue and send */
1304-
for(i = 0; i < n; i++)
1305-
buf[i] = (uint8_t)oqGetI(&console_queue);
1306-
for(i = n; i < CONSOLE_EPSIZE; i++)
1307-
buf[i] = 0;
1308-
osalSysUnlockFromISR();
1309-
usbPrepareTransmit(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1310-
osalSysLockFromISR();
1311-
(void)usbStartTransmitI(usbp, CONSOLE_ENDPOINT);
1314+
/* Checking if there only a buffer partially filled, if so then it is
1315+
enforced in the queue and transmitted.*/
1316+
if(obqTryFlushI(&console_buf_queue)) {
1317+
size_t n,i;
1318+
uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
1319+
1320+
osalDbgAssert(buf != NULL, "queue is empty");
1321+
1322+
/* zero the rest of the buffer (buf should point to allocated space) */
1323+
for(i=n; i<CONSOLE_EPSIZE; i++)
1324+
buf[i]=0;
1325+
usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
1326+
}
13121327

13131328
/* rearm the timer */
13141329
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
@@ -1329,7 +1344,7 @@ int8_t sendchar(uint8_t c) {
13291344
* for USB/HIDRAW to dequeue). Another possibility
13301345
* for fixing this kind of thing is to increase
13311346
* CONSOLE_QUEUE_CAPACITY. */
1332-
return(chOQPutTimeout(&console_queue, c, US2ST(5)));
1347+
return(obqPutTimeout(&console_buf_queue, c, US2ST(100)));
13331348
}
13341349

13351350
#else /* CONSOLE_ENABLE */

0 commit comments

Comments
 (0)