Beispiel #1
0
/**
 * @brief   Default data transmitted callback.
 * @details The application must use this function as callback for the IN
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
  size_t n;
  SerialUSBDriver *sdup = usbp->param;

  (void)ep;

  chSysLockFromIsr();
  chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);

  if ((n = chOQGetFullI(&sdup->oqueue)) > 0) {
    /* The endpoint cannot be busy, we are in the context of the callback,
       so it is safe to transmit without a check.*/
    chSysUnlockFromIsr();

    usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, n);

    chSysLockFromIsr();
    usbStartTransmitI(usbp, ep);
  }
  else if (!(usbp->epc[ep]->in_state->txsize &
            (usbp->epc[ep]->in_maxsize - 1))) {
    /* Transmit zero sized packet in case the last one has maximum allowed
       size. Otherwise the recipient may expect more data coming soon and
       not return buffered data to app. See section 5.8.3 Bulk Transfer
       Packet Size Constraints of the USB Specification document.*/
    chSysUnlockFromIsr();

    usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, 0);

    chSysLockFromIsr();
    usbStartTransmitI(usbp, ep);
  }

  chSysUnlockFromIsr();
}
/**
 * @brief   Notification of data inserted into the output queue.
 *
 * @param[in] qp        the queue pointer.
 */
static void onotify(io_queue_t *qp) {
  size_t n;
  HIDDebugDriver *hiddp = qGetLink(qp);

  /* If the USB driver is not in the appropriate state then transactions
   * must not be started.*/
  if((usbGetDriverStateI(hiddp->config->usbp) != USB_ACTIVE) ||
     (hiddp->state != HIDDEBUG_READY)) {
    return;
  }

  /* If there is not an ongoing transaction and the output queue contains
   * enough data then a new transaction is started.*/
  if(!usbGetTransmitStatusI(hiddp->config->usbp, hiddp->config->ep_in)) {
    if((n = oqGetFullI(&hiddp->oqueue)) >= DEBUG_TX_SIZE) {
      osalSysUnlock();

      usbPrepareQueuedTransmit(hiddp->config->usbp,
                               hiddp->config->ep_in,
                               &hiddp->oqueue, DEBUG_TX_SIZE);

      osalSysLock();
      (void)usbStartTransmitI(hiddp->config->usbp, hiddp->config->ep_in);
    }
  }
}
static void msc_sendstatus(USBDriver *usbp) {

  msc_state = MSC_SENDING_CSW;
  chSysLockFromIsr();
  usbStartTransmitI(usbp, MSC_DATA_IN_EP, (uint8_t *)&CSW, sizeof CSW);
  chSysUnlockFromIsr();
}
/**
 * @brief   Default data transmitted callback.
 * @details The application must use this function as callback for the IN
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void hidDebugDataTransmitted(USBDriver *usbp, usbep_t ep) {
  HIDDebugDriver *hiddp = usbp->in_params[ep - 1U];
  size_t n;

  if(hiddp == NULL) {
    return;
  }

  osalSysLockFromISR();

  /* rearm the flush timer */
  chVTSetI(&hid_debug_flush_timer, MS2ST(DEBUG_TX_FLUSH_MS), hid_debug_flush_cb, hiddp);

  /* see if we've transmitted everything */
  if((n = oqGetFullI(&hiddp->oqueue)) == 0) {
    chnAddFlagsI(hiddp, CHN_OUTPUT_EMPTY);
  }

  /* Check if there's enough data in the queue to send again */
  if(n >= DEBUG_TX_SIZE) {
    /* The endpoint cannot be busy, we are in the context of the callback,
     * so it is safe to transmit without a check.*/
    osalSysUnlockFromISR();

    usbPrepareQueuedTransmit(usbp, ep, &hiddp->oqueue, DEBUG_TX_SIZE);

    osalSysLockFromISR();
    (void)usbStartTransmitI(usbp, ep);
  }

  osalSysUnlockFromISR();
}
/**
 * @brief   Notification of data inserted into the output queue.
 *
 * @param[in] qp        the queue pointer.
 */
