]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
Chibios: Update to new USB API.
authorflabbergast <s3+flabbergast@sdfeu.org>
Fri, 15 Jan 2016 21:41:51 +0000 (21:41 +0000)
committerflabbergast <s3+flabbergast@sdfeu.org>
Fri, 15 Jan 2016 21:41:51 +0000 (21:41 +0000)
tmk_core/protocol/chibios/usb_main.c

index ee2788e5247711b04242ff31e865081f8f53bd7c..9097d4e844ca58c075088bc504ac9c0113bb8de1 100644 (file)
@@ -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 */