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

}
Esempio n. 2
0
/***********************************************************************************
* @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           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();
}
/**************************************************************************************************
 * @fn      hidSendHidInReport
 *
 * @brief   Send HID Consumer Control report.
 *
 * input parameters
 *
 * @param   pReport - report to be sent
 * @param   endPoint - endPoint associated with report.
 * @param   len - length of report
 *
 * output parameters
 *
 * None.
 *
 * @return  TRUE if report was sent; FALSE otherwise.
 */
uint8 hidSendHidInReport(uint8 *pReport, uint8 endPoint, uint8 len)
{
  uint8 result = FALSE;

  if (endPoint < 6)
  {
    uint8 ea = halIntLock();

    USBFW_SELECT_ENDPOINT(endPoint);
    if (!(USBCSIL & USBCSIL_INPKT_RDY))
    {
      usbfwWriteFifo(((&USBF0) + (endPoint << 1)), len, pReport);
      USBCSIL |= USBCSIL_INPKT_RDY;
      result = TRUE;
    }
    halIntUnlock(ea);
  }

  return result;
}
Esempio n. 5
0
uint8_t hidSendMouseInReport(void)
{
    uint8_t result = false;
    bool intDisabled = IntMasterDisable();

    USBFW_SELECT_ENDPOINT(2);
    if(!(HWREG(USB_CSIL) & USB_CSIL_INPKTRDY_M))
    {
        //
        // Send the report
        //
        usbfwWriteFifo(USB_F2, sizeof(MOUSE_IN_REPORT), &hidData.mouseInReport);
        HWREG(USB_CSIL) |= USB_CSIL_INPKTRDY_M;
        result = true;
    }
    if(!intDisabled)
    {
        IntMasterEnable();
    }

    return result;
}
/** \brief Internally used function that configures all endpoints for the specified interface
 *
 * The new endpoint setup overwrites the old, without any warning. Unused endpoints keep their current
 * setup. The user is responsible for ensuring that no endpoint buffers overwrite each other, and that
 * interfaces do not cause conflicts. The pUsbDblbufLutInfo table must contain an entry for each
 * interface descriptor to define endpoint double-buffering.
 *
 * \param[in]       *pInterface
 *     A pointer to the interface descriptor
 */