static void onotify(io_queue_t *qp) {
  size_t n;
  SerialUSBDriver *sdup = qGetLink(qp);

  /* If the USB driver is not in the appropriate state then transactions
     must not be started.*/
  if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) ||
      (sdup->state != SDU_READY)) {
    return;
  }

  /* If there is not an ongoing transaction and the output queue contains
     data then a new transaction is started.*/
  if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
    if ((n = oqGetFullI(&sdup->oqueue)) > 0U) {
      osalSysUnlock();

      usbPrepareQueuedTransmit(sdup->config->usbp,
                               sdup->config->bulk_in,
                               &sdup->oqueue, n);

      osalSysLock();
      (void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in);
    }
  }
}
Beispiel #6
0
/**
 * @brief   SOF handler.
 * @details The SOF interrupt is used for automatic flushing of incomplete
 *          buffers pending in the output queue.
 *
 * @param[in] sdup      pointer to a @p SerialUSBDriver object
 *
 * @iclass
 */
void sduSOFHookI(SerialUSBDriver *sdup) {

  /* If the USB driver is not in the appropriate state then transactions
     must not be started.*/
  if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) ||
      (sdup->state != SDU_READY)) {
    return;
  }

  /* If there is already a transaction ongoing then another one cannot be
     started.*/
  if (usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
    return;
  }

  /* Checking if there only a buffer partially filled, if so then it is
     enforced in the queue and transmitted.*/
  if (obqTryFlushI(&sdup->obqueue)) {
    size_t n;
    uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n);

    osalDbgAssert(buf != NULL, "queue is empty");

    usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
  }
}
Beispiel #7
0
/**
 * @brief   Default EP0 OUT callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 OUT events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0out(USBDriver *usbp, usbep_t ep) {

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_RX:
    /* Receive phase over, sending the zero sized status packet.*/
    usbp->ep0state = USB_EP0_SENDING_STS;
    usbPrepareTransmit(usbp, 0, NULL, 0);
    chSysLockFromIsr();
    usbStartTransmitI(usbp, 0);
    chSysUnlockFromIsr();
    return;
  case USB_EP0_WAITING_STS:
    /* Status packet received, it must be zero sized, invoking the callback
       if defined.*/
    if (usbGetReceiveTransactionSizeI(usbp, 0) != 0)
      break;
    if (usbp->ep0endcb != NULL)
      usbp->ep0endcb(usbp);
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  default:
    ;
  }
  /* Error response, the state machine goes into an error state, the low
     level layer will have to reset it to USB_EP0_WAITING_SETUP after
     receiving a SETUP packet.*/
  usb_lld_stall_in(usbp, 0);
  usb_lld_stall_out(usbp, 0);
  _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
  usbp->ep0state = USB_EP0_ERROR;
}
Beispiel #8
0
void hid_transmit(USBDriver *usbp) {
    usbPrepareTransmit(usbp, HID_IN_EP_ADDRESS, (uint8_t *)&hid_in_data, sizeof (hid_in_data));
	chSysLockFromISR();
	usbStartTransmitI(usbp, HID_IN_EP_ADDRESS);
    palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
    palClearPad(GPIOD, 14);
	chSysUnlockFromISR();
}
Beispiel #9
0
/**
 * @brief   Default EP0 IN callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 IN events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
  size_t max;

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_TX:
    max = (size_t)get_hword(&usbp->setup[6]);
    /* If the transmitted size is less than the requested size and it is a
       multiple of the maximum packet size then a zero size packet must be
       transmitted.*/
    if ((usbp->ep0n < max) &&
        ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) {
      usbPrepareTransmit(usbp, 0, NULL, 0);
      osalSysLockFromISR();
      (void) usbStartTransmitI(usbp, 0);
      osalSysUnlockFromISR();
      usbp->ep0state = USB_EP0_WAITING_TX0;
      return;
    }
    /* Falls into, it is intentional.*/
  case USB_EP0_WAITING_TX0:
    /* Transmit phase over, receiving the zero sized status packet.*/
    usbp->ep0state = USB_EP0_WAITING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
    usbPrepareReceive(usbp, 0, NULL, 0);
    osalSysLockFromISR();
    (void) usbStartReceiveI(usbp, 0);
    osalSysUnlockFromISR();
#else
    usb_lld_end_setup(usbp, ep);
