Browse Source

Chibios: Update to new USB API.

tags/v2.9
flabbergast 8 years ago
parent
commit
5ef7d89406
1 changed files with 73 additions and 58 deletions
  1. 73
    58
      tmk_core/protocol/chibios/usb_main.c

+ 73
- 58
tmk_core/protocol/chibios/usb_main.c View File

#endif /* EXTRAKEY_ENABLE */ #endif /* EXTRAKEY_ENABLE */


#ifdef CONSOLE_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; 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); static void console_flush_cb(void *arg);
#endif /* CONSOLE_ENABLE */ #endif /* CONSOLE_ENABLE */




chVTObjectInit(&keyboard_idle_timer); chVTObjectInit(&keyboard_idle_timer);
#ifdef CONSOLE_ENABLE #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); chVTObjectInit(&console_flush_timer);
#endif #endif
} }
if(keyboard_idle) { if(keyboard_idle) {
#endif /* NKRO_ENABLE */ #endif /* NKRO_ENABLE */
/* TODO: are we sure we want the KBD_ENDPOINT? */ /* 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 */ /* rearm the timer */
chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp); chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
} }
} }
osalSysUnlock(); osalSysUnlock();


bool ep_not_ready;
#ifdef NKRO_ENABLE #ifdef NKRO_ENABLE
if(keyboard_nkro) { /* NKRO protocol */ 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 */ /* 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 } else
#endif /* NKRO_ENABLE */ #endif /* NKRO_ENABLE */
{ /* boot protocol */ { /* boot protocol */
usbPrepareTransmit(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
/* need to wait until the previous packet has made it through */ /* 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; keyboard_report_sent = *report;
} }
* is this really needed? * is this really needed?
*/ */


usbPrepareTransmit(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
osalSysLock(); osalSysLock();
usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT);
usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
osalSysUnlock(); osalSysUnlock();
} }


.usage = 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(); osalSysUnlock();
} }




#ifdef CONSOLE_ENABLE #ifdef CONSOLE_ENABLE


/* debug IN callback hander */
/* console IN callback hander */
void console_in_cb(USBDriver *usbp, usbep_t ep) { 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(); osalSysLockFromISR();


/* rearm the timer */ /* rearm the timer */
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); 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(); osalSysUnlockFromISR();


/* Callback when data is inserted into the output queue /* Callback when data is inserted into the output queue
* Called from a locked state */ * 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) if(usbGetDriverStateI(usbp) != USB_ACTIVE)
return; 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);
}
} }
} }


* callback (called from ISR, unlocked state) */ * callback (called from ISR, unlocked state) */
static void console_flush_cb(void *arg) { static void console_flush_cb(void *arg) {
USBDriver *usbp = (USBDriver *)arg; USBDriver *usbp = (USBDriver *)arg;
size_t i, n;
uint8_t buf[CONSOLE_EPSIZE]; /* TODO: a solution without extra buffer? */
osalSysLockFromISR(); osalSysLockFromISR();


/* check that the states of things are as they're supposed to */ /* check that the states of things are as they're supposed to */
return; 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 */ /* rearm the timer */
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
osalSysUnlockFromISR(); osalSysUnlockFromISR();
return; 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 */ /* rearm the timer */
chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp); chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
* for USB/HIDRAW to dequeue). Another possibility * for USB/HIDRAW to dequeue). Another possibility
* for fixing this kind of thing is to increase * for fixing this kind of thing is to increase
* CONSOLE_QUEUE_CAPACITY. */ * CONSOLE_QUEUE_CAPACITY. */
return(chOQPutTimeout(&console_queue, c, US2ST(5)));
return(obqPutTimeout(&console_buf_queue, c, US2ST(100)));
} }


#else /* CONSOLE_ENABLE */ #else /* CONSOLE_ENABLE */

Loading…
Cancel
Save