示例#1
0
/**
 * @brief   Notification of data removed from the input queue.
 */
static void inotify(GenericQueue *qp) {
  size_t n, maxsize;
  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 in the queue enough space to hold at least one packet and
     a transaction is not yet started then a new transaction is started for
     the available space.*/
  maxsize = bdup->config->usbp->epc[bdup->config->bulk_out]->out_maxsize;
  if (!usbGetReceiveStatusI(bdup->config->usbp, bdup->config->bulk_out) &&
      ((n = chIQGetEmptyI(&bdup->iqueue)) >= maxsize)) {
    chSysUnlock();

    n = (n / maxsize) * maxsize;
    usbPrepareQueuedReceive(bdup->config->usbp,
                            bdup->config->bulk_out,
                            &bdup->iqueue, n);

    chSysLock();
    usbStartReceiveI(bdup->config->usbp, bdup->config->bulk_out);
  }
}
/**
 * @brief   Notification of data removed from the input queue.
 *
 * @param[in] qp        the queue pointer.
 */
static void inotify(io_queue_t *qp) {
  size_t n, maxsize;
  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 in the queue enough space to hold at least one packet and
     a transaction is not yet started then a new transaction is started for
     the available space.*/
  maxsize = sdup->config->usbp->epc[sdup->config->bulk_out]->out_maxsize;
  if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) {
    if ((n = iqGetEmptyI(&sdup->iqueue)) >= maxsize) {
      osalSysUnlock();

      n = (n / maxsize) * maxsize;
      usbPrepareQueuedReceive(sdup->config->usbp,
                              sdup->config->bulk_out,
                              &sdup->iqueue, n);

      osalSysLock();
      (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
    }
  }
}
示例#3
0
/**
 * @brief   Default data received callback.
 * @details The application must use this function as callback for the OUT
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void bduDataReceived(USBDriver *usbp, usbep_t ep) {
  size_t n, maxsize;
  BulkUSBDriver *bdup = usbp->out_params[ep - 1];

  if (bdup == NULL)
    return;

  chSysLockFromIsr();
  chnAddFlagsI(bdup, CHN_INPUT_AVAILABLE);

  /* Writes to the input queue can only happen when there is enough space
     to hold at least one packet.*/
  maxsize = usbp->epc[ep]->out_maxsize;
  if ((n = chIQGetEmptyI(&bdup->iqueue)) >= maxsize) {
    /* The endpoint cannot be busy, we are in the context of the callback,
       so a packet is in the buffer for sure.*/
    chSysUnlockFromIsr();

    n = (n / maxsize) * maxsize;
    usbPrepareQueuedReceive(usbp, ep, &bdup->iqueue, n);

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

  chSysUnlockFromIsr();
}
示例#4
0
/**
 * @brief   Notification of data removed from the input queue.
 */
static void inotify(GenericQueue *qp) {
  size_t n, maxsize;
  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 in the queue enough space to hold at least one packet and
     a transaction is not yet started then a new transaction is started for
     the available space.*/
  maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize;
  if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) &&
      ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) {
    chSysUnlock();

    n = (n / maxsize) * maxsize;
    usbPrepareQueuedReceive(sdup->config->usbp,
                            USB_CDC_DATA_AVAILABLE_EP,
                            &sdup->iqueue, n);

    chSysLock();
    usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP);
  }
}
示例#5
0
/*
 * data Received Callback
 * It toggles an LED based on the first received character.
 */
void dataReceived(USBDriver *usbp, usbep_t ep){
    USBOutEndpointState *osp = usbp->epc[ep]->out_state;
    (void) usbp;
    (void) ep;

    if(osp->rxcnt){
        switch(receiveBuf[0]){
            case '1':
                palTogglePad(GPIOD, GPIOD_LED3);
                break;
            case '2':
                palTogglePad(GPIOD, GPIOD_LED4);
                break;
            case '3':
                palTogglePad(GPIOD, GPIOD_LED5);
                break;
            case '4':
                palTogglePad(GPIOD, GPIOD_LED6);
                break;

        }
    }

    /*
     * Initiate next receive
     */
    usbPrepareReceive(usbp, EP_OUT, receiveBuf, OUT_PACKETSIZE);

    chSysLockFromIsr();
    usbStartReceiveI(usbp, EP_OUT);
    chSysUnlockFromIsr();
}
示例#6
0
/**
 * @brief   Default data received callback.
 * @details The application must use this function as callback for the OUT
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        OUT endpoint number
 */
void sduDataReceived(USBDriver *usbp, usbep_t ep) {
  uint8_t *buf;
  SerialUSBDriver *sdup = usbp->out_params[ep - 1U];

  if (sdup == NULL) {
    return;
  }

  osalSysLockFromISR();

  /* Signaling that data is available in the input queue.*/
  chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);

  /* Posting the filled buffer in the queue.*/
  ibqPostFullBufferI(&sdup->ibqueue,
                     usbGetReceiveTransactionSizeX(sdup->config->usbp,
                                                   sdup->config->bulk_out));

  /* The endpoint cannot be busy, we are in the context of the callback,
     so a packet is in the buffer for sure. Trying to get a free buffer
     for the next transaction.*/
  buf = ibqGetEmptyBufferI(&sdup->ibqueue);
  if (buf != NULL) {
    /* Buffer found, starting a new transaction.*/
    usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
                     buf, SERIAL_USB_BUFFERS_SIZE);
  }
  osalSysUnlockFromISR();
}
/**
 * @brief   MSC state machine initialization.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 */