#endif
    return;
  case USB_EP0_SENDING_STS:
    /* Status packet sent, invoking the callback if defined.*/
    if (usbp->ep0endcb != NULL) {
      usbp->ep0endcb(usbp);
    }
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  case USB_EP0_WAITING_SETUP:
  case USB_EP0_WAITING_STS:
  case USB_EP0_RX:
    /* All the above are invalid states in the IN phase.*/
    osalDbgAssert(false, "EP0 state machine error");
    /* Falling through is intentional.*/
  case USB_EP0_ERROR:
    /* Error response, the state machine goes into an error state, the low
       level layer will have to reset it to USB_EP0_WAITING_SETUP after
       receiving a SETUP packet.*/
    usb_lld_stall_in(usbp, 0);
    usb_lld_stall_out(usbp, 0);
    _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
    usbp->ep0state = USB_EP0_ERROR;
    return;
  default:
    osalDbgAssert(false, "EP0 state machine invalid state");
  }
}
static void msc_transmit(USBDriver *usbp, const uint8_t *p, size_t n) {

  if (n > CBW.dCBWDataTransferLength)
    n = CBW.dCBWDataTransferLength;
  CSW.dCSWDataResidue = CBW.dCBWDataTransferLength - (uint32_t)n;
  chSysLockFromIsr();
  usbStartTransmitI(usbp, MSC_DATA_IN_EP, p, n);
  chSysUnlockFromIsr();
}
Beispiel #11
0
static msg_t tUsbTx(void *arg) {
  (void)arg;
  chRegSetThreadName("usbTx");


  msg_t msg;
  usbPacket *usbBufp;

  enum {UsbTxComleteID = 0, UsbResetID = 1, UsbConfiguredID = 2};

  EventListener elUsbTxComplete;
  EventListener elUsbReset;
  EventListener elUsbConfigured;

  eventmask_t   activeEvents;


  chEvtRegister(&esUsbTxComplete, &elUsbTxComplete, UsbTxComleteID);
  chEvtRegister(&esUsbReset, &elUsbReset, UsbResetID);
  chEvtRegister(&esUsbConfigured, &elUsbConfigured, UsbConfiguredID);

  // Wait for the USB system to be configured. and clear all other event flags.
  chEvtWaitOne(EVENT_MASK(UsbConfiguredID));
  chEvtGetAndClearEvents(EVENT_MASK(UsbTxComleteID) | EVENT_MASK(UsbResetID));

  while (TRUE) {
    chMBFetch (&usbTXMailbox, &msg, TIME_INFINITE);

    // Check if USB has been reconfigured while waiting for message from sysctrl
    activeEvents = chEvtGetAndClearEvents(EVENT_MASK(UsbConfiguredID));
    if (activeEvents == EVENT_MASK(UsbConfiguredID)) {
      // If so, clear the reset event since it is no longer relevant.
      activeEvents = chEvtGetAndClearEvents(EVENT_MASK(UsbResetID));
    }

    // Typecast Mailbox message to command package pointer for readability
    usbBufp = (usbPacket*)msg;

    // Prepare transmit and start the transmission. This operation will return immediately
    usbPrepareTransmit(usbp, EP_IN, usbBufp->packet, (size_t)usbBufp->size);
    chSysLock();
    usbStartTransmitI(usbp, EP_IN);
    chSysUnlock();

    //Check for events from the USB system.
    activeEvents = chEvtWaitAny(EVENT_MASK(UsbTxComleteID) | EVENT_MASK(UsbResetID));

    if (activeEvents == EVENT_MASK(UsbResetID)) {
      chEvtWaitOne(EVENT_MASK(UsbConfiguredID));
      // Clear any events that has occurred while the usb was not configured.
      chEvtGetAndClearEvents(EVENT_MASK(UsbTxComleteID) | EVENT_MASK(UsbResetID));
    }
    usbFreeMailboxBuffer (usbBufp);
  }
  return 0;
}
Beispiel #12
0
/**
 * @brief   Default data transmitted callback.
 * @details The application must use this function as callback for the IN
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        IN endpoint number
 */
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
  uint8_t *buf;
  size_t n;
  SerialUSBDriver *sdup = usbp->in_params[ep - 1U];

  if (sdup == NULL) {
    return;
  }

  osalSysLockFromISR();

  /* Signaling that space is available in the output queue.*/
  chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);

  /* Freeing the buffer just transmitted, if it was not a zero size packet.*/
  if (usbp->epc[ep]->in_state->txsize > 0U) {
    obqReleaseEmptyBufferI(&sdup->obqueue);
  }

  /* Checking if there is a buffer ready for transmission.*/
  buf = obqGetFullBufferI(&sdup->obqueue, &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.*/
    usbStartTransmitI(usbp, ep, buf, n);
  }
  else if ((usbp->epc[ep]->in_state->txsize > 0U) &&
           ((usbp->epc[ep]->in_state->txsize &
            ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) {
    /* Transmit zero sized packet in case the last one has maximum allowed
       size. Otherwise the recipient may expect more data coming soon and
       not return buffered data to app. See section 5.8.3 Bulk Transfer
       Packet Size Constraints of the USB Specification document.*/
    usbStartTransmitI(usbp, ep, usbp->setup, 0);

  }
  else {
    /* Nothing to transmit.*/
  }

  osalSysUnlockFromISR();
}
Beispiel #13
0
void send_data(){
  usbStatus=1;  
  if(initUSB){ 
    usbPrepareTransmit(usbp, EP_IN, transferBuf, sizeof transferBuf);
    chSysLock();
    usbStartTransmitI(usbp, EP_IN);
    chSysUnlock();
    /* chSequentialStreamWrite(&SDU1, buf, sizeof buf - 1); */
  }
  initUSB=0;
  // else failed
}
/**
 * @brief   Default data transmitted callback.
 * @details The application must use this function as callback for the IN
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
  size_t n;
  SerialUSBDriver *sdup = usbp->in_params[ep - 1U];

  if (sdup == NULL) {
    return;
  }

  osalSysLockFromISR();
  chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY);

  /*lint -save -e9013 [15.7] There is no else because it is not needed.*/
  if ((n = oqGetFullI(&sdup->oqueue)) > 0U) {
    /* The endpoint cannot be busy, we are in the context of the callback,
       so it is safe to transmit without a check.*/
    osalSysUnlockFromISR();

    usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, n);

    osalSysLockFromISR();
    (void) usbStartTransmitI(usbp, ep);
  }
  else if ((usbp->epc[ep]->in_state->txsize > 0U) &&
           ((usbp->epc[ep]->in_state->txsize &
            ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) {
    /* Transmit zero sized packet in case the last one has maximum allowed
       size. Otherwise the recipient may expect more data coming soon and
       not return buffered data to app. See section 5.8.3 Bulk Transfer
       Packet Size Constraints of the USB Specification document.*/
    osalSysUnlockFromISR();

    usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, 0);

    osalSysLockFromISR();
    (void) usbStartTransmitI(usbp, ep);
  }
  /*lint -restore*/

  osalSysUnlockFromISR();
}
Beispiel #15
0
/**
 * @brief   Default EP0 OUT callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 OUT events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0out(USBDriver *usbp, usbep_t ep) {

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_RX:
    /* Receive phase over, sending the zero sized status packet.*/
    usbp->ep0state = USB_EP0_SENDING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
    usbPrepareTransmit(usbp, 0, NULL, 0);
    osalSysLockFromISR();
    (void) usbStartTransmitI(usbp, 0);
    osalSysUnlockFromISR();