static void ConfigureEndpoints(USB_INTERFACE_DESCRIPTOR __xdata *pInterface)
{
   uint8 n;
   uint16 maxpRegValue;
   uint8 csRegValue;
   uint8 endpoint;
   USB_ENDPOINT_DESCRIPTOR __xdata *pEndpoint;
   DBLBUF_LUT_INFO __xdata *pUsbDblbufLutInfo;

   // Locate the double buffer settings
   if (!pInterface->bNumEndpoints) {
       return;
   }
   pUsbDblbufLutInfo = (DBLBUF_LUT_INFO __xdata*) usbDescriptorMarker.pUsbDblbufLut;
   while (pUsbDblbufLutInfo->pInterface != pInterface) {
      pUsbDblbufLutInfo++;
   }

   // For each endpoint in this interface
   for (n = 0; n < pInterface->bNumEndpoints; n++) {
      if (pEndpoint = usbdpFindNext(DESC_TYPE_ENDPOINT, 0)) {

         // Get the endpoint index
         endpoint = pEndpoint->bEndpointAddress & 0x0F;
         USBFW_SELECT_ENDPOINT(endpoint);

         csRegValue = 0x00;
         maxpRegValue = (pEndpoint->wMaxPacketSize + 7) >> 3;

         // For IN endpoints...
         if (pEndpoint->bEndpointAddress & 0x80) {

            // Clear data toggle, and flush twice (due to double buffering)
            USBCSIL = USBCSIL_CLR_DATA_TOG | USBCSIL_FLUSH_PACKET;
            USBCSIL = USBCSIL_FLUSH_PACKET;

            // USBCSIH
            if ((pEndpoint->bmAttributes & EP_ATTR_TYPE_BM) == EP_ATTR_ISO) csRegValue |= USBCSIH_ISO;  // ISO flag
            if (pUsbDblbufLutInfo->inMask & (1 << endpoint)) csRegValue |= USBCSIH_IN_DBL_BUF;          // Double buffering
            USBCSIH = csRegValue;

            // Max transfer size
            USBMAXI = maxpRegValue;

            // Endpoint status
            usbfwData.pEpInStatus[endpoint - 1] = EP_IDLE;

         // For OUT endpoints...
         } else {

            // Clear data toggle, and flush twice (due to double buffering)
            USBCSOL = USBCSOL_CLR_DATA_TOG | USBCSOL_FLUSH_PACKET;
            USBCSOL = USBCSOL_FLUSH_PACKET;

            // USBCSOH
            if ((pEndpoint->bmAttributes & EP_ATTR_TYPE_BM) == EP_ATTR_ISO) csRegValue |= USBCSOH_ISO;  // ISO flag
            if (pUsbDblbufLutInfo->outMask & (1 << endpoint)) csRegValue |= USBCSOH_OUT_DBL_BUF;        // Double buffering
            USBCSOH = csRegValue;

            // Max transfer size
            USBMAXO = maxpRegValue;

            // Endpoint status
            usbfwData.pEpOutStatus[endpoint - 1] = EP_IDLE;
         }
         USBFW_SELECT_ENDPOINT(0);
      }
   }
/** \brief Internal function used for the very similar \ref SET_FEATURE and \ref CLEAR_FEATURE requests
 *
 * This function either sets or clears the specified feature on the specified recipient.
 *
 * \param[in]       set
 *     When TRUE, the feature is set. When FALSE, the feature is cleared.
 *
 * \return
 *     TRUE if the selected feature is supported by the USB library. FALSE to indicate that
 *     \ref usbsrHookClearFeature() or \ref usbsrHookSetFeature() must be called.
 */
static uint8 ChangeFeature(uint8 set)
{
   uint8 endpoint;

   // Sanity check
   if (usbSetupHeader.length || (usbfwData.usbState != DEV_CONFIGURED) && (usbSetupHeader.index != 0)) {
      usbfwData.ep0Status = EP_STALL;

      // Handle based on recipient
   } else {
      switch (usbSetupHeader.requestType & RT_MASK_RECIP) {

      // Device
      case RT_RECIP_DEV:

         // Sanity check
         if (LO_UINT16(usbSetupHeader.value) != DEVICE_REMOTE_WAKEUP) {
            return FALSE;
         } else {
            usbfwData.remoteWakeup = set;
            usbsrHookProcessEvent(set ? USBSR_EVENT_REMOTE_WAKEUP_ENABLED : USBSR_EVENT_REMOTE_WAKEUP_DISABLED, 0);
         }
         break;

      // Endpoint
      case RT_RECIP_IF:
         return FALSE;

      // Endpoint
      case RT_RECIP_EP:
         endpoint = LO_UINT16(usbSetupHeader.index) & 0x7F;

         // Sanity check
         if (LO_UINT16(usbSetupHeader.value) != ENDPOINT_HALT) {
            return FALSE;
         } else if (endpoint > 5) {
            usbfwData.ep0Status = EP_STALL;
         } else {
            USBFW_SELECT_ENDPOINT(endpoint);

            // IN
            if (LO_UINT16(usbSetupHeader.index) & 0x80) {
               USBCSIL = set ? USBCSIL_SEND_STALL : USBCSIL_CLR_DATA_TOG;
               usbfwData.pEpInStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE;
               usbsrHookProcessEvent(set ? USBSR_EVENT_EPIN_STALL_SET : USBSR_EVENT_EPIN_STALL_CLEARED, endpoint);

            // OUT
            } else {
               USBCSOL = set ? USBCSOL_SEND_STALL : USBCSOL_CLR_DATA_TOG;
               usbfwData.pEpOutStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE;
               usbsrHookProcessEvent(set ? USBSR_EVENT_EPOUT_STALL_SET : USBSR_EVENT_EPOUT_STALL_CLEARED, endpoint);
            }
            USBFW_SELECT_ENDPOINT(0);
         }
         break;

      default:
         usbfwData.ep0Status = EP_STALL;
         break;
      }
   }
   return TRUE;
} // ChangeFeature
// ************************ 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);
	}
}
Esempio n. 9
0
/** \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
Esempio n. 10
0
/** \brief Internally used function that configures all endpoints for the specified interface
 *
 * The new endpoint setup overwrites the old. Unused endpoints keep their current setup. The user is
 * responsible for ensuring that no endpoint buffers overwrite each other, and that interfaces do not
 * cause conflicts. The \ref pUsbInterfaceEpDblbufLut[] lookup table must contain an entry for each
 * interface descriptor to define endpoint double-buffering.
 *
 * \param[in]       *pInterface
 *     A pointer to the interface descriptor
 */
