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

📄 usb_ep0_pxa.c

📁 LUBBOCK板的BLOB
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  Copyright (C) Extenex Corporation 2001
 *  Copyright (C) Compaq Computer Corporation, 1998, 1999
 *  Copyright (C) Intrinsyc, Inc., 2002
 *
 *  PXA USB controller driver - Endpoint zero management
 *
 *  Please see:
 *    linux/Documentation/arm/SA1100/SA1100_USB 
 *  for more info.
 *
 *  02-May-2002
 *   Frank Becker (Intrinsyc) - derived from sa1100 usb_ctl.c
 * 
 */

#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif

#include <blob/arch.h>
#include <blob/types.h>
#include <blob/serial.h>

#include "linux/errno.h"
#include "pxa_usb.h"  /* public interface */
#include "usb_ctl_pxa.h"  /* private stuff */
#include "usb_ep0_pxa.h"


// 1 == lots of trace noise,  0 = only "important' stuff
#define VERBOSITY 0

enum { true = 1, false = 0 };
typedef int bool;
#ifndef MIN
#define MIN( a, b ) ((a)<(b)?(a):(b))
#endif

#if 1 && !defined( ASSERT )
#  define ASSERT(expr) \
if(!(expr)) { \
	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
#expr,__FILE__,__FUNCTION__,__LINE__); \
}
#else
#  define ASSERT(expr)
#endif

#if VERBOSITY
#define PRINTKD(fmt, args...) printk( fmt , ## args)
#else
#define PRINTKD(fmt, args...)
#endif


static EP0_state ep0_state = EP0_IDLE;

static int current_cfg_index = 0;
/***************************************************************************
  Prototypes
 ***************************************************************************/
/* "setup handlers" -- the main functions dispatched to by the
   .. isr. These represent the major "modes" of endpoint 0 operation */
static void sh_setup_begin(void);				/* setup begin (idle) */
static void sh_write( void );      				/* writing data */
static int  read_fifo( usb_dev_request_t * p );
static void write_fifo( void );
static void get_descriptor( usb_dev_request_t * pReq );
static void queue_and_start_write( void * p, int req, int act );

/***************************************************************************
  Inline Helpers
 ***************************************************************************/

inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); }

/* print string descriptor */
static inline void psdesc( string_desc_t * p )
{
	int i;
	int nchars = ( p->bLength - 2 ) / sizeof( __u16 );
	//printk( "'" );
	for( i = 0 ; i < nchars ; i++ ) {
		//printk( "%c", (char) p->bString[i] );
	}
	//printk( "'\n" );
}

#if VERBOSITY
/* "pcs" == "print control status" */
static inline void pcs( void )
{
	__u32 foo = UDCCS0;
	/*
	printk( "%08x: %s %s %s %s %s %s\n",
			foo,
			foo & UDCCS0_SA   ? "SA" : "",
			foo & UDCCS0_OPR  ? "OPR" : "",
			foo & UDCCS0_RNE  ? "RNE" : "",
			foo & UDCCS0_SST  ? "SST" : "",
			foo & UDCCS0_FST  ? "FST" : "",
			foo & UDCCS0_DRWF ? "DRWF" : ""
	      );
*/
}
static inline void preq( usb_dev_request_t * pReq )
{
	static char * tnames[] = { "dev", "intf", "ep", "oth" };
	static char * rnames[] = { "std", "class", "vendor", "???" };
	char * psz;
	switch( pReq->bRequest ) {
		case GET_STATUS:        psz = "get stat"; break;
		case CLEAR_FEATURE:     psz = "clr feat"; break;
		case SET_FEATURE:       psz = "set feat"; break;
		case SET_ADDRESS:       psz = "set addr"; break;
		case GET_DESCRIPTOR:    psz = "get desc"; break;
		case SET_DESCRIPTOR:    psz = "set desc"; break;
		case GET_CONFIGURATION: psz = "get cfg"; break;
		case SET_CONFIGURATION: psz = "set cfg"; break;
		case GET_INTERFACE:     psz = "get intf"; break;
		case SET_INTERFACE:     psz = "set intf"; break;
		case SYNCH_FRAME:       psz = "synch frame"; break;
		default:                psz = "unknown"; break;
	}
	/* printk( "- [%s: %s req to %s. dir=%s]\n", psz,
			rnames[ (pReq->bmRequestType >> 5) & 3 ],
			tnames[ pReq->bmRequestType & 3 ],
			( pReq->bmRequestType & 0x80 ) ? "in" : "out" );
	*/
}

#else
static inline void pcs( void ){}
static inline void preq( usb_dev_request_t *x){}
#endif

/***************************************************************************
  Globals
 ***************************************************************************/
static const char pszMe[] = "usbep0: ";

/* pointer to current setup handler */
static void (*current_handler)(void) = sh_setup_begin;