#else
    usb_lld_end_setup(usbp, ep);
#endif
    return;
  case USB_EP0_WAITING_STS:
    /* Status packet received, it must be zero sized, invoking the callback
       if defined.*/
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
    if (usbGetReceiveTransactionSizeI(usbp, 0) != 0U) {
      break;
    }
#endif
    if (usbp->ep0endcb != NULL) {
      usbp->ep0endcb(usbp);
    }
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  case USB_EP0_WAITING_SETUP:
  case USB_EP0_TX:
  case USB_EP0_WAITING_TX0:
  case USB_EP0_SENDING_STS:
    /* All the above are invalid states in the IN phase.*/
    osalDbgAssert(false, "EP0 state machine error");
    /* Falling through is intentional.*/
  case USB_EP0_ERROR:
    /* Error response, the state machine goes into an error state, the low
       level layer will have to reset it to USB_EP0_WAITING_SETUP after
       receiving a SETUP packet.*/
    usb_lld_stall_in(usbp, 0);
    usb_lld_stall_out(usbp, 0);
    _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
    usbp->ep0state = USB_EP0_ERROR;
    return;
  default:
    osalDbgAssert(false, "EP0 state machine invalid state");
  }
}
Beispiel #16
0
/*
 * data Transmitted Callback
 */
