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

📄 usb_ep0.c

📁 linux2.4.20下的针对三星公司的s3c2410的usb模块驱动代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) Intrinsyc, Inc., 2002 *  Modified for 24A0A board *  usb_ep0.h * */#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/tqueue.h>#include <linux/delay.h>#include <linux/sched.h>#include <linux/slab.h>#include <asm/io.h>#include <asm/dma.h>#include <asm/irq.h>#include "s3c2440_usb.h"	/* public interface */#include "usb_ctl.h"		/* private stuff */#include "usb_ep0.h"//#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)) { \          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...)#endifunsigned int ep0_state;__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. This part includes the code for basic Enumeration*//*************************************************************************/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);static void queue_and_start_write( void * p, int req, int act );/*************************************************************************//*Inline Helpers*//**************************************************************************/inline intrequest_target(__u8 b){	return (int) (b & 0x0F);}inline intwindex_to_ep_num(__u16 w){	return (int) (w & 0x000F);}inline inttype_code_from_request(__u8 by){	return ((by >> 4) & 3);}/* print string descriptor */static inline voidpsdesc(string_desc_t * p){	int i;	int nchars = (p->bLength - 2) / sizeof (__u16);	for (i = 0; i < nchars; i++) {		//printk( "%c", (char) p->bString[i] );	}}#if VERBOSITY/* "pcs" == "print control status" */static inline voidpcs(void){	unsigned long backup;	__u32 foo;	backup = UD_INDEX;	UD_INDEX = UD_INDEX_EP0;	foo = UD_ICSR1;	UD_INDEX = backup;}static inline voidpreq(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;	}	// 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#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***************************************************************************//* 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 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;\}#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; \}#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; \}voidep0_int_hndlr(void){	usb_dev_request_t req;	int request_type, n;	__u32 cs_reg;	UD_INDEX = UD_INDEX_EP0;	cs_reg = UD_ICSR1;	pcs();	if (cs_reg & EP0_CSR_SENTSTL) {		clear_ep0_sst;		ep0_state = EP0_STATE_IDLE;		/* return; */ /* Remove to respond simultaneous interrupt. by SW Lee */	}	if (cs_reg & EP0_CSR_SE) {		clear_ep0_se;		ep0_state = EP0_STATE_IDLE;		/* return; */ /* Remove to respond simultaneous interrupt. by SW Lee */	}	switch (ep0_state) {	case EP0_STATE_IDLE:		if (cs_reg & EP0_CSR_OPKRDY) {			/* read setup request */			n = read_fifo(&req);			if (n != sizeof (req)) {				printk ("%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) {			case 0:	// standard request				standard_dev_req(req);				break;			default:	// class, vendor, resolved types#if defined(CONFIG_S3C2440_USB_CDC_ENCM) || defined(CONFIG_S3C2440_USB_CDC_ENCM_MODULE)				if (req.bRequest == CDC_ENCM_SET_ETHERNET_PACKET_FILTER) {					printk("%sCDC_ENCM_SET_ETHERNET_PACKET_FILTER\n",					       pszMe);					clear_ep0_opr;					set_ep0_ipr;				} else {					printk("%sunknown request packet:\n",					       pszMe);					printk					    ("%sbmRequestType: 0x%02x, bRequest: 0x%02x, "					     "wValue: 0x%04x, wIndex: 0x%04x, wLength: 0x%04x\n",					     pszMe, req.bmRequestType,					     req.bRequest, req.wValue,					     req.wIndex, req.wLength);//					set_ep0_ipr;//					clear_ep0_opr;				}#else				printk				    ("%ssetup begin : unsupported bmRequestType :"				     " %d ignored\n", pszMe, request_type);#endif				return;			}		}		break;	case EP0_STATE_TRANSFER:		ep0_transmit();		break;	case EP0_STATE_RECEIVER:		ep0_receive();		break;	}	pcs();}/* working shawn */static voidstandard_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);			usbd_info.address = address;			usbctl_next_state_on_event(kEvAddress);			set_ep0_de_out;			ep0_state = EP0_STATE_IDLE;			break;		case SET_DESCRIPTOR:			set_descriptor();			break;		case SET_CONFIGURATION:			set_configuration = (__u8) req.wValue;	/* low byte */#if 0			set_ep0_de_out;#endif			if (req.wValue == 1) {	/* configured */				if (usbctl_next_state_on_event(kEvConfig) !=				    kError) {					desc_t *pDesc = elfin_usb_get_descriptor_ptr();					__u32 in = __le16_to_cpu(pDesc->b.ep2.wMaxPacketSize);					__u32 out = __le16_to_cpu(pDesc->b.ep1.wMaxPacketSize);					UD_INDEX = 2;					UD_MAXP = UD_MAXP_64;					UD_INDEX = 1;					UD_MAXP = UD_MAXP_64;					printk ("%sConfigured (IN MAX PACKET=%d, OUT MAX PACKET=%d)\n",					     pszMe, in, out);				}			} else if (req.wValue == 0) {				if (usbctl_next_state_on_event(kEvDeConfig) != kError)					printk("%sDe-Configuration\n", pszMe);			} else {				printk ("%ssetup phase : Unknown [set configuration] data %d\n",

⌨️ 快捷键说明

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