⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usbsample.c

📁 Real working webserver on SAM7-EX256
💻 C
📖 第 1 页 / 共 3 页
字号:
	'f', 0x00,
	'a', 0x00,
	'c', 0x00,
	'e', 0x00,
	' ', 0x00,
	'N', 0x00,
	'a', 0x00,
	'm', 0x00,
	'e', 0x00
};

/* Enumeration descriptors. */
const portCHAR pxReportDescriptor[] =
{
	0x05, 0x01,						/* USAGE_PAGE (Generic Desktop)			*/
	0x09, 0x02,						/* USAGE (Mouse)						*/
	0xa1, 0x01,						/* COLLECTION (Application)				*/
	0x09, 0x01,						/*   USAGE (Pointer)					*/
	0xa1, 0x00,						/*   COLLECTION (Physical)				*/
	0x95, 0x03,						/*     REPORT_COUNT (3)					*/
	0x75, 0x01,						/*     REPORT_SIZE (1)					*/
	0x05, 0x09,						/*     USAGE_PAGE (Button)				*/
	0x19, 0x01,						/*     USAGE_MINIMUM (Button 1)			*/
	0x29, 0x03,						/*     USAGE_MAXIMUM (Button 3)			*/
	0x15, 0x00,						/*     LOGICAL_MINIMUM (0)				*/
	0x25, 0x01,						/*     LOGICAL_MAXIMUM (1)				*/
	0x81, 0x02,						/*     INPUT (Data,Var,Abs)				*/
	0x95, 0x01,						/*     REPORT_COUNT (1)					*/
	0x75, 0x05,						/*     REPORT_SIZE (5)					*/
	0x81, 0x01,						/*     INPUT (Cnst,Ary,Abs)				*/
	0x75, 0x08,						/*     REPORT_SIZE (8)					*/
	0x95, 0x02,						/*     REPORT_COUNT (2)					*/
	0x05, 0x01,						/*     USAGE_PAGE (Generic Desktop)		*/
	0x09, 0x30,						/*     USAGE (X)						*/
	0x09, 0x31,						/*     USAGE (Y)						*/
	0x15, 0x81,						/*     LOGICAL_MINIMUM (-127)			*/
	0x25, 0x7f,						/*     LOGICAL_MAXIMUM (127)			*/
	0x81, 0x06,						/*     INPUT (Data,Var,Rel)				*/
	0xc0,							/*   END_COLLECTION						*/
	0xc0							/* END_COLLECTION						*/
};



const char pxDeviceDescriptor[] = 
{
	/* Device descriptor */
	0x12,								/* bLength				*/
	0x01,								/* bDescriptorType		*/
	0x10, 0x01,							/* bcdUSBL				*/
	usbDEVICE_CLASS_VENDOR_SPECIFIC,	/* bDeviceClass:		*/
	0x00,								/* bDeviceSubclass:		*/
	0x00,								/* bDeviceProtocol:		*/
	0x08,								/* bMaxPacketSize0		*/
	0xFF, 0xFF,							/* idVendorL			*/
	0x02, 0x00,							/* idProductL			*/
	0x00, 0x01,							/* bcdDeviceL			*/
	usbMANUFACTURER_STRING,				/* iManufacturer		*/
	usbPRODUCT_STRING,					/* iProduct				*/
	0x00,								/* SerialNumber			*/
	0x01								/* bNumConfigs			*/
};


const char pxConfigDescriptor[] = {
	/* Configuration 1 descriptor */
	0x09,			/* CbLength									*/
	0x02,			/* CbDescriptorType							*/
	0x22, 0x00,		/* CwTotalLength 2 EP + Control				*/
	0x01,			/* CbNumInterfaces							*/
	0x01,			/* CbConfigurationValue						*/
	usbCONFIGURATION_STRING,/* CiConfiguration					*/
	usbBUS_POWERED,	/* CbmAttributes Bus powered + Remote Wakeup*/
	0x32,			/* CMaxPower: 100mA							*/

	/* Mouse Interface Descriptor Requirement */
	0x09,			/* bLength									*/
	0x04,			/* bDescriptorType							*/
	0x00,			/* bInterfaceNumber							*/
	0x00,			/* bAlternateSetting						*/
	0x01,			/* bNumEndpoints							*/
	0x03,			/* bInterfaceClass: HID code				*/
	0x01,			/* bInterfaceSubclass boot					*/
	0x02,			/* bInterfaceProtocol mouse boot			*/
	usbINTERFACE_STRING,/* iInterface							*/

	/* HID Descriptor */
	0x09,			/* bLength									*/
	0x21,			/* bDescriptor type: HID Descriptor Type	*/
	0x00, 0x01,		/* bcdHID									*/
	0x00,			/* bCountryCode								*/
	0x01,			/* bNumDescriptors							*/
	usbHID_REPORT_DESCRIPTOR,	  /* bDescriptorType			*/
	sizeof( pxReportDescriptor ), 0x00, /* wItemLength			*/

	/* Endpoint 1 descriptor */
	0x07,			/* bLength									*/
	0x05,			/* bDescriptorType							*/
	0x81,			/* bEndpointAddress, Endpoint 01 - IN		*/
	0x03,			/* bmAttributes      INT					*/
	0x08, 0x00,		/* wMaxPacketSize: 8?						*/
	0x0A			/* bInterval								*/
};

