📄 usb_ep0.c
字号:
/* * * usb_ep0.c - S3C24x0 USB controller driver. * Endpoint zero management * * Seungbum Lim <shawn@mizi.com> */#include <common.h>#include <s3c2440.h>#include <s3c24x0_usb.h> /* public interface */#include "usb_ctl.h" /* private stuff *///#define VERBOSITY 1enum { false = 0, true = 1 };#ifndef MIN#define MIN( a, b ) ((a)<(b)?(a):(b))#endif#if 1 && !defined( ASSERT )# define ASSERT(expr) \ if(!(expr)) { \ printf( "Assertion failed! %s,%s,%s,line=%d\n",\ #expr,__FILE__,__FUNCTION__,__LINE__); \ }#else# define ASSERT(expr)#endif#if VERBOSITY#define PRINTKD(fmt, args...) printf( fmt , ## args)#else#define PRINTKD(fmt, args...)#endifunsigned int ep0_state; // sec like, shawn__u8 set_configuration;__u8 set_interface;__u8 device_status;__u8 ep0_status;__u8 ep_bulk_in_status;__u8 ep_bulk_out_status;unsigned int control_complete;/*================================================ * USB Protocol Stuff *//* Request Codes, standard request spec 1.1 */enum { GET_STATUS=0, CLEAR_FEATURE=1, SET_FEATURE=3, SET_ADDRESS=5, GET_DESCRIPTOR=6, SET_DESCRIPTOR=7, GET_CONFIGURATION=8, SET_CONFIGURATION=9, GET_INTERFACE=10, SET_INTERFACE=11 };/* USB Device Requests */typedef struct{ __u8 bmRequestType; __u8 bRequest; __u16 wValue; __u16 wIndex; __u16 wLength;} usb_dev_request_t __attribute__ ((packed));static int read_fifo( usb_dev_request_t * p );static void standard_dev_req(usb_dev_request_t req);static void set_feature(usb_dev_request_t req);static void clear_feature(usb_dev_request_t req);static void set_descriptor(void);static void get_descriptor(usb_dev_request_t req);static void ep0_transmit(void);static void ep0_receive(void);/***************************************************************************Inline Helpers***************************************************************************//* Data extraction from usb_request_t fields */enum { kTargetDevice=0, kTargetInterface=1, kTargetEndpoint=2 };static inline int request_target( __u8 b ) { return (int) ( b & 0x0F); }/* Standard Feature Selectors, shawn */enum { fEndpoint_Halt = 0, fDevice_Remote_Wakeup = 1 };static inline int windex_to_ep_num( __u16 w ) { return (int) ( w & 0x000F); }inline int type_code_from_request( __u8 by ) { return (( by >> 4 ) & 3); } // ? [5,6] , shawn/* print string descriptor */static inline void psdesc( string_desc_t * p ){ int i; int nchars = ( p->bLength - 2 ) / sizeof( __u16 ); // printf( "'" ); for( i = 0 ; i < nchars ; i++ ) { // printf( "%c", (char) p->bString[i] ); } // printf( "'\n" );}#if VERBOSITY/* "pcs" == "print control status" */static inline void pcs( void ){ unsigned long backup; __u32 foo ; backup = UD_INDEX; UD_INDEX = UD_INDEX_EP0; foo = UD_ICSR1; //printf( "%8.8X\n", foo); UD_INDEX = backup;}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; default: psz = "unknown"; break; } // printf( "- [%s: %s req to %s. dir=%s]\n", psz, // rnames[ (pReq->bmRequestType >> 5) & 3 ], // tnames[ pReq->bmRequestType & 3 ], // ( pReq->bmRequestType & 0x80 ) ? "in" : "out" );}#else#define pcs() (void)(0)#define preq(x) (void)(0)#endif/***************************************************************************Globals***************************************************************************/static const char pszMe[] = "usbep0: ";/* global write struct to keep write ..state around across interrupts */static struct { unsigned char *p; int bytes_left; unsigned int transfer_length; unsigned int transfered_data;} wr;/***************************************************************************Public Interface***************************************************************************/#define NULL 0/* reset received from HUB (or controller just went nuts and reset by itself!) so udc core has been reset, track this state here */voidep0_reset(void){ /* reset state machine */ wr.p = NULL; wr.bytes_left = 0; wr.transfer_length = 0; wr.transfered_data = 0; usbd_info.address = 0; control_complete = 0;}/* handle interrupt for endpoint zero */#define EP0_STATE_IDLE 0#define EP0_STATE_TRANSFER 1#define EP0_STATE_RECEIVER 2#define clear_ep0_sst { \ UD_INDEX = UD_INDEX_EP0; \ UD_ICSR1 = 0x00; /*EP0_CSR_SENTSTL*/ \}#define clear_ep0_se { \ __u32 reg;\ UD_INDEX = UD_INDEX_EP0; \ reg=UD_ICSR1;\ reg=( reg & ~0xC0) | EP0_CSR_SSE; \ UD_ICSR1 = reg;\}#define clear_ep0_opr { \ __u32 reg;\ UD_INDEX = UD_INDEX_EP0; \ reg=UD_ICSR1;\ reg=( reg & ~0xC0) | EP0_CSR_SOPKTRDY; \ UD_ICSR1=reg;\}#define set_ep0_ipr { \ __u32 reg;\ UD_INDEX = UD_INDEX_EP0; \ reg=UD_ICSR1;\ reg= ( reg & ~0xC0) | EP0_CSR_IPKRDY; \ UD_ICSR1=reg;\}#define set_ep0_de { \ __u32 reg;\ UD_INDEX = UD_INDEX_EP0; \ reg = UD_ICSR1\ reg = EP0_CSR_DE; \ UD_ICSR1= reg;\}#define set_ep0_ss { \ __u32 reg;\ UD_INDEX = UD_INDEX_EP0; \ reg = UD_ICSR1;\ reg = EP0_CSR_SENDSTL; \ UD_ICSR1 = reg;\}#define set_ep0_de_out { \ __u32 reg;\ UD_INDEX = UD_INDEX_EP0; \ reg= UD_ICSR1;\ reg = ( reg & ~0xC0) | (EP0_CSR_SOPKTRDY | EP0_CSR_DE); \ UD_ICSR1 = reg;\}#define set_ep0_de_in { \ __u32 reg;\ UD_INDEX = UD_INDEX_EP0; \ reg = UD_ICSR1;\ reg = ( reg & ~0xC0) |(EP0_CSR_IPKRDY | EP0_CSR_DE); \ UD_ICSR1=reg;\}#if 1#define clear_stall_ep4_out { \ __u32 reg; \ UD_INDEX = UD_INDEX_EP4; \ reg = UD_OCSR1; \ UD_OCSR1 = reg; \}#define clear_stall_ep3_out { \ __u32 reg; \ UD_INDEX = UD_INDEX_EP3; \ reg = UD_OCSR1; \ UD_OCSR1 = reg; \}#endif#define clear_stall_ep1_out { \ __u32 reg; \ UD_INDEX = UD_INDEX_EP1; \ reg = UD_OCSR1; \ UD_OCSR1 = reg; \}#define clear_stall_ep2_out { \ __u32 reg; \ UD_INDEX = UD_INDEX_EP2; \ reg = UD_OCSR1; \ UD_OCSR1 = reg; \}void ep0_int_hndlr( void ){ usb_dev_request_t req; int request_type, n ; __u32 cs_reg; UD_INDEX = UD_INDEX_EP0; cs_reg = UD_ICSR1; PRINTKD( "/\\(%d)\n", UD_FUNC ); pcs(); if( cs_reg & EP0_CSR_SENTSTL) { PRINTKD( "EP0_CSR_SENTSTL\n" ); clear_ep0_sst; ep0_state = EP0_STATE_IDLE; //return; //?? !! } if( cs_reg & EP0_CSR_SE) { PRINTKD( "EP0_CSR_SE\n" ); clear_ep0_se; ep0_state = EP0_STATE_IDLE; // return; //?? !! } switch(ep0_state) { case EP0_STATE_IDLE : if(cs_reg & EP0_CSR_OPKRDY) { /* read setup request */ n = read_fifo(&req); if ( n != sizeof(req)) { printf("%ssettup begin : fifo READ ERROR wanted %d bytes got %d. Stalling out...\n", pszMe, sizeof(req), n); set_ep0_ss; return; }#if VERBOSITY { 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 request_type = type_code_from_request(req.bmRequestType); switch( request_type){/* Only Support Standard Request, shawn */ case 0: // standard request standard_dev_req(req); break; default: // class, vendor, resolved types printf("%ssetup begin : unsupported bmRequestType :" " %d ignored\n", pszMe, request_type); return; } } break; case EP0_STATE_TRANSFER : ep0_transmit(); break; case EP0_STATE_RECEIVER : printf(" EP0_STATE_RECEIVER \n"); ep0_receive(); break; } PRINTKD( "---\n" ); pcs(); PRINTKD( "\\/\n\n" );}/* working shawn */static void standard_dev_req(usb_dev_request_t req){ __u32 address; int n, e; n = request_target(req.bmRequestType); switch( n ) { /* device recipient */ case kTargetDevice : switch(req.bRequest) { case SET_FEATURE : set_feature(req); /* work?, shawn */ break; case CLEAR_FEATURE : clear_feature(req); /* work? shawn */ break; case SET_ADDRESS : address = (__u32)(req.wValue & 0x7F); UD_FUNC = (address | 0x80);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -