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

📄 usb_ep0_pxa.c

📁 LUBBOCK板的BLOB
💻 C
📖 第 1 页 / 共 2 页
字号:
			//SerialOutputString("GET_DESCRIPTOR\n");
			get_descriptor( &req );
			break;

		case SET_INTERFACE:
			//SerialOutputString("SET_INTERFACE\n");
			//PRINTKD( "%sSET_INTERFACE TODO...\n", pszMe);
			break;

		case SET_DESCRIPTOR:
			//SerialOutputString("SET_DESCRIPTOR\n");
			//PRINTKD( "%sSET_DESCRIPTOR TODO...\n", pszMe );
			break;

		case SET_CONFIGURATION:
			//SerialOutputString("SET_CONFIGURATION\n");
			//PRINTKD( "%sSET_CONFIGURATION %d\n", pszMe, req.wValue);

/*
 * FIXME: Something is not quite right here... I only ever get a 
 * de-configure from the host. Ignoring it for now, since usb
 * ethernet won't do anything unless usb is 'configured'.
 *
 */
#if 0
			switch( req.wValue)
			{
				case 0:
					/* configured */
					usbctl_next_state_on_event( kEvConfig );
					break;
				case 1:
					/* de-configured */
					usbctl_next_state_on_event( kEvDeConfig );
					break;
				default:
					PRINTKD( "%sSET_CONFIGURATION: unknown configuration value (%d)\n", pszMe, req.wValue);
					break;
			}
#endif
			break;
		default :
			//printk("%sunknown request 0x%x\n", pszMe, req.bRequest);
			break;
	} /* switch( bRequest ) */

sh_sb_end:
	return;
}

/*
 * sh_write()
 * 
 * Due to UDC bugs we push everything into the fifo in one go.
 * Using interrupts just didn't work right...
 * This should be ok, since control request are small.
 */
static void sh_write()
{
	//PRINTKD( "sh_write\n" );
	do
	{
	    write_fifo();
	} while( ep0_state != EP0_END_XFER);
}

/***************************************************************************
  Other Private Subroutines
 ***************************************************************************/
/*
 * queue_and_start_write()
 * data == data to send
 * req == bytes host requested
 * act == bytes we actually have
 *
 * Sets up the global "wr"-ite structure and load the outbound FIFO 
 * with data.
 *
 */
static void queue_and_start_write( void * data, int req, int act )
{
	//PRINTKD( "write start: bytes requested=%d actual=%d\n", req, act);

	wr.p = (unsigned char*) data;
	wr.bytes_left = MIN( act, req );

	ep0_state = EP0_IN_DATA_PHASE;
	sh_write();

	return;
}
/*
 * write_fifo()
 * Stick bytes in the endpoint zero FIFO.
 *
 */
static void write_fifo( void )
{
	int bytes_this_time = MIN( wr.bytes_left, EP0_FIFO_SIZE );
	int bytes_written = 0;
	//SerialOutputString("in write_fifo\n");

	while( bytes_this_time-- ) {
//		PRINTKD( "%2.2X ", *wr.p );
		UDDR0 = *wr.p++;
		bytes_written++;
	}
	wr.bytes_left -= bytes_written;

	usbd_info.stats.ep0_bytes_written += bytes_written;

	if( (wr.bytes_left==0))
	{
		wr.p = 0;  				/* be anal */

 		if(bytes_written < EP0_FIFO_SIZE)
		{
			int count;
			int udccs0;

			/* We always end the transfer with a short or zero length packet */
			ep0_state = EP0_END_XFER;
			current_handler = sh_setup_begin;

			/* Let the packet go... */
			UDCCS0 = UDCCS0_IPR;

			/* Wait until we get to status-stage, then ack.
			 *
			 * When the UDC sets the UDCCS0[OPR] bit, an interrupt
			 * is supposed to be generated (see 12.5.1 step 14ff, PXA Dev Manual).   
			 * That approach didn't work out. Usually a new SETUP command was
			 * already in the fifo. I tried many approaches but was always losing 
			 * at least some OPR interrupts. Thus the polling below...
			 */
			count = 1000;
			udccs0 = UDCCS0;
			do
			{
				if( (UDCCS0 & UDCCS0_OPR)) 
				{
					/* clear OPR, generate ack */
					UDCCS0 = UDCCS0_OPR;
					break;
				}
				count--;	
				msleep(1);
				//udelay(1);
			} while( count);

			PRINTKD( "write fifo: count=%d UDCCS0=%x UDCCS0=%x\n", count, udccs0, UDCCS0);
		}
	}
	/* something goes poopy if I dont wait here ... */
	msleep(1);
	//udelay(500);

	//PRINTKD( "write fifo: bytes sent=%d, bytes left=%d\n", bytes_written, wr.bytes_left);
}