/*-----------------------------------------------------------*/

/* File scope state variables. */
static unsigned portCHAR ucUSBConfig = ( unsigned portCHAR ) 0;
static unsigned portLONG ulReceivedAddress = ( unsigned portLONG ) 0;
static eDRIVER_STATE eDriverState = eNOTHING;

/* Structure used to control the characters being sent to the host. */
static xTX_MESSAGE pxCharsForTx;

/* Queue used to pass messages between the ISR and the task. */
xQueueHandle xUSBInterruptQueue; 

/*-----------------------------------------------------------*/

void vStartUSBTask( unsigned portBASE_TYPE uxPriority )
{
	/* Create the queue used to communicate between the USB ISR and task. */
	xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );

	/* Create the task itself. */
	xTaskCreate( vUSBDemoTask, "USB", configMINIMAL_STACK_SIZE, NULL, uxPriority, NULL );
}
/*-----------------------------------------------------------*/

static void vUSBDemoTask( void *pvParameters )
{
xISRStatus *pxMessage;

	/* The parameters are not used in this task. */
	( void ) pvParameters;

    /* Init USB device */
    portENTER_CRITICAL();
	    vInitUSBInterface();
    portEXIT_CRITICAL();

	/* Process interrupts as they arrive.   The ISR takes a snapshot of the 
	interrupt status then posts the information on this queue for processing
	at the task level.  This simple demo implementation only processes
	a few interrupt sources. */
	for( ;; )
	{
		if( xQueueReceive( xUSBInterruptQueue, &pxMessage, usbSHORT_DELAY ) )
		{
			if( pxMessage->ulISR & AT91C_UDP_EPINT0 )
			{
				/* Process end point 0 interrupt. */
				prvProcessEndPoint0Interrupt( pxMessage );
			}

			if( pxMessage->ulISR & AT91C_UDP_ENDBUSRES )
			{
				/* Process an end of bus reset interrupt. */
				prvResetEndPoints();		
			}
		}
		else
		{
			/* The ISR did not post any data for us to process on the queue, so
			just generate and send some sample data. */
			if( eDriverState == eREADY_TO_SEND )
			{
				prvTransmitSampleValues();
			}
		}
	}
}
/*-----------------------------------------------------------*/

static void prvControlCursorSpeed( signed portCHAR *cVal, unsigned portLONG ulInput, unsigned portLONG ulSwitch1, unsigned portLONG ulSwitch2 )
{
const portCHAR cSpeed = 20;

	if( !( ulInput & ulSwitch1 ) )
	{
		/* We are going in the decreasing y direction. */
		if( *cVal > 0 )
		{
			/* We have changed direction since last time so start from
			0 again. */
			*cVal = 0;
		}
		
		if( *cVal > -cSpeed )
		{
			/* Ramp y down to the max speed. */
			(*cVal)--;
		}
	}
	else if( !( ulInput & ulSwitch2 ) )
	{
		/* We are going in the increasing y direction. */
		if( *cVal < 0 )
		{
			/* We have changed direction since last time, so start from
			0 again. */
			*cVal = 0;
		}
		
		if( *cVal < cSpeed )
		{
			/* Ramp y up to the max speed again. */
			(*cVal)++;
		}
	}
	else
	{
		*cVal = 0;
	}
}
/*-----------------------------------------------------------*/

static void prvTransmitSampleValues( void )
{
/* Variables to hold dummy x, y and z joystick axis data. */
static signed portCHAR x = 0, y = 0, z = 0;
unsigned portLONG ulStatus;

	ulStatus = 	AT91C_BASE_PIOA->PIO_PDSR;

	prvControlCursorSpeed( &y, ulStatus, ( unsigned long ) usbSW1, ( unsigned long ) usbSW2 );
	prvControlCursorSpeed( &x, ulStatus, ( unsigned long ) usbSW3, ( unsigned long ) usbSW4 );
	
	/* Just make the z axis go up and down. */
	z = ( ( ulStatus & usbSW_CLICK ) == 0 );

	/* Can we place data in the fifo? */
	if( !( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] & AT91C_UDP_TXPKTRDY ) )
	{
		/* Write our sample data to the fifo. */
		AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = z;
		AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = x;
		AT91C_BASE_UDP->UDP_FDR[ usbEND_POINT_1 ] = y;
		
		/* Send the data. */
		portENTER_CRITICAL();
		{
			ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];
			usbCSR_SET_BIT( &ulStatus, ( AT91C_UDP_TXPKTRDY ) );
			AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulStatus;
		}
		portEXIT_CRITICAL();
	}
}
/*-----------------------------------------------------------*/