static void usbsrConfigureEndpoints(const USB_INTERFACE_DESCRIPTOR* pInterface)
{
    const USB_ENDPOINT_DESCRIPTOR* pEndpoint;
    const USB_INTERFACE_EP_DBLBUF_LUT* pUsbInterfaceEpDblbufInfo;

    //
    // Locate the double-buffer settings
    //
    if(pInterface->bNumEndpoints)
    {
        pUsbInterfaceEpDblbufInfo = (const USB_INTERFACE_EP_DBLBUF_LUT*) pUsbInterfaceEpDblbufLut;
        while(pUsbInterfaceEpDblbufInfo->pInterface != pInterface)
        {
            pUsbInterfaceEpDblbufInfo++;
        }
    }

    //
    // For each endpoint in this interface
    //
    for(uint8_t n = 0; n < pInterface->bNumEndpoints; n++)
    {
        if(pEndpoint = usbdpFindNext(USB_DESC_TYPE_ENDPOINT, 0))
        {
            //
            // Get the endpoint index
            //
            uint32_t endpoint = pEndpoint->bEndpointAddress & 0x0F;
            USBFW_SELECT_ENDPOINT(endpoint);

            uint32_t csRegValue = 0x00;
            uint32_t maxpRegValue = (pEndpoint->wMaxPacketSize + 7) >> 3;

            //
            // For IN endpoints...
            //
            if(pEndpoint->bEndpointAddress & 0x80)
            {
                //
                // Clear data toggle, and flush twice (due to double buffering)
                //
                HWREG(USB_CS0_CSIL) = USB_CSIL_CLRDATATOG_M | USB_CSIL_FLUSHPACKET_M;
                HWREG(USB_CS0_CSIL) = USB_CSIL_FLUSHPACKET_M;
                
                //
                // USBCSIH
                //
                if((pEndpoint->bmAttributes & USB_EP_ATTR_TYPE_BM) == USB_EP_ATTR_ISO)
                {
                    //
                    // ISO flag
                    //
                    csRegValue |= USB_CSIH_ISO_M;
                }
                if(pUsbInterfaceEpDblbufInfo->inMask & (1 << endpoint))
                {
                    //
                    // Double buffering
                    //
                    csRegValue |= USB_CSIH_INDBLBUF_M;
                }
                HWREG(USB_CSIH) = csRegValue;

                //
                // Max transfer size
                //
                HWREG(USB_MAXI) = maxpRegValue;

                //
                // Endpoint status
                //
                usbfwData.pEpInStatus[endpoint - 1] = EP_IDLE;

                //
                // For OUT endpoints...
                //
            }
            else
            {
                //
                // Clear data toggle, and flush twice (due to double buffering)
                //
                HWREG(USB_CSOL) = USB_CSOL_CLRDATATOG_M | USB_CSOL_FLUSHPACKET_M;
                HWREG(USB_CSOL) = USB_CSOL_FLUSHPACKET_M;

                //
                // USBCSOH
                //
                if((pEndpoint->bmAttributes & USB_EP_ATTR_TYPE_BM) == USB_EP_ATTR_ISO)
                {
                    //
                    // ISO flag
                    //
                    csRegValue |= USB_CSOH_ISO_M;    
                }
                if(pUsbInterfaceEpDblbufInfo->outMask & (1 << endpoint))
                {
                    //
                    // Double buffering
                    //
                    csRegValue |= USB_CSOH_OUTDBLBUF_M;    
                }
                HWREG(USB_CSOH) = csRegValue;

                //
                // Max transfer size
                //
                HWREG(USB_MAXO) = maxpRegValue;

                //
                // Endpoint status
                //
                usbfwData.pEpOutStatus[endpoint - 1] = EP_IDLE;
            }
            USBFW_SELECT_ENDPOINT(0);
        }
    }
Esempio n. 11
0
/** \brief Internal function used for the very similar \c SET_FEATURE and \c CLEAR_FEATURE requests
 *
 * This function either sets or clears the specified feature on the specified recipient.
 *
 * \param[in]       set
 *     When TRUE, the feature is set. When FALSE, the feature is cleared.
 *
 * \return
 *     TRUE if the selected feature is supported by the USB library. FALSE to indicate that
 *     \ref usbsrHookClearFeature() or \ref usbsrHookSetFeature() must be called.
 */
static uint8_t usbsrChangeFeature(uint8_t set)
{
    uint8_t endpoint;
    
    //
    // Sanity check
    //
    if(usbSetupHeader.length || ((usbfwData.usbState != DEV_CONFIGURED) && (usbSetupHeader.index != 0)))
    {
        usbfwData.ep0Status = EP_STALL;
        //
        // Handle based on recipient
        //
    }
    else
    {
        switch(usbSetupHeader.requestType & RT_MASK_RECIP)
        {
            //
            // Device
            //
        case RT_RECIP_DEV:
            
            //
            // Sanity check
            //
            if(usbSetupHeader.valueLsb != USBSR_FEATSEL_DEVICE_REMOTE_WAKEUP)
            {
                return false;
            }
            else
            {
                usbfwData.remoteWakeup = set;
                usbsrHookProcessEvent(set ? USBSR_EVENT_REMOTE_WAKEUP_ENABLED : USBSR_EVENT_REMOTE_WAKEUP_DISABLED, 0);
            }
            break;
            //
            // Interface
            //
        case RT_RECIP_IF:
            return false;

            //
            // Endpoint
            //
        case RT_RECIP_EP:
            endpoint = usbSetupHeader.indexLsb & 0x7F;
            
            //
            // Sanity check
            //
            if(usbSetupHeader.valueLsb != USBSR_FEATSEL_ENDPOINT_HALT)
            {
                return false;
            }
            else if(endpoint > 5)
            {
                usbfwData.ep0Status = EP_STALL;
            }
            else
            {
                USBFW_SELECT_ENDPOINT(endpoint);
                
                //
                // IN
                //
                if(usbSetupHeader.indexLsb & 0x80)
                {
                    HWREG(USB_CS0_CSIL) = set ? USB_CSIL_SENDSTALL_M : USB_CSIL_CLRDATATOG_M;
                    usbfwData.pEpInStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE;
                    usbsrHookProcessEvent(set ? USBSR_EVENT_EPIN_STALL_SET : USBSR_EVENT_EPIN_STALL_CLEARED, endpoint);
                    
                    //
                    // OUT
                    //
                }
                else
                {
                    HWREG(USB_CSOL) = set ? USB_CSOL_SENDSTALL_M : USB_CSOL_CLRDATATOG_M;
                    usbfwData.pEpOutStatus[endpoint - 1] = set ? EP_HALT : EP_IDLE;
                    usbsrHookProcessEvent(set ? USBSR_EVENT_EPOUT_STALL_SET : USBSR_EVENT_EPOUT_STALL_CLEARED, endpoint);
                }
                USBFW_SELECT_ENDPOINT(0);
            }
            break;

        default:
            usbfwData.ep0Status = EP_STALL;
            break;
        }
    }
    return true;
}
/***********************************************************************************
* @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);
}