/*********************************************************************************** * @fn halUartPollRx * * @brief Poll for data from USB. * * @param none * * @return none */ void halUartPollRx(void) { uint8 cnt; uint8 ep = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(4); /* If the OUT endpoint has received a complete packet. */ if (USBFW_OUT_ENDPOINT_DISARMED()) { halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); /* Get length of USB packet, this operation must not be interrupted. */ cnt = USBFW_GET_OUT_ENDPOINT_COUNT_LOW(); cnt += USBFW_GET_OUT_ENDPOINT_COUNT_HIGH() >> 8; HAL_EXIT_CRITICAL_SECTION(intState); while (cnt--) { halUartRxQ[halUartRxT++] = HWREG(USB_F4); } USBFW_ARM_OUT_ENDPOINT(); /* If the USB has transferred in more Rx bytes, reset the Rx idle timer. */ /* Re-sync the shadow on any 1st byte(s) received. */ if (rxTick == 0) { rxShdw = ST0; } rxTick = HAL_UART_USB_IDLE; } else if (rxTick)
/*********************************************************************************** * @fn usbInProcess * * @brief Handle traffic flow from RF to USB. * * @param none * * @return none */ static void usbInProcess(void) { //uint8 length; // USB ready to accept new IN packet halIntOff(); oldEndpoint = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(4); // The IN endpoint is ready to accept data if ( USBFW_IN_ENDPOINT_DISARMED() ) { if (usb_sendack) { // modify and return received packet usbfwWriteFifo(&USBF4, usb_buffer[2], &usb_buffer[0]); usb_sendack = 0; // Flag USB IN buffer as not ready (disarming EP4) USBFW_SELECT_ENDPOINT(4); USBFW_ARM_IN_ENDPOINT(); // Send data to the host } /* // Number of bytes present in RF buffer length= bufNumBytes(&rbTxBuf); if (length>0) { // Limit the size if (length > USB_MAX_PACKET_SIZE) { length = USB_MAX_PACKET_SIZE; } // Read from UART TX buffer bufGet(&rbTxBuf,buffer,length); // Write to USB FIFO usbfwWriteFifo(&USBF4, length, buffer); // Flag USB IN buffer as not ready (disarming EP4) USBFW_SELECT_ENDPOINT(4); USBFW_ARM_IN_ENDPOINT(); // Send data to the host }*/ } USBFW_SELECT_ENDPOINT(oldEndpoint); halIntOn(); }
/*********************************************************************************** * @fn usbOutProcess * * @brief Handle traffic flow from USB to RF. * * @param none * * @return none */ static void usbOutProcess(void) { uint8 length, nToSend; // If new packet is ready in USB FIFO halIntOff(); oldEndpoint = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(4); if (USBFW_OUT_ENDPOINT_DISARMED() ) { // Get length of USB packet, this operation must not be interrupted. length = USBFW_GET_OUT_ENDPOINT_COUNT_LOW(); length+= (int)(USBFW_GET_OUT_ENDPOINT_COUNT_HIGH()) >> 8; // Calculate number of bytes available in RF buffer; and the number // of bytes we may transfer in this operation. nToSend= MIN(BUF_SIZE - bufNumBytes(&rbRxBuf), length); // Space available in UART RX buffer ? if (nToSend>0) { // Read from USB FIFO usbfwReadFifo(&USBF4, nToSend, buffer); // Write to radio TX buffer bufPut(&rbRxBuf,buffer,nToSend); // If entire USB packet is read from buffer if (length == nToSend) { USBFW_SELECT_ENDPOINT(4); USBFW_ARM_OUT_ENDPOINT(); } } } USBFW_SELECT_ENDPOINT(oldEndpoint); halIntOn(); }
// ************************ USB interrupt event processing ************************* void usbirqHookProcessEvents(void) { T1CNTL=0; if (usbirqData.eventMask & USBIRQ_EVENT_EP5IN){ if (isFifoEmpty()==0){ struct UsbISR * msg = (struct UsbISR *)osal_msg_allocate(sizeof(struct UsbISR) ); msg->msg.event = EVENT_USB_ISR; msg->isr = eventSendFifo; osal_msg_send(zusbTaskId, (uint8 *)msg); } } if (usbirqData.eventMask & USBIRQ_EVENT_EP2OUT){ uint8 oldEndpoint = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(2); uint8 length = USBFW_GET_OUT_ENDPOINT_COUNT_LOW(); if (length > MAX_DATE_SIZE_2){ length = MAX_DATE_SIZE_2; } if (length) { struct UsbISR * msg =NULL; uint8 code = USBF2; switch( code){ case ENABLE_INFO_MESSAGE: usbOn=1; break; case REQ_RESET: msg = (struct UsbISR *)osal_msg_allocate(sizeof(struct UsbISR) ); msg->msg.event = EVENT_USB_ISR; msg->isr = eventReset; break; case REQ_BIND_TABLE: { uint8 addr[2]; addr[0] = USBF2; addr[1] = USBF2; struct BindTableRequestMsg * msgReq = (struct BindTableRequestMsg *)osal_msg_allocate(sizeof(struct BindTableRequestMsg) ); msg = &(msgReq->isr); msg->isr = eventBindReq; msg->msg.event = EVENT_USB_ISR; msgReq->afAddrType.addrMode = Addr16Bit; msgReq->afAddrType.addr.shortAddr = *(uint16 *)(addr); } break; case REQ_ACTIVE_EP:{ struct ReqActiveEndpointsEvent * msgEP = (struct ReqActiveEndpointsEvent *)osal_msg_allocate(sizeof(struct ReqActiveEndpointsEvent) ); msg = &(msgEP->isr); msg->isr = eventActiveEP; msg->msg.event = EVENT_USB_ISR; msgEP->data[0] = USBF2; msgEP->data[1] = USBF2; } break; case REQ_ADD_BIND_TABLE_ENTRY: msg = createMsgForBind(); msg->isr = eventBindRequest; break; case REQ_REMOVE_BIND_TABLE_ENTRY: msg = createMsgForBind(); msg->isr = eventUnbindRequest; break; case NODE_POWER_REQUEST:{ struct ReqPowerNodeMsg * msgReq =(struct ReqPowerNodeMsg *)osal_msg_allocate(sizeof(struct ReqPowerNodeMsg) ); msg = &(msgReq->isr); msg->isr = eventReqPowerNode; msg->msg.event = EVENT_USB_ISR; msgReq->data[0] = USBF2; msgReq->data[1] = USBF2; } break; case REQ_IEEE_ADDRESS:{ struct ReqIeeeAddrMsg * msgReq = (struct ReqIeeeAddrMsg *)osal_msg_allocate(sizeof(struct ReqIeeeAddrMsg) ); msg = &(msgReq->isr); msg->isr = eventReqIeeeAddr; msg->msg.event = EVENT_USB_ISR; msgReq->data[0] = USBF2; msgReq->data[1] = USBF2; msgReq->requestType = USBF2; msgReq->startIndex = USBF2; break; } case WRITE_ATTRIBUTE_VALUE:{ struct WriteAttributeValueUsbMsg usbMsg; uint8 * data = (uint8 *)(&usbMsg); uint8 i; for(i=0; i < sizeof(struct WriteAttributeValueUsbMsg); i++){ *data = USBF2; data++; } struct WriteAttributeValueMsg * msgCmd = (struct WriteAttributeValueMsg *)osal_msg_allocate(sizeof(struct WriteAttributeValueMsg) +sizeof(zclWriteRec_t) + usbMsg.dataValueLen ); msg = &(msgCmd->isr); msg->isr = eventWriteValue; msg->msg.event = EVENT_USB_ISR; msgCmd->afAddrType.addrMode=afAddr16Bit; msgCmd->afAddrType.addr.shortAddr=usbMsg.nwkAddr; msgCmd->afAddrType.endPoint=usbMsg.endpoint; msgCmd->cluster = usbMsg.cluster; msgCmd->writeCmd.numAttr=1; msgCmd->writeCmd.attrList->attrID = usbMsg.attributeId; msgCmd->writeCmd.attrList->dataType=usbMsg.dataType; data = ((uint8 *)msgCmd) + sizeof(struct WriteAttributeValueMsg) +sizeof(zclWriteRec_t); msgCmd->writeCmd.attrList->attrData = data; for(i=0; i < usbMsg.dataValueLen; i++){ *data = USBF2; data++; } } break; case SEND_CMD:{ struct SendCmdUsbMsg usbMsg; uint8 * data = (uint8 *)(&usbMsg); uint8 i; for(i=0; i < sizeof(struct SendCmdUsbMsg); i++){ *data = USBF2; data++; } struct SendCmdMsg * msgCmd = (struct SendCmdMsg *)osal_msg_allocate(sizeof(struct SendCmdMsg) +usbMsg.dataLen ); msg = &(msgCmd->isr); msg->isr = eventSendCmd; msg->msg.event = EVENT_USB_ISR; msgCmd->cluster =usbMsg.cluster; msgCmd->cmdClusterId = usbMsg.cmdClusterId; msgCmd->afAddrType.addr.shortAddr= usbMsg.nwkAddr; msgCmd->afAddrType.addrMode = afAddr16Bit; msgCmd->afAddrType.endPoint = usbMsg.endpoint; msgCmd->dataLen = usbMsg.dataLen; data = (uint8 *)(msgCmd->data); for(i=0; i < usbMsg.dataLen; i++){ *data = USBF2; data++; } } break; case REQ_ATTRIBUTE_VALUES: { struct ReqAttributeValueMsg attr; uint8 * data = (uint8 *)(&attr); uint8 i; for(i=0; i < sizeof(struct ReqAttributeValueMsg); i++){ *data = USBF2; data++; } struct ReqAttributeMsg * msgAttr = (struct ReqAttributeMsg *)osal_msg_allocate(sizeof(struct ReqAttributeMsg) +attr.numAttributes* sizeof(uint16) ); msg = &(msgAttr->isr); msg->isr = attributeValue; msg->msg.event = EVENT_USB_ISR; msgAttr->afAddrType.addr.shortAddr = attr.nwkAddr; msgAttr->afAddrType.addrMode = afAddr16Bit; msgAttr->afAddrType.endPoint = attr.endpoint; msgAttr->numAttr = attr.numAttributes; data = (uint8 *)&msgAttr->attrID; for (uint8 i=0; i < attr.numAttributes; i++){ *data = USBF2; data++; *data = USBF2; data++; } msgAttr->cluster = attr.cluster; osal_msg_send(zusbTaskId, (uint8 *)msg); break; } case REQ_DEVICE_INFO:{ struct ReqDeviceInformationEvent * msgEP = (struct ReqDeviceInformationEvent *)osal_msg_allocate(sizeof(struct ReqDeviceInformationEvent) ); msg = &(msgEP->isr); msg->isr = eventDeviceInfo; msg->msg.event = EVENT_USB_ISR; msgEP->data[0] = USBF2; msgEP->data[1] = USBF2; } break; } if (msg != NULL) { uint8 low = T1CNTL; uint8 hi = T1CNTH; msg->time=BUILD_UINT16(low,hi); osal_msg_send(zusbTaskId, (uint8 *)msg); } /*uint8 __generic *pTemp = rxData; do { *(pTemp++) = USBF2; } while (--length);*/ } USBFW_ARM_OUT_ENDPOINT(); USBFW_SELECT_ENDPOINT(oldEndpoint); } }
/** \brief USB Setup Handler * * This function should be called either from the USB interrupt or the main loop when the \c USBIIF.EP0IF * flag has been set. Keep in mind that all bits in \c USBIIF register are cleared when the register is * read. A detailed description of the framework is found in the \ref section_setup_handler_usage * section. * * \note The USB header data is always little-endian, so if a big-endian compiler is used (such as Keil * C51), the 16-bit values in the \ref usbSetupHeader must be flipped before they are used. */ void usbfwSetupHandler(void) { uint8 controlReg; uint8 bytesNow; uint8 oldEndpoint; // Save the old index setting, then select endpoint 0 and fetch the control register oldEndpoint = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(0); controlReg = USBCS0; // The last transfer was ended prematurely by a new SETUP packet if (controlReg & USBCS0_SETUP_END) { USBCS0 = USBCS0_CLR_SETUP_END; usbfwData.ep0Status = EP_CANCEL; if (ProcessFunc) ProcessFunc(); usbfwData.ep0Status = EP_IDLE; } // A STALL handshake was transmitted to the PC if (controlReg & USBCS0_SENT_STALL) { USBCS0 = 0x00; usbfwData.ep0Status = EP_IDLE; } // Receive OUT packets if (usbfwData.ep0Status == EP_RX) { // Read FIFO bytesNow = USBCNT0; usbfwReadFifo(&USBF0, bytesNow, usbSetupData.pBuffer); usbSetupData.bytesLeft -= bytesNow; usbSetupData.pBuffer += bytesNow; // Arm the endpoint USBCS0 = usbSetupData.bytesLeft ? USBCS0_CLR_OUTPKT_RDY : (USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END); // Make a call to the appropriate request handler when done if (usbSetupData.bytesLeft == 0) { if (ProcessFunc) ProcessFunc(); usbfwData.ep0Status = EP_IDLE; } // Return here since nothing more will happen until the next interrupt USBFW_SELECT_ENDPOINT(oldEndpoint); return; // Let the application handle the reception } else if (usbfwData.ep0Status == EP_MANUAL_RX) { ProcessFunc(); } // Receive SETUP header if (usbfwData.ep0Status == EP_IDLE) { if (controlReg & USBCS0_OUTPKT_RDY) { usbfwReadFifo(&USBF0, 8, (uint8 __xdata *) &usbSetupHeader); // Handle control transfers individually ProcessFunc = NULL; switch (usbSetupHeader.requestType & (RT_MASK_TYPE | RT_MASK_DIR)) { // Standard requests with data from the host (OUT) case RT_STD_OUT: switch (usbSetupHeader.request) { case SET_ADDRESS: usbsrSetAddress(); break; case SET_FEATURE: usbsrSetFeature(); break; case CLEAR_FEATURE: usbsrClearFeature(); break; case SET_CONFIGURATION: usbsrSetConfiguration(); break; case SET_INTERFACE: usbsrSetInterface(); break; case SET_DESCRIPTOR: /*usbsrHookSetDescriptor(); break; - unsupported */ default: usbfwData.ep0Status = EP_STALL; break; } break; // Standard requests with data to the host (IN) case RT_STD_IN: switch (usbSetupHeader.request) { case GET_STATUS: usbsrGetStatus(); break; case GET_DESCRIPTOR: usbsrGetDescriptor(); break; case GET_CONFIGURATION: usbsrGetConfiguration(); break; case GET_INTERFACE: usbsrGetInterface(); break; case SYNCH_FRAME: /*usbsrHookSynchFrame(); break; - unsupported */ default: usbfwData.ep0Status = EP_STALL; break; } break; // Vendor requests case RT_VEND_OUT: ProcessFunc = usbvrHookProcessOut; usbvrHookProcessOut(); break; case RT_VEND_IN: ProcessFunc = usbvrHookProcessIn; usbvrHookProcessIn(); break; // Class requests case RT_CLASS_OUT: ProcessFunc = usbcrHookProcessOut; usbcrHookProcessOut(); break; case RT_CLASS_IN: ProcessFunc = usbcrHookProcessIn; usbcrHookProcessIn(); break; // Unrecognized request: Stall the endpoint default: usbfwData.ep0Status = EP_STALL; break; } // Arm/stall the endpoint USBCS0 = (usbfwData.ep0Status == EP_STALL) ? (USBCS0_CLR_OUTPKT_RDY | USBCS0_SEND_STALL) : USBCS0_CLR_OUTPKT_RDY; } } // Transmit IN packets if (usbfwData.ep0Status == EP_TX) { controlReg = USBCS0_INPKT_RDY; // The last frame should contain 0 to (EP0_PACKET_SIZE - 1) bytes if (usbSetupData.bytesLeft < EP0_PACKET_SIZE) { bytesNow = usbSetupData.bytesLeft; controlReg |= USBCS0_DATA_END; // All other packets should have the maximum length } else { bytesNow = EP0_PACKET_SIZE; } // Load the FIFO and move the pointer usbfwWriteFifo(&USBF0, bytesNow, usbSetupData.pBuffer); usbSetupData.pBuffer += bytesNow; usbSetupData.bytesLeft -= bytesNow; // Arm the FIFO (even for a zero-length packet) USBCS0 = controlReg; // Make a call to the appropriate request handler when done if (bytesNow < EP0_PACKET_SIZE) { if (ProcessFunc) ProcessFunc(); usbfwData.ep0Status = EP_IDLE; } // Let the application handle the transmission } else if (usbfwData.ep0Status == EP_MANUAL_TX) { ProcessFunc(); } // Restore the old index setting USBFW_SELECT_ENDPOINT(oldEndpoint); } // usbfwSetupHandler
/*********************************************************************************** * @fn usbOutProcess * * @brief Handle traffic flow from USB to RF. * * @param none * * @return none */ static void usbOutProcess(void) { uint8 length, /*nToSend,*/ packetlength=0; // If new packet is ready in USB FIFO halIntOff(); oldEndpoint = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(4); if (USBFW_OUT_ENDPOINT_DISARMED() ) { // Get length of USB packet, this operation must not be interrupted. length = USBFW_GET_OUT_ENDPOINT_COUNT_LOW(); length+= USBFW_GET_OUT_ENDPOINT_COUNT_HIGH() >> 8; // Avoid overflow message_length = USB_MAX_MESSAGE_LENGTH; if (usb_bufferIndex + length > USB_MAX_MESSAGE_LENGTH) usb_bufferIndex=0; // Copy received bytes from FIFO to buffer usbfwReadFifo(&USBF4, length, &usb_buffer[usb_bufferIndex]); // Increase buffer index usb_bufferIndex += length; // If entire USB packet is read from buffer USBFW_SELECT_ENDPOINT(4); USBFW_ARM_OUT_ENDPOINT(); // get packet lenght from byte #2 of received packet if ((usb_bufferIndex >= 2) && (packetlength == 0)) packetlength = usb_buffer[2]; if ((usb_bufferIndex > packetlength-1) && (packetlength >= USB_MIN_MESSAGE_LENGTH)) { //extract data from packet usb_decode(); usb_bufferIndex = 0; } /* // Calculate number of bytes available in RF buffer; and the number // of bytes we may transfer in this operation. nToSend= MIN(BUF_SIZE - bufNumBytes(&rbRxBuf), length); // Space available in UART RX buffer ? if (nToSend>0) { // Read from USB FIFO usbfwReadFifo(&USBF4, nToSend, buffer); // Write to radio TX buffer bufPut(&rbRxBuf,buffer,nToSend); // If entire USB packet is read from buffer if (length == nToSend) { USBFW_SELECT_ENDPOINT(4); USBFW_ARM_OUT_ENDPOINT(); } }*/ } USBFW_SELECT_ENDPOINT(oldEndpoint); halIntOn(); }
/** \brief USB Setup Handler * * This function should be called either from the USB interrupt or the main loop when the * \c USB_IIF.EP0IF flag has been set. A detailed description of the framework is found in the * \ref section_setup_handler_usage section. */ void usbfwSetupHandler(void) { uint32_t controlReg; uint32_t oldEndpoint; uint32_t bytesNow; // // Save the old index setting, then select endpoint 0 and fetch the control register // oldEndpoint = USBFW_GET_SELECTED_ENDPOINT(); USBFW_SELECT_ENDPOINT(0); controlReg = HWREG(USB_CS0); // // Update the USB device address after the status stage // if(usbfwData.ep0Status == EP_ADDRESS) { if(!(controlReg & USB_CS0_OUTPKTRDY_M)) { uint8_t address = usbSetupHeader.valueLsb; HWREG(USB_ADDR) = address; if(usbfwData.usbState < DEV_CONFIGURED) { if(address) { usbfwData.usbState = DEV_ADDRESS; } else { usbfwData.usbState = DEV_DEFAULT; } } } usbfwData.ep0Status = EP_IDLE; } // // A STALL handshake was transmitted to the host // if(controlReg & USB_CS0_SENTSTALL_M) { HWREG(USB_CS0) = 0x00; usbfwData.ep0Status = EP_IDLE; } // // The last transfer was ended prematurely by a new SETUP packet // if(controlReg & USB_CS0_SETUPEND_M) { HWREG(USB_CS0) = USB_CS0_CLRSETUPEND_M; usbfwData.ep0Status = EP_CANCEL; if(pProcessFunc) { pProcessFunc(); } usbfwData.ep0Status = EP_IDLE; } // // Receive OUT packets // if(usbfwData.ep0Status == EP_RX) { if(controlReg & USB_CS0_OUTPKTRDY_M) { // // Read FIFO // uint32_t bytesNow = HWREG(USB_CNT0); usbfwReadFifo(USB_F0, bytesNow, usbSetupData.pBuffer); usbSetupData.bytesLeft -= bytesNow; usbSetupData.pBuffer = ((uint8_t*) usbSetupData.pBuffer) + bytesNow; // // Arm the endpoint // if(usbSetupData.bytesLeft) { HWREG(USB_CS0) = USB_CS0_CLROUTPKTRDY_M; } else { HWREG(USB_CS0) = USB_CS0_CLROUTPKTRDY_M | USB_CS0_DATAEND_M; } // // Make a call to the appropriate request handler when done // if(usbSetupData.bytesLeft == 0) { if(pProcessFunc) { pProcessFunc(); } usbfwData.ep0Status = EP_IDLE; } } // // Return here since nothing more will happen until the next interrupt // USBFW_SELECT_ENDPOINT(oldEndpoint); return; // // Let the application handle the reception // } else if(usbfwData.ep0Status == EP_MANUAL_RX) { if(pProcessFunc) { pProcessFunc(); } } // // Receive SETUP header // if(usbfwData.ep0Status == EP_IDLE) { if(controlReg & USB_CS0_OUTPKTRDY_M) { usbfwReadFifo(USB_F0, 8, &usbSetupHeader); // // Handle control transfers individually // pProcessFunc = NULL; switch(usbSetupHeader.requestType & (RT_MASK_TYPE | RT_MASK_DIR)) { // // Standard requests without data or with data from the host (OUT) // case RT_STD_OUT: switch(usbSetupHeader.request) { case USBSR_REQ_SET_ADDRESS: usbsrSetAddress(); break; case USBSR_REQ_SET_FEATURE: usbsrSetFeature(); break; case USBSR_REQ_CLEAR_FEATURE: usbsrClearFeature(); break; case USBSR_REQ_SET_CONFIGURATION: usbsrSetConfiguration(); break; case USBSR_REQ_SET_INTERFACE: usbsrSetInterface(); break; case USBSR_REQ_SET_DESCRIPTOR: pProcessFunc = usbsrHookSetDescriptor; usbsrHookSetDescriptor(); break; default: usbfwData.ep0Status = EP_STALL; break; } break; // // Standard requests with data to the host (IN) // case RT_STD_IN: switch(usbSetupHeader.request) { case USBSR_REQ_GET_STATUS: usbsrGetStatus(); break; case USBSR_REQ_GET_DESCRIPTOR: usbsrGetDescriptor(); break; case USBSR_REQ_GET_CONFIGURATION: usbsrGetConfiguration(); break; case USBSR_REQ_GET_INTERFACE: usbsrGetInterface(); break; case USBSR_REQ_SYNCH_FRAME: pProcessFunc = usbsrHookSynchFrame; usbsrHookSynchFrame(); break; default: usbfwData.ep0Status = EP_STALL; break; } break; // // Vendor requests // case RT_VEND_OUT: pProcessFunc = usbvrHookProcessOut; usbvrHookProcessOut(); break; case RT_VEND_IN: pProcessFunc = usbvrHookProcessIn; usbvrHookProcessIn(); break; // // Class requests // case RT_CLASS_OUT: pProcessFunc = usbcrHookProcessOut; usbcrHookProcessOut(); break; case RT_CLASS_IN: pProcessFunc = usbcrHookProcessIn; usbcrHookProcessIn(); break; // // Unrecognized request: Stall the endpoint // default: usbfwData.ep0Status = EP_STALL; break; } // // Arm/stall the endpoint // if(usbfwData.ep0Status == EP_STALL) { HWREG(USB_CS0) = USB_CS0_CLROUTPKTRDY_M | USB_CS0_SENDSTALL_M; } else if((usbfwData.ep0Status == EP_TX) || (usbfwData.ep0Status == EP_RX)) { HWREG(USB_CS0) = USB_CS0_CLROUTPKTRDY_M; } else { HWREG(USB_CS0) = USB_CS0_CLROUTPKTRDY_M | USB_CS0_DATAEND_M; } } } // // Transmit IN packets // if(usbfwData.ep0Status == EP_TX) { controlReg = USB_CS0_INPKTRDY_M; // // The last frame should contain 0 to (EP0_PACKET_SIZE - 1) bytes // if(usbSetupData.bytesLeft < USB_EP0_PACKET_SIZE) { bytesNow = usbSetupData.bytesLeft; controlReg |= USB_CS0_DATAEND_M; } else { // // All other packets should have the maximum length // bytesNow = USB_EP0_PACKET_SIZE; } // // Load the FIFO and move the pointer // usbfwWriteFifo(USB_F0, bytesNow, usbSetupData.pBuffer); usbSetupData.pBuffer = ((uint8_t*) usbSetupData.pBuffer) + bytesNow; usbSetupData.bytesLeft -= bytesNow; // // Arm the FIFO (even for a zero-length packet) // HWREG(USB_CS0) = controlReg; // // Make a call to the appropriate request handler when done // if(bytesNow < USB_EP0_PACKET_SIZE) { if(pProcessFunc) { pProcessFunc(); } usbfwData.ep0Status = EP_IDLE; } // // Let the application handle the transmission // } else if(usbfwData.ep0Status == EP_MANUAL_TX) { if(pProcessFunc) { pProcessFunc(); } } // // Restore the old index setting // USBFW_SELECT_ENDPOINT(oldEndpoint); }