示例#1
0
文件: usb.c 项目: Inspirati/freeMixer
/********************************************************************
 * Function:        void USBCBSendResume(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        The USB specifications allow some types of USB
 *                  peripheral devices to wake up a host PC (such
 *                  as if it is in a low power suspend to RAM state).
 *                  This can be a very useful feature in some
 *                  USB applications, such as an Infrared remote
 *                  control    receiver.  If a user presses the "power"
 *                  button on a remote control, it is nice that the
 *                  IR receiver can detect this signalling, and then
 *                  send a USB "command" to the PC to wake up.
 *
 *                  The USBCBSendResume() "callback" function is used
 *                  to send this special USB signalling which wakes 
 *                  up the PC.  This function may be called by
 *                  application firmware to wake up the PC.  This
 *                  function will only be able to wake up the host if
 *                  all of the below are true:
 *
 *                    1.  The USB driver used on the host PC supports
 *                        the remote wakeup capability.
 *                    2.  The USB configuration descriptor indicates
 *                        the device is remote wakeup capable in the
 *                        bmAttributes field.
 *                    3.  The USB host PC is currently sleeping,
 *                        and has previously sent your device a SET 
 *                        FEATURE setup packet which "armed" the
 *                        remote wakeup capability.   
 *
 *                  If the host has not armed the device to perform remote wakeup,
 *                  then this function will return without actually performing a
 *                  remote wakeup sequence.  This is the required behavior, 
 *                  as a USB device that has not been armed to perform remote 
 *                  wakeup must not drive remote wakeup signalling onto the bus;
 *                  doing so will cause USB compliance testing failure.
 *
 *                  This callback should send a RESUME signal that
 *                  has the period of 1-15ms.
 *
 * Note:            This function does nothing and returns quickly, if the USB
 *                  bus and host are not in a suspended condition, or are 
 *                  otherwise not in a remote wakeup ready state.  Therefore, it
 *                  is safe to optionally call this function regularly, ex: 
 *                  anytime application stimulus occurs, as the function will
 *                  have no effect, until the bus really is in a state ready
 *                  to accept remote wakeup. 
 *
 *                  When this function executes, it may perform clock switching,
 *                  depending upon the application specific code in 
 *                  USBCBWakeFromSuspend().  This is needed, since the USB
 *                  bus will no longer be suspended by the time this function
 *                  returns.  Therefore, the USB module will need to be ready
 *                  to receive traffic from the host.
 *
 *                  The modifiable section in this routine may be changed
 *                  to meet the application needs. Current implementation
 *                  temporary blocks other functions from executing for a
 *                  period of ~3-15 ms depending on the core frequency.
 *
 *                  According to USB 2.0 specification section 7.1.7.7,
 *                  "The remote wakeup device must hold the resume signaling
 *                  for at least 1 ms but for no more than 15 ms."
 *                  The idea here is to use a delay counter loop, using a
 *                  common value that would work over a wide range of core
 *                  frequencies.
 *                  That value selected is 1800. See table below:
 *                  ==========================================================
 *                  Core Freq(MHz)      MIP         RESUME Signal Period (ms)
 *                  ==========================================================
 *                      48              12          1.05
 *                       4              1           12.6
 *                  ==========================================================
 *                  * These timing could be incorrect when using code
 *                    optimization or extended instruction mode,
 *                    or when having other interrupts enabled.
 *                    Make sure to verify using the MPLAB SIM's Stopwatch
 *                    and verify the actual signal on an oscilloscope.
 *******************************************************************/
