|
|
@@ -52,11 +52,12 @@ uint8_t extra_report_blank[3] = {0}; |
|
|
|
#endif /* EXTRAKEY_ENABLE */ |
|
|
|
|
|
|
|
#ifdef CONSOLE_ENABLE |
|
|
|
/* The emission queue */ |
|
|
|
output_queue_t console_queue; |
|
|
|
static uint8_t console_queue_buffer[CONSOLE_QUEUE_BUFFER_SIZE]; |
|
|
|
/* The emission buffers queue */ |
|
|
|
output_buffers_queue_t console_buf_queue; |
|
|
|
static uint8_t console_queue_buffer[BQ_BUFFER_SIZE(CONSOLE_QUEUE_CAPACITY, CONSOLE_EPSIZE)]; |
|
|
|
|
|
|
|
static virtual_timer_t console_flush_timer; |
|
|
|
void console_queue_onotify(io_queue_t *qp); |
|
|
|
void console_queue_onotify(io_buffers_queue_t *bqp); |
|
|
|
static void console_flush_cb(void *arg); |
|
|
|
#endif /* CONSOLE_ENABLE */ |
|
|
|
|
|
|
@@ -1019,7 +1020,7 @@ void init_usb_driver(USBDriver *usbp) { |
|
|
|
|
|
|
|
chVTObjectInit(&keyboard_idle_timer); |
|
|
|
#ifdef CONSOLE_ENABLE |
|
|
|
oqObjectInit(&console_queue, console_queue_buffer, sizeof(console_queue_buffer), console_queue_onotify, (void *)usbp); |
|
|
|
obqObjectInit(&console_buf_queue, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp); |
|
|
|
chVTObjectInit(&console_flush_timer); |
|
|
|
#endif |
|
|
|
} |
|
|
@@ -1093,10 +1094,7 @@ static void keyboard_idle_timer_cb(void *arg) { |
|
|
|
if(keyboard_idle) { |
|
|
|
#endif /* NKRO_ENABLE */ |
|
|
|
/* TODO: are we sure we want the KBD_ENDPOINT? */ |
|
|
|
osalSysUnlockFromISR(); |
|
|
|
usbPrepareTransmit(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent)); |
|
|
|
osalSysLockFromISR(); |
|
|
|
usbStartTransmitI(usbp, KBD_ENDPOINT); |
|
|
|
usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent)); |
|
|
|
/* rearm the timer */ |
|
|
|
chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp); |
|
|
|
} |
|
|
@@ -1121,26 +1119,28 @@ void send_keyboard(report_keyboard_t *report) { |
|
|
|
} |
|
|
|
osalSysUnlock(); |
|
|
|
|
|
|
|
bool ep_not_ready; |
|
|
|
#ifdef NKRO_ENABLE |
|
|
|
if(keyboard_nkro) { /* NKRO protocol */ |
|
|
|
usbPrepareTransmit(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t)); |
|
|
|
/* need to wait until the previous packet has made it through */ |
|
|
|
do { |
|
|
|
osalSysLock(); |
|
|
|
ep_not_ready = usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT); |
|
|
|
osalSysUnlock(); |
|
|
|
} while (ep_not_ready); |
|
|
|
/* can rewrite this using the synchronous API, then would wait |
|
|
|
* until *after* the packet has been transmitted. I think |
|
|
|
* this is more efficient */ |
|
|
|
/* busy wait, should be short and not very common */ |
|
|
|
osalSysLock(); |
|
|
|
while(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT)) |
|
|
|
; |
|
|
|
usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t)); |
|
|
|
osalSysUnlock(); |
|
|
|
} else |
|
|
|
#endif /* NKRO_ENABLE */ |
|
|
|
{ /* boot protocol */ |
|
|
|
usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE); |
|
|
|
/* need to wait until the previous packet has made it through */ |
|
|
|
do { |
|
|
|
osalSysLock(); |
|
|
|
ep_not_ready = usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT); |
|
|
|
osalSysUnlock(); |
|
|
|
} while (ep_not_ready); |
|
|
|
/* busy wait, should be short and not very common */ |
|
|
|
osalSysLock(); |
|
|
|
while(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT)) |
|
|
|
; |
|
|
|
usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE); |
|
|
|
osalSysUnlock(); |
|
|
|
} |
|
|
|
keyboard_report_sent = *report; |
|
|
|
} |
|
|
@@ -1171,9 +1171,8 @@ void send_mouse(report_mouse_t *report) { |
|
|
|
* is this really needed? |
|
|
|
*/ |
|
|
|
|
|
|
|
usbPrepareTransmit(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t)); |
|
|
|
osalSysLock(); |
|
|
|
usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT); |
|
|
|
usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t)); |
|
|
|
osalSysUnlock(); |
|
|
|
} |
|
|
|
|
|
|
@@ -1209,10 +1208,7 @@ static void send_extra_report(uint8_t report_id, uint16_t data) { |
|
|
|
.usage = data |
|
|
|
}; |
|
|
|
|
|
|
|
osalSysUnlock(); |
|
|
|
usbPrepareTransmit(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t)); |
|
|
|
osalSysLock(); |
|
|
|
usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT); |
|
|
|
usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t)); |
|
|
|
osalSysUnlock(); |
|
|
|
} |
|
|
|
|
|
|
@@ -1240,20 +1236,32 @@ void send_consumer(uint16_t data) { |
|
|
|
|
|
|
|
#ifdef CONSOLE_ENABLE |
|
|
|
|
|
|
|
/* debug IN callback hander */ |
|
|
|
/* console IN callback hander */ |
|
|
|
void console_in_cb(USBDriver *usbp, usbep_t ep) { |
|
|
|
(void)ep; |
|
|
|
(void)ep; /* should have ep == CONSOLE_ENDPOINT, so use that to save time/space */ |
|
|
|
uint8_t *buf; |
|
|
|
size_t n; |
|
|
|
|
|
|
|
osalSysLockFromISR(); |
|
|
|
|
|
|
|
/* rearm the timer */ |
|
|
|
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); |
|
|
|
|
|
|
|
/* Check if there is data to send left in the output queue */ |
|
|
|
if(chOQGetFullI(&console_queue) >= CONSOLE_EPSIZE) { |
|
|
|
osalSysUnlockFromISR(); |
|
|
|
usbPrepareQueuedTransmit(usbp, CONSOLE_ENDPOINT, &console_queue, CONSOLE_EPSIZE); |
|
|
|
osalSysLockFromISR(); |
|
|
|
usbStartTransmitI(usbp, CONSOLE_ENDPOINT); |
|
|
|
/* Freeing the buffer just transmitted, if it was not a zero size packet.*/ |
|
|
|
if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) { |
|
|
|
obqReleaseEmptyBufferI(&console_buf_queue); |
|
|
|
} |
|
|
|
|
|
|
|
/* Checking if there is a buffer ready for transmission.*/ |
|
|
|
buf = obqGetFullBufferI(&console_buf_queue, &n); |
|
|
|
|
|
|
|
if (buf != NULL) { |
|
|
|
/* The endpoint cannot be busy, we are in the context of the callback, |
|
|
|
so it is safe to transmit without a check.*/ |
|
|
|
/* Should have n == CONSOLE_EPSIZE; check it? */ |
|
|
|
usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE); |
|
|
|
} else { |
|
|
|
/* Nothing to transmit.*/ |
|
|
|
} |
|
|
|
|
|
|
|
osalSysUnlockFromISR(); |
|
|
@@ -1261,18 +1269,22 @@ void console_in_cb(USBDriver *usbp, usbep_t ep) { |
|
|
|
|
|
|
|
/* Callback when data is inserted into the output queue |
|
|
|
* Called from a locked state */ |
|
|
|
void console_queue_onotify(io_queue_t *qp) { |
|
|
|
USBDriver *usbp = qGetLink(qp); |
|
|
|
void console_queue_onotify(io_buffers_queue_t *bqp) { |
|
|
|
size_t n; |
|
|
|
USBDriver *usbp = bqGetLinkX(bqp); |
|
|
|
|
|
|
|
if(usbGetDriverStateI(usbp) != USB_ACTIVE) |
|
|
|
return; |
|
|
|
|
|
|
|
if(!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT) |
|
|
|
&& (chOQGetFullI(&console_queue) >= CONSOLE_EPSIZE)) { |
|
|
|
osalSysUnlock(); |
|
|
|
usbPrepareQueuedTransmit(usbp, CONSOLE_ENDPOINT, &console_queue, CONSOLE_EPSIZE); |
|
|
|
osalSysLock(); |
|
|
|
usbStartTransmitI(usbp, CONSOLE_ENDPOINT); |
|
|
|
/* Checking if there is already a transaction ongoing on the endpoint.*/ |
|
|
|
if (!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) { |
|
|
|
/* Trying to get a full buffer.*/ |
|
|
|
uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n); |
|
|
|
if (buf != NULL) { |
|
|
|
/* Buffer found, starting a new transaction.*/ |
|
|
|
/* Should have n == CONSOLE_EPSIZE; check this? */ |
|
|
|
usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -1280,8 +1292,6 @@ void console_queue_onotify(io_queue_t *qp) { |
|
|
|
* callback (called from ISR, unlocked state) */ |
|
|
|
static void console_flush_cb(void *arg) { |
|
|
|
USBDriver *usbp = (USBDriver *)arg; |
|
|
|
size_t i, n; |
|
|
|
uint8_t buf[CONSOLE_EPSIZE]; /* TODO: a solution without extra buffer? */ |
|
|
|
osalSysLockFromISR(); |
|
|
|
|
|
|
|
/* check that the states of things are as they're supposed to */ |
|
|
@@ -1292,23 +1302,28 @@ static void console_flush_cb(void *arg) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* don't do anything if the queue is empty or has enough stuff in it */ |
|
|
|
if(((n = oqGetFullI(&console_queue)) == 0) || (n >= CONSOLE_EPSIZE)) { |
|
|
|
/* If there is already a transaction ongoing then another one cannot be |
|
|
|
started.*/ |
|
|
|
if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) { |
|
|
|
/* rearm the timer */ |
|
|
|
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); |
|
|
|
osalSysUnlockFromISR(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* there's stuff hanging in the queue - so dequeue and send */ |
|
|
|
for(i = 0; i < n; i++) |
|
|
|
buf[i] = (uint8_t)oqGetI(&console_queue); |
|
|
|
for(i = n; i < CONSOLE_EPSIZE; i++) |
|
|
|
buf[i] = 0; |
|
|
|
osalSysUnlockFromISR(); |
|
|
|
usbPrepareTransmit(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE); |
|
|
|
osalSysLockFromISR(); |
|
|
|
(void)usbStartTransmitI(usbp, CONSOLE_ENDPOINT); |
|
|
|
/* Checking if there only a buffer partially filled, if so then it is |
|
|
|
enforced in the queue and transmitted.*/ |
|
|
|
if(obqTryFlushI(&console_buf_queue)) { |
|
|
|
size_t n,i; |
|
|
|
uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n); |
|
|
|
|
|
|
|
osalDbgAssert(buf != NULL, "queue is empty"); |
|
|
|
|
|
|
|
/* zero the rest of the buffer (buf should point to allocated space) */ |
|
|
|
for(i=n; i<CONSOLE_EPSIZE; i++) |
|
|
|
buf[i]=0; |
|
|
|
usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE); |
|
|
|
} |
|
|
|
|
|
|
|
/* rearm the timer */ |
|
|
|
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); |
|
|
@@ -1329,7 +1344,7 @@ int8_t sendchar(uint8_t c) { |
|
|
|
* for USB/HIDRAW to dequeue). Another possibility |
|
|
|
* for fixing this kind of thing is to increase |
|
|
|
* CONSOLE_QUEUE_CAPACITY. */ |
|
|
|
return(chOQPutTimeout(&console_queue, c, US2ST(5))); |
|
|
|
return(obqPutTimeout(&console_buf_queue, c, US2ST(100))); |
|
|
|
} |
|
|
|
|
|
|
|
#else /* CONSOLE_ENABLE */ |