/** * @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); } } }
/** * @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(); }
/** * @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); } }
/* * 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(); }
/** * @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(); }
/** * @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(); }
/** * @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); }
/** * @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); }
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; }
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; }
/** * @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); }
/** * @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); }
/** * @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; }
/** * @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; }
/* * 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(); }
/** * @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: ; } }
/** * @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); } } }
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; } }
/** * @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 } } }
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(); }