/* global write struct to keep write
   ..state around across interrupts */
static struct {
	unsigned char *p;
	int bytes_left;
} wr;

/***************************************************************************
  Public Interface
 ***************************************************************************/

/* reset received from HUB (or controller just went nuts and reset by itself!)
   so udc core has been reset, track this state here  */
void ep0_reset(void)
{
	//PRINTKD( "%sep0_reset\n", pszMe);
	/* reset state machine */
	current_handler = sh_setup_begin;
	wr.p = 0;
	wr.bytes_left = 0;
	usbd_info.address=0;
}

/* handle interrupt for endpoint zero */
void ep0_int_hndlr( void )
{
	//PRINTKD( "%sep0_int_hndlr\n", pszMe);
	pcs();
	(*current_handler)();
}

/***************************************************************************
  Setup Handlers
 ***************************************************************************/
/*
 * sh_setup_begin()
 * This setup handler is the "idle" state of endpoint zero. It looks for OPR
 * (OUT packet ready) to see if a setup request has been been received from the
 * host. 
 *
 */
static void sh_setup_begin( void )
{
	usb_dev_request_t req;
	int request_type;
	int n;
	__u32 cs_reg_in = UDCCS0;

	//PRINTKD( "%ssh_setup_begin\n", pszMe);
	//SerialOutputString("in sh_setup_begin\n");

	/* Be sure out packet ready, otherwise something is wrong */
	if ( (cs_reg_in & UDCCS0_OPR) == 0 ) {
		/* we can get here early...if so, we'll int again in a moment  */
		//PRINTKD( "%ssetup begin: no OUT packet available. Exiting\n", pszMe );
		SerialOutputString("setup begin: no OUT packet avaible. Exting\n");	
		goto sh_sb_end;
	}

	if( ((cs_reg_in & UDCCS0_SA) == 0) && (ep0_state == EP0_IN_DATA_PHASE))
	{
		//PRINTKD( "%ssetup begin: premature status\n", pszMe );

		SerialOutputString(" premature status\n");

		/* premature status, reset tx fifo and go back to idle state*/
		UDCCS0 = UDCCS0_OPR | UDCCS0_FTF;

		ep0_state = EP0_IDLE;
		return;
	}

	if( (UDCCS0 & UDCCS0_RNE) == 0)
	{
		/* zero-length OUT? */
		//printk( "%ssetup begin: zero-length OUT?\n", pszMe );
		SerialOutputString(" zero-length OUT\n");
		goto sh_sb_end;
	}

	/* read the setup request */
	n = read_fifo( &req );
	if ( n != sizeof( req ) ) {
		/*
		printk( "%ssetup begin: fifo READ ERROR wanted %d bytes got %d. "
				" Stalling out...\n",
				pszMe, sizeof( req ), n );
		*/
		//SerialOutputString("req != request\n");
		/* force stall, serviced out */
		UDCCS0 = UDCCS0_FST;
		goto sh_sb_end;
	}

	/* Is it a standard request? (not vendor or class request) */
	request_type = type_code_from_request( req.bmRequestType );
	if ( request_type != 0 ) {
		/*
		printk( "%ssetup begin: unsupported bmRequestType: %d ignored\n",
				pszMe, request_type );
		*/
		SerialOutputString("unsupported bmRequestType\n");
		goto sh_sb_end;
	}


#if 0
	{
		unsigned char * pdb = (unsigned char *) &req;
		PRINTKD( "%2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X ",
				pdb[0], pdb[1], pdb[2], pdb[3], pdb[4], pdb[5], pdb[6], pdb[7]
		       );
		preq( &req );
	}
#endif

	/* Handle it */
	switch( req.bRequest ) {

		case SET_ADDRESS:
			//PRINTKD( "%sSET_ADDRESS handled by UDC\n", pszMe);
			SerialOutputString("SET_ADDRESS\n");
			break;
#if 0 /* NOT_NEEDED */

		case SET_FEATURE:
			PRINTKD( "%sSET_FEATURE handled by UDC\n", pszMe);
			break;

		case CLEAR_FEATURE:
			PRINTKD( "%sCLEAR_FEATURE handled by UDC\n", pszMe);
			break;

		case GET_CONFIGURATION:
			PRINTKD( "%sGET_CONFIGURATION handled by UDC\n", pszMe );
			break;

		case GET_STATUS:
			PRINTKD( "%s%sGET_STATUS handled by UDC\n", pszMe );
			break;

		case GET_INTERFACE:
			PRINTKD( "%sGET_INTERFACE handled by UDC\n", pszMe);
			break;

		case SYNCH_FRAME:
			PRINTKD( "%sSYNCH_FRAME handled by UDC\n", pszMe );
			break;
#endif

		case GET_DESCRIPTOR:
			//PRINTKD( "%sGET_DESCRIPTOR\n", pszMe );

⌨️ 快捷键说明

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