static void prvUSBTransmitNull( void )
{
unsigned portLONG ulStatus;

	/* Wait until the FIFO is free - even though we are not going to use it.
	THERE IS NO TIMEOUT HERE! */
	while( AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] & AT91C_UDP_TXPKTRDY )
	{
		vTaskDelay( usbSHORTEST_DELAY );
	}

	portENTER_CRITICAL();
	{
		/* Set the length of data to send to equal the index of the next byte
		to send.  This will prevent the ACK to this NULL packet causing any
		further data transmissions. */
		pxCharsForTx.ulTotalDataLength = pxCharsForTx.ulNextCharIndex;

		/* Set the TXPKTRDY bit to cause a transmission with no data. */
		ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
		usbCSR_SET_BIT( &ulStatus, ( AT91C_UDP_TXPKTRDY ) );
		AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
	}
	portEXIT_CRITICAL();
}
/*-----------------------------------------------------------*/

static void prvSendStall( void )
{
unsigned portLONG ulStatus;

	portENTER_CRITICAL();
	{
		/* Force a stall by simply setting the FORCESTALL bit in the CSR. */
		ulStatus = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
		usbCSR_SET_BIT( &ulStatus, AT91C_UDP_FORCESTALL );
		AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulStatus;
	}
	portEXIT_CRITICAL();
}
/*-----------------------------------------------------------*/

static void prvResetEndPoints( void )
{
unsigned portLONG ulTemp;

	eDriverState = eJUST_RESET;

	/* Reset all the end points. */
	AT91C_BASE_UDP->UDP_RSTEP  = usbEND_POINT_RESET_MASK;
	AT91C_BASE_UDP->UDP_RSTEP  = ( unsigned portLONG ) 0x00;

	/* Enable data to be sent and received. */
	AT91C_BASE_UDP->UDP_FADDR = AT91C_UDP_FEN;

	/* Repair the configuration end point. */
	portENTER_CRITICAL();
	{
		ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ];
		usbCSR_SET_BIT( &ulTemp, ( ( unsigned portLONG ) ( AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL ) ) );
		AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_0 ] = ulTemp;
		AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT0;
	}
	portEXIT_CRITICAL();
}
/*-----------------------------------------------------------*/

static void prvProcessEndPoint0Interrupt( xISRStatus *pxMessage )
{
	if( pxMessage->ulCSR0 & AT91C_UDP_RX_DATA_BK0 )
	{		
		/* We only expect to receive zero length data here as ACK's. 
		Set the data pointer to the end of the current Tx packet to
		ensure we don't send out any more data. */	
		pxCharsForTx.ulNextCharIndex = pxCharsForTx.ulTotalDataLength;
	}

	if( pxMessage->ulCSR0 & AT91C_UDP_TXCOMP )
	{
		/* We received a TX complete interrupt.  What we do depends on
		what we sent to get this interrupt. */

		if( eDriverState == eJUST_GOT_CONFIG )
		{
			/* We sent an acknowledgement of a SET_CONFIG request.  We
			are now at the end of the enumeration. */
			AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_CONFG;

			/* Read the end point for data transfer. */
			portENTER_CRITICAL();
			{
				unsigned portLONG ulTemp;

				ulTemp = AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ];					
				usbCSR_SET_BIT( &ulTemp, AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN );
				AT91C_BASE_UDP->UDP_CSR[ usbEND_POINT_1 ] = ulTemp;		
				AT91C_BASE_UDP->UDP_IER = AT91C_UDP_EPINT1;
			}
			portEXIT_CRITICAL();

			eDriverState = eREADY_TO_SEND;
		}		
		else if( eDriverState == eJUST_GOT_ADDRESS )
		{
			/* We sent an acknowledgement of a SET_ADDRESS request.  Move
			to the addressed state. */
			if( ulReceivedAddress != ( unsigned portLONG ) 0 )
			{			
				AT91C_BASE_UDP->UDP_GLBSTATE = AT91C_UDP_FADDEN;
			}
			else
			{
				AT91C_BASE_UDP->UDP_GLBSTATE = 0;
			}			

			AT91C_BASE_UDP->UDP_FADDR = ( AT91C_UDP_FEN | ulReceivedAddress );		
			eDriverState = eNOTHING;
		}
		else
		{		
			/* The TXCOMP was not for any special type of transmission.  See
			if there is any more data to send. */
			prvSendNextSegment();
		}
	}

	if( pxMessage->ulCSR0 & AT91C_UDP_RXSETUP )
	{
		xUSB_REQUEST xRequest;
		unsigned portCHAR ucRequest;
		unsigned portLONG ulRxBytes;

		/* A data packet is available. */	
		ulRxBytes = pxMessage->ulCSR0 >> 16;
		ulRxBytes &= usbRX_COUNT_MASK;

		if( ulRxBytes >= usbEXPECTED_NUMBER_OF_BYTES )
		{
			/* Create an xUSB_REQUEST variable from the raw bytes array. */

			xRequest.ucReqType = pxMessage->ucFifoData[ usbREQUEST_TYPE_INDEX ];
			xRequest.ucRequest = pxMessage->ucFifoData[ usbREQUEST_INDEX ];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -