📄 usb_ep0_pxa.c
字号:
/*
* 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 + -