void dataTransmitted(USBDriver *usbp, usbep_t ep){
    (void) usbp;
    (void) ep;

    // exit on USB reset
    if(!usbStatus) return;


    usbPrepareTransmit(usbp, EP_IN, transferBuf, sizeof transferBuf);

    chSysLockFromIsr();
    usbStartTransmitI(usbp, EP_IN);
    chSysUnlockFromIsr();

}
Beispiel #17
0
static void send_extra_report(uint8_t report_id, uint16_t data) {
  osalSysLock();
  if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
    osalSysUnlock();
    return;
  }

  report_extra_t report = {
    .report_id = report_id,
    .usage = data
  };

  usbStartTransmitI(&USB_DRIVER, EXTRAKEY_IN_EPNUM, (uint8_t *)&report, sizeof(report_extra_t));
  osalSysUnlock();
}
Beispiel #18
0
/**
 * @brief   Performs a transmit transaction on an IN endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 * @param[in] buf       buffer where to fetch the data to be transmitted
 * @param[in] n         transaction size
 *
 * @return              The operation status.
 * @retval MSG_OK       operation performed successfully.
 * @retval MSG_RESET    driver not in @p USB_ACTIVE state or the operation
 *                      has been aborted by an USB reset or a transition to
 *                      the @p USB_SUSPENDED state.
 *
 * @api
 */
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) {
  msg_t msg;

  osalSysLock();

  if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
    osalSysUnlock();
    return MSG_RESET;
  }

  usbStartTransmitI(usbp, ep, buf, n);
  msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
  osalSysUnlock();

  return msg;
}
Beispiel #19
0
/**
 * @brief   Default EP0 IN callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 IN events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
  size_t max;

  (void)ep;
  switch (usbp->ep0state) {
  case USB_EP0_TX:
    max = usbFetchWord(&usbp->setup[6]);
    /* If the transmitted size is less than the requested size and it is a
       multiple of the maximum packet size then a zero size packet must be
       transmitted.*/
    if ((usbp->ep0n < max) && ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) {
      usbPrepareTransmit(usbp, 0, NULL, 0);
      chSysLockFromIsr();
      usbStartTransmitI(usbp, 0);
      chSysUnlockFromIsr();
      usbp->ep0state = USB_EP0_WAITING_TX0;
      return;
    }
    /* Falls into, it is intentional.*/
  case USB_EP0_WAITING_TX0:
    /* Transmit phase over, receiving the zero sized status packet.*/
    usbp->ep0state = USB_EP0_WAITING_STS;
    usbPrepareReceive(usbp, 0, NULL, 0);
    chSysLockFromIsr();
    usbStartReceiveI(usbp, 0);
    chSysUnlockFromIsr();
    return;
  case USB_EP0_SENDING_STS:
    /* Status packet sent, invoking the callback if defined.*/
    if (usbp->ep0endcb != NULL)
      usbp->ep0endcb(usbp);
    usbp->ep0state = USB_EP0_WAITING_SETUP;
    return;
  default:
    ;
  }
  /* Error response, the state machine goes into an error state, the low
     level layer will have to reset it to USB_EP0_WAITING_SETUP after
     receiving a SETUP packet.*/
  usb_lld_stall_in(usbp, 0);
  usb_lld_stall_out(usbp, 0);
  _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
  usbp->ep0state = USB_EP0_ERROR;
}
Beispiel #20
0
/**
 * @brief   Notification of filled buffer inserted into the output buffers queue.
 *
 * @param[in] bqp       the buffers queue pointer.
 */