static void msc_reset(USBDriver *usbp) {

  msc_state = MSC_IDLE;
  chSysLockFromIsr();
  usbStartReceiveI(usbp, MSC_DATA_OUT_EP, (uint8_t *)&CBW, sizeof CBW);
  chSysUnlockFromIsr();
}
示例#8
0
/**
 * @brief   Default data received callback.
 * @details The application must use this function as callback for the OUT
 *          data endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 */
void sduDataReceived(USBDriver *usbp, usbep_t ep) {
  size_t n, maxsize;
  SerialUSBDriver *sdup = usbp->param;

  (void)ep;

  chSysLockFromIsr();
  chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE);

  /* Writes to the input queue can only happen when there is enough space
     to hold at least one packet.*/
  maxsize = usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize;
  if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) {
    /* The endpoint cannot be busy, we are in the context of the callback,
       so a packet is in the buffer for sure.*/
    chSysUnlockFromIsr();

    n = (n / maxsize) * maxsize;
    usbPrepareQueuedReceive(usbp, ep, &sdup->iqueue, n);

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

  chSysUnlockFromIsr();
}
示例#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");
  }
}
/**
 * @brief   USB device configured handler.
 *
 * @param[in] sdup      pointer to a @p SerialUSBDriver object
 *
 * @iclass
 */
void sduConfigureHookI(SerialUSBDriver *sdup) {
  USBDriver *usbp = sdup->config->usbp;

  iqResetI(&sdup->iqueue);
  oqResetI(&sdup->oqueue);
  chnAddFlagsI(sdup, CHN_CONNECTED);

  /* Starts the first OUT transaction immediately.*/
  usbPrepareQueuedReceive(usbp, sdup->config->bulk_out, &sdup->iqueue,
                          usbp->epc[sdup->config->bulk_out]->out_maxsize);
  (void) usbStartReceiveI(usbp, sdup->config->bulk_out);
}
示例#11
0
/**
 * @brief   USB device configured handler.
 *
 * @param[in] bdup      pointer to a @p BulkUSBDriver object
 *
 * @iclass
 */
void bduConfigureHookI(BulkUSBDriver *bdup) {
  USBDriver *usbp = bdup->config->usbp;

  chIQResetI(&bdup->iqueue);
  chOQResetI(&bdup->oqueue);
  chnAddFlagsI(bdup, CHN_CONNECTED);

  /* Starts the first OUT transaction immediately.*/
  usbPrepareQueuedReceive(usbp, bdup->config->bulk_out, &bdup->iqueue,
                          usbp->epc[bdup->config->bulk_out]->out_maxsize);
  usbStartReceiveI(usbp, bdup->config->bulk_out);
}
示例#12
0
static msg_t tUsbRx(void *arg) {
  (void)arg;
  chRegSetThreadName("usbRx");

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

  usbPacket *usbBufp;

  EventListener elUsbRxComplete;
  EventListener elUsbReset;
  EventListener elUsbConfigured;

  eventmask_t   activeEvents;


  chEvtRegister(&esUsbRxComplete, &elUsbRxComplete, UsbRxComleteID);
  chEvtRegister(&esUsbReset, &elUsbReset, UsbResetID);
  chEvtRegister(&esUsbConfigured, &elUsbConfigured, UsbConfiguredID);

  // Wait for the USB system to be configured.
  chEvtWaitOne(EVENT_MASK(UsbConfiguredID));
  chEvtGetAndClearEvents(EVENT_MASK(UsbRxComleteID) | EVENT_MASK(UsbResetID));

  while (TRUE) {

    // Allocate buffer space for reception of package in the sysctrl mempool
    usbBufp = usbAllocMailboxBuffer();

    // Prepare receive operation and initiate the usb system to listen
    usbPrepareReceive(usbp, EP_OUT, usbBufp->packet, 64);
    chSysLock();
    usbStartReceiveI(usbp, EP_OUT);
    chSysUnlock();

    // Wait for events from the USB system
    activeEvents = chEvtWaitAny(EVENT_MASK(UsbRxComleteID) | EVENT_MASK(UsbResetID));

    if (activeEvents == EVENT_MASK(UsbResetID)) {
      // If the system was reset, clean up and wait for new configure.
      usbFreeMailboxBuffer (usbBufp);
      chEvtWaitOne(EVENT_MASK(UsbConfiguredID));
      chEvtGetAndClearEvents(EVENT_MASK(UsbRxComleteID) | EVENT_MASK(UsbResetID));
    }
    else {
      // Post pagckage to sysctrl if receive was successful
      usbBufp->size = ep2outstate.rxcnt;
      chMBPost (&usbRXMailbox, (msg_t)usbBufp, TIME_INFINITE);
    }
  }

  return 0;
}
示例#13
0
uint8_t receive_data(){
  // while EP_BUSY 
  usbStatus=1;
  if(initUSB){
    usbPrepareReceive(usbp, EP_OUT, receiveBuf, 64);
    chSysLock();
    usbStartReceiveI(usbp, EP_OUT);
    chSysUnlock(); 
    
  }
  initUSB=0;
  return 0;
}
示例#14
0
/**
 * @brief   USB device configured handler.
 *
 * @param[in] sdup      pointer to a @p SerialUSBDriver object
 *
 * @iclass
 */