/*
 * read_fifo()
 * Read bytes out of FIFO and put in request.
 * Called to do the initial read of setup requests
 * from the host. Return number of bytes read.
 *
 */
static int read_fifo( usb_dev_request_t * request )
{
	int bytes_read = 0;
	unsigned char * pOut = (unsigned char*) request;

	int udccs0 = UDCCS0;

	if( (udccs0 & SETUP_READY) == SETUP_READY)
	{
		/* ok it's a setup command */
		while( UDCCS0 & UDCCS0_RNE)
		{
			if( bytes_read >= sizeof( usb_dev_request_t))
			{
				/* We've already read enought o fill usb_dev_request_t.
				 * Our tummy is full. Go barf... 
				 */
				//printk( "%sread_fifo(): read failure\n", pszMe );
				usbd_info.stats.ep0_fifo_read_failures++;
				break;
			}

			*pOut++ = UDDR0;
			bytes_read++;
		}
	}
	//PRINTKD( "read_fifo %d bytes\n", bytes_read );

	/* clear SA & OPR */
	UDCCS0 = SETUP_READY;

	usbd_info.stats.ep0_bytes_read += bytes_read;
	return bytes_read;
}

/*
 * get_descriptor()
 * Called from sh_setup_begin to handle data return
 * for a GET_DESCRIPTOR setup request.
 *
 * +-----+------------------------------------------------+-----------------+
 * | dev | cfg1 | intf 1 | ep 1..N | intf 2 | ep 1..N |...| cfg2 .......... |
 * +-----+------------------------------------------------+-----------------+
 */
static void get_descriptor( usb_dev_request_t * pReq )
{
	string_desc_t * pString;
	ep_desc_t * pEndpoint = 0;
	config_desc_t *pcfg = 0;

	desc_t * pDesc = pxa_usb_get_descriptor_ptr();
	int type = pReq->wValue >> 8;
	int idx  = pReq->wValue & 0xFF;

//	PRINTKD( "%sget_descriptor for %d\n", pszMe, type );
	switch( type ) {
		case USB_DESC_DEVICE:
			/* return device descritpor */
			queue_and_start_write( &pDesc->dev,
					pReq->wLength,
					pDesc->dev.bLength );
			break;

			// return config descriptor buffer, cfg, intf 1..N,  ep 1..N
		case USB_DESC_CONFIG:
			{
				int i,len;
				config_desc_t *cfg =(config_desc_t*) (pDesc->cdb);

				len=0;
				for( i=0; i<pDesc->dev.bNumConfigurations; i++) {
					len += __le16_to_cpu(cfg->wTotalLength);
					cfg = (config_desc_t*) ( (unsigned char*) cfg 
							+ __le16_to_cpu(cfg->wTotalLength)) ;
				}
					
				queue_and_start_write( pDesc->cdb,
						pReq->wLength,
						len);
			}
			break;

			// not quite right, since doesn't do language code checking
		case USB_DESC_STRING:
			pString = pxa_usb_get_string_descriptor( idx );
			if ( pString ) {
				if ( idx != 0 ) {  // if not language index
					//printk( "%sReturn string %d: ", pszMe, idx );
					psdesc( pString );
				}
				queue_and_start_write( pString,
						pReq->wLength,
						pString->bLength );
			}
			else {
				//printk("%sunkown string index %d Stall.\n", pszMe, idx );
			}
			break;

			/*
		case USB_DESC_INTERFACE:
			for( i = 0; i < pDesc->intf_num; i++) {
				if ( idx == pDesc->intf[i].bInterfaceNumber ) {
					queue_and_start_write( &pDesc->intf[i],
							pReq->wLength,
							pDesc->intf[i].bLength );
				}
			}
			break;

		case USB_DESC_ENDPOINT: 
			for( i = 0; i < pDesc->ep_num; i++) {
				if ( idx == (0x0F & pDesc->ep[i].bEndpointAddress)) {
					queue_and_start_write( &pDesc->ep[i],
							pReq->wLength,
							pDesc->ep[i].bLength );
				}
			}
			break;
			*/

		default :
			//printk("%sunknown descriptor type %d. Stall.\n", pszMe, type );
			break;

	}
}

/* end usb_ep0.c - who needs this comment? */

⌨️ 快捷键说明

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