static void obnotify(io_buffers_queue_t *bqp) {
  size_t n;
  SerialUSBDriver *sdup = bqGetLinkX(bqp);
  /* If the USB driver is not in the appropriate state then transactions
     must not be started.*/
  if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) ||
      (sdup->state != SDU_READY)) {
    return;
  }
  /* Checking if there is already a transaction ongoing on the endpoint.*/
  if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in)) {
    /* Trying to get a full buffer.*/
    uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n);
    if (buf != NULL) {
      /* Buffer found, starting a new transaction.*/
      usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
    }
  }
}
Beispiel #21
0
void send_mouse(report_mouse_t *report) {
  osalSysLock();
  if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
    osalSysUnlock();
    return;
  }

  if(usbGetTransmitStatusI(&USB_DRIVER, MOUSE_IN_EPNUM)) {
    /* Need to either suspend, or loop and call unlock/lock during
     * every iteration - otherwise the system will remain locked,
     * no interrupts served, so USB not going through as well.
     * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
    if (osalThreadSuspendTimeoutS(&(&USB_DRIVER)->epc[MOUSE_IN_EPNUM]->in_state->thread, MS2ST(10)==MSG_TIMEOUT)) {
      osalSysUnlock();
      return;
    }
  }
  usbStartTransmitI(&USB_DRIVER, MOUSE_IN_EPNUM, (uint8_t *)report, sizeof(report_mouse_t));
  osalSysUnlock();
}
/**
 * @brief   Default data transmitted callback.
 * @details The application must use this function as callback for the IN
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void mscDataTransmitted(USBDriver *usbp, usbep_t ep) {

  switch (msc_state) {
  case MSC_DATA_IN:
    CSW.dCSWSignature = MSC_CSW_SIGNATURE;
    CSW.dCSWTag = CBW.dCBWTag;
    chSysLockFromIsr();
    usbStartTransmitI(usbp, ep, (uint8_t *)&CSW, sizeof CSW);
    chSysUnlockFromIsr();
    msc_state = MSC_SENDING_CSW;
    break;
  case MSC_SENDING_CSW:
    chSysLockFromIsr();
    usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
    chSysUnlockFromIsr();
    msc_state = MSC_IDLE;
    break;
  default:
    ;
  }
}
/* callback */
static void hid_debug_flush_cb(void *arg) {
  HIDDebugDriver *hiddp = (HIDDebugDriver *)arg;
  size_t i, n;
  uint8_t buf[DEBUG_TX_SIZE];

  osalSysLockFromISR();

  /* check that the states of things are as they're supposed to */
  if((usbGetDriverStateI(hiddp->config->usbp) != USB_ACTIVE) ||
     (hiddp->state != HIDDEBUG_READY)) {
    /* rearm the timer */
    chVTSetI(&hid_debug_flush_timer, MS2ST(DEBUG_TX_FLUSH_MS), hid_debug_flush_cb, hiddp);
    osalSysUnlockFromISR();
    return;
  }

  /* don't do anything if the queue or has enough stuff in it */
  if(((n = oqGetFullI(&hiddp->oqueue)) == 0) || (n >= DEBUG_TX_SIZE)) {
    /* rearm the timer */
    chVTSetI(&hid_debug_flush_timer, MS2ST(DEBUG_TX_FLUSH_MS), hid_debug_flush_cb, hiddp);
    osalSysUnlockFromISR();
    return;
  }

  /* there's stuff hanging in the queue - so dequeue and send */
  for(i = 0; i < n; i++)
    buf[i] = (uint8_t)oqGetI(&hiddp->oqueue);
  for(i = n; i < DEBUG_TX_SIZE; i++)
    buf[i] = 0;
  osalSysUnlockFromISR();
  usbPrepareTransmit(hiddp->config->usbp, hiddp->config->ep_in, buf, DEBUG_TX_SIZE);
  osalSysLockFromISR();
  (void)usbStartTransmitI(hiddp->config->usbp, hiddp->config->ep_in);

  /* rearm the timer */
  chVTSetI(&hid_debug_flush_timer, MS2ST(DEBUG_TX_FLUSH_MS), hid_debug_flush_cb, hiddp);
  osalSysUnlockFromISR();
}
Beispiel #24
0
static msg_t initUsbTransfer(void *arg) {

  (void)arg;
  uint8_t i;
  chRegSetThreadName("initUsbTransfer");

  while (TRUE) {
    //wait until enough ADC data is aquired or an overflow is detected
    while((((p1+BUFFLEN-p2)%BUFFLEN)<IN_PACKETSIZE) && !overflow){
      chThdSleepMilliseconds(1);
    }

    // copy the ADC data to the USB transfer buffer
    for (i=0;i<IN_PACKETSIZE;i++){
      transferBuf[i]=((uint8_t*) data)[p2];
      //if an overflow is detected, write the overflow count.
      // in a real application this has to be send on another channel
      if(overflow){
          transferBuf[i]= overflow;
          overflow=0;
      }
      p2 = (p2+1)%BUFFLEN;
    }
    //wait for the last transmission to complete
    while(transmitting){
      chThdSleepMilliseconds(1);
    }

    transmitting = 1;
    usbPrepareTransmit(usbp, EP_IN, transferBuf, IN_PACKETSIZE);

    chSysLock();
    usbStartTransmitI(usbp, EP_IN);
    chSysUnlock();

  }
  return 0;
}
Beispiel #25
0
/**
 * @brief   Notification of data inserted into the output queue.
 */
static void onotify(GenericQueue *qp) {
  size_t n;
  SerialUSBDriver *sdup = chQGetLink(qp);

  /* If the USB driver is not in the appropriate state then transactions
     must not be started.*/
  if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE)
    return;

  /* If there is not an ongoing transaction and the output queue contains
     data then a new transaction is started.*/
  if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) &&
      ((n = chOQGetFullI(&sdup->oqueue)) > 0)) {
    chSysUnlock();

    usbPrepareQueuedTransmit(sdup->config->usbp,
                             USB_CDC_DATA_REQUEST_EP,
                             &sdup->oqueue, n);

    chSysLock();
    usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP);
  }
}
Beispiel #26
0
/**
 * @brief   Notification of data inserted into the output queue.
 */