void USBCBSendResume(void)
{
	static WORD delay_count;

	// First verify that the host has armed us to perform remote wakeup.
	// It does this by sending a SET_FEATURE request to enable remote wakeup,
	// usually just before the host goes to standby mode (note: it will only
	// send this SET_FEATURE request if the configuration descriptor declares
	// the device as remote wakeup capable, AND, if the feature is enabled
	// on the host (ex: on Windows based hosts, in the device manager 
	// properties page for the USB device, power management tab, the 
	// "Allow this device to bring the computer out of standby." checkbox 
	// should be checked).
	if (USBGetRemoteWakeupStatus() == TRUE) 
	{
		// Verify that the USB bus is in fact suspended, before we send
		// remote wakeup signalling.
		if (USBIsBusSuspended() == TRUE)
		{
			USBMaskInterrupts();

			// Clock switch to settings consistent with normal USB operation.
			USBCBWakeFromSuspend();
			USBSuspendControl = 0; 
			USBBusIsSuspended = FALSE;  // So we don't execute this code again, 
			                            // until a new suspend condition is detected.

			// Section 7.1.7.7 of the USB 2.0 specifications indicates a USB
			// device must continuously see 5ms+ of idle on the bus, before it sends
			// remote wakeup signalling.  One way to be certain that this parameter
			// gets met, is to add a 2ms+ blocking delay here (2ms plus at 
			// least 3ms from bus idle to USBIsBusSuspended() == TRUE, yeilds
			// 5ms+ total delay since start of idle).
			delay_count = 3600U;
			do
			{
				delay_count--;
			} while(delay_count);

			// Now drive the resume K-state signalling onto the USB bus.
			USBResumeControl = 1;       // Start RESUME signaling
			delay_count = 1800U;        // Set RESUME line for 1-13 ms
			do
			{
				delay_count--;
			} while(delay_count);
			USBResumeControl = 0;       // Finished driving resume signalling

			USBUnmaskInterrupts();
		}
	}
}
示例#2
0
文件: main.c 项目: jrapp01/SrDesign
void USBCBSendResume(void)
{
    static WORD delay_count;

    if(USBGetRemoteWakeupStatus() == TRUE) 
    {
        // Verify that the USB bus is in fact suspended, before we send
        // remote wakeup signalling.
        if(USBIsBusSuspended() == TRUE)
        {
            USBMaskInterrupts();
            
            // Clock switch to settings consistent with normal USB operation.
            // USBCBWakeFromSuspend();
            USBSuspendControl = 0; 
            USBBusIsSuspended = FALSE;  // So we don't execute this code again,
                                        // until a new suspend condition is
                                        // detected.

            // Section 7.1.7.7 of the USB 2.0 specifications indicates a USB
            // device must continuously see 5ms+ of idle on the bus, before it
            // sends remote wakeup signalling.  One way to be certain that this
            // parameter gets met, is to add a 2ms+ blocking delay here
            // (2ms plus at least 3ms from bus idle to
            // USBIsBusSuspended() == TRUE, yeilds 5ms+ total delay since start
            // of idle).
            delay_count = 3600U;        
            do
            {
                delay_count--;
            }while(delay_count);
            
            //Now drive the resume K-state signalling onto the USB bus.
            USBResumeControl = 1;       // Start RESUME signaling
            delay_count = 1800U;        // Set RESUME line for 1-13 ms
            do
            {
                delay_count--;
            }while(delay_count);
            USBResumeControl = 0;       //Finished driving resume signalling

            USBUnmaskInterrupts();
        }
    }
}
示例#3
0
// Send resume call-back
void USBCBSendResume(void)
{
    static WORD delay_count;
    
    // Verify that the host has armed us to perform remote wakeup.
    if(USBGetRemoteWakeupStatus() == FLAG_TRUE) 
    {
        // Verify that the USB bus is suspended (before we send remote wakeup signalling).
        if(USBIsBusSuspended() == FLAG_TRUE)
        {
            USBMaskInterrupts();
            
            // Bring the clock speed up to normal running state
            USBCBWakeFromSuspend();
            USBSuspendControl = 0; 
            USBBusIsSuspended = FLAG_FALSE;

            // Section 7.1.7.7 of the USB 2.0 specifications indicates a USB
            // device must continuously see 5ms+ of idle on the bus, before it sends
            // remote wakeup signalling.  One way to be certain that this parameter
            // gets met, is to add a 2ms+ blocking delay here (2ms plus at 
            // least 3ms from bus idle to USBIsBusSuspended() == FLAG_TRUE, yeilds
            // 5ms+ total delay since start of idle).
            delay_count = 3600U;        
            do
            {
                delay_count--;
            } while(delay_count);
            
            // Start RESUME signaling for 1-13 ms
            USBResumeControl = 1;
            delay_count = 1800U;
            do
            {
                delay_count--;
            } while(delay_count);
            USBResumeControl = 0;

            USBUnmaskInterrupts();
        }
    }
}
示例#4
0
void CDCTxService(void)
{
    BYTE byte_to_send;
    BYTE i;
    
    USBMaskInterrupts();
    
    CDCNotificationHandler();
    
    if(USBHandleBusy(CDCDataInHandle)) 
    {
        USBUnmaskInterrupts();
        return;
    }

    /*
     * Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ].
     * By having this stage, user can always check cdc_trf_state,
     * and not having to call mCDCUsartTxIsBusy() directly.
     */
    if(cdc_trf_state == CDC_TX_COMPLETING)
        cdc_trf_state = CDC_TX_READY;
    
    /*
     * If CDC_TX_READY state, nothing to do, just return.
     */
    if(cdc_trf_state == CDC_TX_READY)
    {
        USBUnmaskInterrupts();
        return;
    }
    
    /*
     * If CDC_TX_BUSY_ZLP state, send zero length packet
     */
    if(cdc_trf_state == CDC_TX_BUSY_ZLP)
    {
        CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,NULL,0);
        //CDC_DATA_BD_IN.CNT = 0;
        cdc_trf_state = CDC_TX_COMPLETING;
    }
    else if(cdc_trf_state == CDC_TX_BUSY)
    {
        /*
         * First, have to figure out how many byte of data to send.
         */
    	if(cdc_tx_len > sizeof(cdc_data_tx))
    	    byte_to_send = sizeof(cdc_data_tx);
    	else
    	    byte_to_send = cdc_tx_len;

        /*
         * Subtract the number of bytes just about to be sent from the total.
         */
    	cdc_tx_len = cdc_tx_len - byte_to_send;
    	  
        pCDCDst.bRam = (BYTE*)&cdc_data_tx; // Set destination pointer
        
        i = byte_to_send;
        if(cdc_mem_type == USB_EP0_ROM)            // Determine type of memory source
        {
            while(i)
            {
                *pCDCDst.bRam = *pCDCSrc.bRom;
                pCDCDst.bRam++;
                pCDCSrc.bRom++;
                i--;
            }//end while(byte_to_send)
        }
        else // _RAM
        {
            while(i)
            {
                *pCDCDst.bRam = *pCDCSrc.bRam;
                pCDCDst.bRam++;
                pCDCSrc.bRam++;
                i--;
            }//end while(byte_to_send._word)
        }//end if(cdc_mem_type...)
        
        /*
         * Lastly, determine if a zero length packet state is necessary.
         * See explanation in USB Specification 2.0: Section 5.8.3
         */
        if(cdc_tx_len == 0)
        {
            if(byte_to_send == CDC_DATA_IN_EP_SIZE)
                cdc_trf_state = CDC_TX_BUSY_ZLP;
            else
                cdc_trf_state = CDC_TX_COMPLETING;
        }//end if(cdc_tx_len...)
        CDCDataInHandle = USBTxOnePacket(CDC_DATA_EP,(BYTE*)&cdc_data_tx,byte_to_send);

    }//end if(cdc_tx_sate == CDC_TX_BUSY)
    
    USBUnmaskInterrupts();
}//end CDCTxService
void USBCCIDBulkInService(void)
{
    WORD byte_to_send;
    BYTE i;

    USBMaskInterrupts();
    if(USBHandleBusy(usbCcidBulkInHandle)) 
    {
        USBUnmaskInterrupts();
        return;
    }


    if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_COMPLETING)
        usbCcidBulkInTrfState = USB_CCID_BULK_IN_READY;
    
    /*
     * If USB_CCID_BULK_IN_READY state, nothing to do, just return.
     */
    if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_READY)
    {
        USBUnmaskInterrupts();
        return;
    }
    
    /*
     * If USB_CCID_BULK_IN_BUSY_ZLP state, send zero length packet
     */
    if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_BUSY_ZLP)
    {
        usbCcidBulkInHandle = USBTxOnePacket(USB_EP_BULK_IN,NULL,0);
        usbCcidBulkInTrfState = USB_CCID_BULK_IN_COMPLETING;
    }
    else if(usbCcidBulkInTrfState == USB_CCID_BULK_IN_BUSY) 
    {
        /*
         * First, have to figure out how many byte of data to send.
         */
    	if(usbCcidBulkInLen > sizeof(usbCcidBulkInEndpoint)) 
    	    byte_to_send = sizeof(usbCcidBulkInEndpoint);
    	else
    	    byte_to_send = usbCcidBulkInLen;
            
        /*
         * Subtract the number of bytes just about to be sent from the total.
         */
    	usbCcidBulkInLen = usbCcidBulkInLen - byte_to_send;
    	  
        pCCIDDst.bRam = (BYTE*)usbCcidBulkInEndpoint; // Set destination pointer
        
        i = byte_to_send;
       
        while(i)
        {
            *pCCIDDst.bRam = *pCCIDSrc.bRam;
            pCCIDDst.bRam++;
            pCCIDSrc.bRam++;
            i--;
        }//end while(byte_to_send._word)
 
        
        /*
         * Lastly, determine if a zero length packet state is necessary.
         * See explanation in USB Specification 2.0: Section 5.8.3
         */
        if(usbCcidBulkInLen == 0)
        {
            if(byte_to_send == USB_EP_SIZE)
                usbCcidBulkInTrfState = USB_CCID_BULK_IN_BUSY_ZLP;
            else
                usbCcidBulkInTrfState = USB_CCID_BULK_IN_COMPLETING;
        }//end if(usbCcidBulkInLen...)
        usbCcidBulkInHandle = USBTxOnePacket(USB_EP_BULK_IN,(BYTE*)usbCcidBulkInEndpoint,byte_to_send);

    }//end if(cdc_tx_sate == USB_CCID_BULK_IN_BUSY)
    USBUnmaskInterrupts();
}//end USBCCIDBulkInService