void sduConfigureHookI(SerialUSBDriver *sdup) {
  uint8_t *buf;

  ibqResetI(&sdup->ibqueue);
  obqResetI(&sdup->obqueue);
  chnAddFlagsI(sdup, CHN_CONNECTED);

  /* Starts the first OUT transaction immediately.*/
  buf = ibqGetEmptyBufferI(&sdup->ibqueue);

  osalDbgAssert(buf != NULL, "no free buffer");

  usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
                   buf, SERIAL_USB_BUFFERS_SIZE);
}
示例#15
0
/**
 * @brief   USB device configured handler.
 *
 * @param[in] uhdp      pointer to a @p USBHIDDriver object
 *
 * @iclass
 */
void hidConfigureHookI(USBHIDDriver *uhdp) {
  uint8_t *buf;

  ibqResetI(&uhdp->ibqueue);
  obqResetI(&uhdp->obqueue);
  chnAddFlagsI(uhdp, CHN_CONNECTED);

  /* Starts the first OUT transaction immediately.*/
  buf = ibqGetEmptyBufferI(&uhdp->ibqueue);

  osalDbgAssert(buf != NULL, "no free buffer");

  usbStartReceiveI(uhdp->config->usbp, uhdp->config->int_out,
                   buf, USB_HID_BUFFERS_SIZE);
}
示例#16
0
/**
 * @brief   Performs a receive transaction on an OUT endpoint.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 * @param[out] buf      buffer where to copy the received data
 * @param[in] n         transaction size. It is recommended a multiple of
 *                      the packet size because the excess is discarded.
 *
 * @return              The received effective data size, it can be less than
 *                      the amount specified.
 * @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 usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
  msg_t msg;

  osalSysLock();

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

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

  return msg;
}
示例#17
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;
}
示例#18
0
/*
 * data Received Callback
 * It prints to shell a string
 */
void dataReceived(USBDriver *usbp, usbep_t ep){
    USBOutEndpointState *osp = usbp->epc[ep]->out_state;
    (void) usbp;
    (void) ep;
    // exit on USB reset
    if(!usbStatus) return;

   if(osp->rxcnt){
     //  chprintf(chp,"Data received");
    }

    /*
     * Initiate next receive
     */
    usbPrepareReceive(usbp, EP_OUT, receiveBuf, 64);

    chSysLockFromIsr();
    usbStartReceiveI(usbp, EP_OUT);
    chSysUnlockFromIsr();
}
示例#19
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 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:
    ;
  }
}
示例#20
0
/**
 * @brief   Notification of empty buffer released into the input buffers queue.
 *
 * @param[in] bqp       the buffers queue pointer.
 */
static void ibnotify(io_buffers_queue_t *bqp) {
  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 (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) {
    /* Trying to get a free buffer.*/
    uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue);
    if (buf != NULL) {
      /* Buffer found, starting a new transaction.*/
      usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
                       buf, SERIAL_USB_BUFFERS_SIZE);
    }
  }
}
示例#21
0
int main(void) {

  //start system
  halInit();
  chSysInit();


  //start and connect USB
  usbStart(usbp, &config);
  usbConnectBus(usbp);

  //init the ADC
  myADCinit();


  //main loop, inits the USB transfers when it is told to do so
  while (TRUE) {
      while(!initUSB){
        chThdSleepMilliseconds(100);
      }
    palTogglePad(GPIOD, GPIOD_LED6);
    /*
     * starts first receiving transaction
     * all further transactions are initiated by the dataReceived callback
     */
    usbPrepareReceive(usbp, EP_OUT, receiveBuf, 64);
    chSysLock();
    usbStartReceiveI(usbp, EP_OUT);
    chSysUnlock();
    /*
     * starts the transfer thread
     */
    tp = chThdCreateStatic(waInitUsbTransfer, sizeof(waInitUsbTransfer), NORMALPRIO, initUsbTransfer, NULL);
    initUSB=0;
  }
}
示例#22
0
文件: usb.c 项目: hmchen1/ChibiOS
/**
 * @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
    }
  }
}
示例#23
0
void hid_recive(USBDriver *usbp) {
	usbPrepareReceive(usbp, HID_OUT_EP_ADDRESS, (uint8_t *)&hid_out_data, sizeof (hid_out_data));
	chSysLockFromISR();
	usbStartReceiveI(usbp, HID_OUT_EP_ADDRESS);
	chSysUnlockFromISR();
}