static void onotify(GenericQueue *qp) {
  size_t n;
  BulkUSBDriver *bdup = chQGetLink(qp);

  /* If the USB driver is not in the appropriate state then transactions
     must not be started.*/
  if ((usbGetDriverStateI(bdup->config->usbp) != USB_ACTIVE) ||
      (bdup->state != BDU_READY))
    return;

  /* If there is not an ongoing transaction and the output queue contains
     data then a new transaction is started.*/
  if (!usbGetTransmitStatusI(bdup->config->usbp, bdup->config->bulk_in) &&
      ((n = chOQGetFullI(&bdup->oqueue)) > 0)) {
    chSysUnlock();

    usbPrepareQueuedTransmit(bdup->config->usbp,
                             bdup->config->bulk_in,
                             &bdup->oqueue, n);

    chSysLock();
    usbStartTransmitI(bdup->config->usbp, bdup->config->bulk_in);
  }
}
Beispiel #27
0
/* Idle requests timer code
 * callback (called from ISR, unlocked state) */
static void keyboard_idle_timer_cb(void *arg) {
  USBDriver *usbp = (USBDriver *)arg;

  osalSysLockFromISR();

  /* check that the states of things are as they're supposed to */
  if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
    /* do not rearm the timer, should be enabled on IDLE request */
    osalSysUnlockFromISR();
    return;
  }

#ifdef NKRO_ENABLE
  if(!keymap_config.nkro && keyboard_idle) {
#else /* NKRO_ENABLE */
  if(keyboard_idle) {
#endif /* NKRO_ENABLE */
    /* TODO: are we sure we want the KBD_ENDPOINT? */
    if(!usbGetTransmitStatusI(usbp, KEYBOARD_IN_EPNUM)) {
      usbStartTransmitI(usbp, KEYBOARD_IN_EPNUM, (uint8_t *)&keyboard_report_sent, KEYBOARD_EPSIZE);
    }
    /* rearm the timer */
    chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
  }

  /* do not rearm the timer if the condition above fails
   * it should be enabled again on either IDLE or SET_PROTOCOL requests */
  osalSysUnlockFromISR();
}

/* LED status */
uint8_t keyboard_leds(void) {
  return (uint8_t)(keyboard_led_stats & 0xFF);
}

/* prepare and start sending a report IN
 * not callable from ISR or locked state */
void send_keyboard(report_keyboard_t *report) {
  osalSysLock();
  if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
    osalSysUnlock();
    return;
  }
  osalSysUnlock();

#ifdef NKRO_ENABLE
  if(keymap_config.nkro) {  /* NKRO protocol */
    /* need to wait until the previous packet has made it through */
    /* 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();
    if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_IN_EPNUM)) {
      /* Need to either suspend, or loop and call unlock/lock during
       * every iteration - otherwise the system will remain locked,
       * no interrupts served, so USB not going through as well.
       * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
      osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_IN_EPNUM]->in_state->thread);
    }
    usbStartTransmitI(&USB_DRIVER, NKRO_IN_EPNUM, (uint8_t *)report, sizeof(report_keyboard_t));
    osalSysUnlock();
  } else
#endif /* NKRO_ENABLE */
  { /* boot protocol */
    /* need to wait until the previous packet has made it through */
    /* busy wait, should be short and not very common */
    osalSysLock();
    if(usbGetTransmitStatusI(&USB_DRIVER, KEYBOARD_IN_EPNUM)) {
      /* Need to either suspend, or loop and call unlock/lock during
       * every iteration - otherwise the system will remain locked,
       * no interrupts served, so USB not going through as well.
       * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
      osalThreadSuspendS(&(&USB_DRIVER)->epc[KEYBOARD_IN_EPNUM]->in_state->thread);
    }
    usbStartTransmitI(&USB_DRIVER, KEYBOARD_IN_EPNUM, (uint8_t *)report, KEYBOARD_EPSIZE);
    osalSysUnlock();
  }
  keyboard_report_sent = *report;
}
Beispiel #28
0
/**
 * @brief   Default EP0 SETUP callback.
 * @details This function is used by the low level driver as default handler
 *          for EP0 SETUP events.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number, always zero
 *
 * @notapi
 */
void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
  size_t max;

  usbp->ep0state = USB_EP0_WAITING_SETUP;
  usbReadSetup(usbp, ep, usbp->setup);

  /* First verify if the application has an handler installed for this
     request.*/
  if (!(usbp->config->requests_hook_cb) ||
      !(usbp->config->requests_hook_cb(usbp))) {
    /* Invoking the default handler, if this fails then stalls the
       endpoint zero as error.*/
    if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) ||
        !default_handler(usbp)) {
      /* Error response, the state machine goes into an error state, the low
         level layer will have to reset it to USB_EP0_WAITING_SETUP after
         receiving a SETUP packet.*/
      usb_lld_stall_in(usbp, 0);
      usb_lld_stall_out(usbp, 0);
      _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED);
      usbp->ep0state = USB_EP0_ERROR;
      return;
    }
  }
#if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW)
  if (usbp->setup[1] == USB_REQ_SET_ADDRESS) {
    /* Zero-length packet sent by hardware */
    return;
  }
#endif
  /* Transfer preparation. The request handler must have populated
     correctly the fields ep0next, ep0n and ep0endcb using the macro
     usbSetupTransfer().*/
  max = usbFetchWord(&usbp->setup[6]);
  /* The transfer size cannot exceed the specified amount.*/
  if (usbp->ep0n > max)
    usbp->ep0n = max;
  if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) {
    /* IN phase.*/
    if (usbp->ep0n > 0) {
      /* Starts the transmit phase.*/
      usbp->ep0state = USB_EP0_TX;
      usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n);
      osalSysLockFromISR();
      usbStartTransmitI(usbp, 0);
      osalSysUnlockFromISR();
    }
    else {
      /* No transmission phase, directly receiving the zero sized status
         packet.*/
      usbp->ep0state = USB_EP0_WAITING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
      usbPrepareReceive(usbp, 0, NULL, 0);
      osalSysLockFromISR();
      usbStartReceiveI(usbp, 0);
      osalSysUnlockFromISR();
#else
      usb_lld_end_setup(usbp, ep);
#endif
    }
  }
  else {
    /* OUT phase.*/
    if (usbp->ep0n > 0) {
      /* Starts the receive phase.*/
      usbp->ep0state = USB_EP0_RX;
      usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n);
      osalSysLockFromISR();
      usbStartReceiveI(usbp, 0);
      osalSysUnlockFromISR();
    }
    else {
      /* No receive phase, directly sending the zero sized status
         packet.*/
      usbp->ep0state = USB_EP0_SENDING_STS;
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
      usbPrepareTransmit(usbp, 0, NULL, 0);
      osalSysLockFromISR();
      usbStartTransmitI(usbp, 0);
      osalSysUnlockFromISR();
#else
      usb_lld_end_setup(usbp, ep);
#endif
    }
  }
}