www.pudn.com > SL811.rar > SL811.C


#include "common.h" 
#include "SL811.H" 
#include "HAL.H" 
#include "HPI.H" 
 
sbit		SEL_OTHERS=P1^5; 
bit		SLAVE_ONLINE; 
 
 
extern bit		SLAVE_IS_ATTACHED; 
extern bit		SLAVE_REMOVED; 
extern bit		SLAVE_FOUND;		// Slave USB device found 
extern bit		SLAVE_ENUMERATED;// slave USB device enumeration done 
extern bit		TIMEOUT_ERR;		// timeout error during data endpoint transfer 
extern bit		DATA_STOP;		// device unplugged during data transfer 
extern bit		bTimer; 
extern bit		bMassDevice; 
extern bit		bData1; 
 
uchar xdata DBUF[2048]	_at_	0X1000; 
pUSBDEV  xdata	uDev;			// Multiple USB devices attributes, Max 5 devices 
xdata pDevDesc  	pDev;			// Device descriptor struct 
xdata pCfgDesc 	pCfg;			// Configuration descriptor struct 
xdata pIntfDesc 	pIfc;				// Interface descriptor struct 
xdata pEPDesc 		pEnp;			// Endpoint descriptor struct 
xdata pStrDesc 	pStr;			// String descriptor struct 
 
extern void FlashLowTo811(void); 
extern void FlashHighTo811(void); 
 
//***************************************************************************************** 
// SL811H variables initialization 
//***************************************************************************************** 
//////bit SL811_GetRev(void) 
//////{ 
//////	//SL811Write(SL811_ADDR_PORT, 0x0e); 
//////	return SL811Read(0x0e); 
//////} 
 
void USBReset(void) 
	{ 
	unsigned char temp; 
    	temp=SL811Read(CtrlReg); 
 	SL811Write(CtrlReg,temp|0x08); 
	DelayMs(25); 
    	SL811Write(CtrlReg,temp); 
	} 
bit FlashWithUsb(uint	wLen)	//将当前长度的FLASH中的数据通过USB发出,完成所有的数据传输才退出 
	{ 
	uchar 	bufLen,cmd,intr,ep_out,page; 
	uchar	j,i=0; 
	uchar *buffer=DBUF; 
	ep_out=uDev.epbulkout&0x0F; 
	cmd=DATA0_WR;					//将写命令的控制字准备好 
	if(!uDev.bData1[ep_out]) 
		cmd|=0x40; 
	SL811Write(IntStatus,INT_CLEAR); 	//清除中断标志 
	page=(uchar)(wLen>>7); 
	for(j=0;j=0x40)  		// select proper data payload	//判断实际要求传送的长度 
//		xferLen=0x40;		// limit to wPayload size	//最大不能超过负载,超过部分下次再传 
//	else					// else take < payload len 
//		xferLen=wLen; 
//	// For OUT token 
//	if(xferLen)			// only when there are,把需要加载的数据转移到811 
//		SL811BufWrite(0x10,buffer,xferLen); 	// data to transfer on USB 
//	cmd=sDATA0_WR;		//将写命令的控制字准备好 
//	bData1=uDev.bData1[ep_out];		//得到当前的切换状况 
//    	uDev.bData1[ep_out]=(!bData1); 	// DataToggle,翻转,为下次准备 
//	if(bData1) 
//    		cmd|=0x40;                      	// Set Data1 bit in command,根据状况修改命令字 
//	//------------------------------------------------ 
//	//------------------------------------------------ 
//	// Arming of USB data transfer for the first pkt,准备数据,送到SIE待传 
//	//------------------------------------------------ 
//	SL811Write(EP0Status,(ep_out|PID_OUT));	// PID + EP address 
//	SL811Write(EP0Counter,1);				// USB address 
//	SL811Write(EP0Address,0x10);			// buffer address, start with "data0",首次传送的地址,一定从DATA0开始 
//	SL811Write(EP0XferLen,xferLen);			// data transfer length,本次传送的长度 
//	SL811Write(IntStatus,INT_CLEAR); 		// clear interrupt status,清除中断 
//	SL811Write(EP0Control,cmd);				// Enable ARM and USB transfer start here,开始传送 
//	//------------------------------------------------ 
//	// Main loop for completing a wLen data trasnfer 
//	//------------------------------------------------ 
//	while(i--) 
//		{ 
//		//---------------Wait for done interrupt------------------ 
//		while(TRUE)											// always ensure requested device is 
//			{												// inserted at all time, then you will 
//			intr=SL811Read(IntStatus);			//读取中断标志 
//			if((intr&USB_RESET)||(intr&INSERT_REMOVE))			// proceed to parse result from slave 
//				{											// device.设备被重置了要退出传送并给出标志 
//				DATA_STOP=TRUE;								// if device is removed, set DATA_STOP 
//				return	FALSE;								// flag true, so that main loop will 
//				}											// know this condition and exit gracefully 
//			if(intr& USB_A_DONE)		//本次传送完毕 
//				break;										// interrupt done !!! 
//			} 
//		SL811Write(IntStatus,INT_CLEAR); 						// clear interrupt status,清除中断标志 
//		result=SL811Read(EP0Status);								// read EP0status register,得到传送结果 
//		//-------------------------ACK---------------------------- 
//		if (result&EP0_ACK)										// Transmission ACK,如果接收正确 
//			{ 
//			// OUT TOKEN 
//			wLen-=(uint)xferLen;								// update remainding wLen value,得到剩余要传字节的数量 
//			bufLen=xferLen;			//上次已经传掉的数量 
//			if(wLen)	//如果还有数据要传送 
//				{ 
//		        	bData1=uDev.bData1[ep_out]; 
//		        	uDev.bData1[ep_out]=(!bData1); 				// DataToggle,把标志切换到下一个 
//				cmd^=0x40;    							// toggle DATA0/DATA1 
//				cmd&=0xdf; 
//				addr=bData1?0x50:0x10; 					// select next address for data 
//				xferLen=(BYTE)(wLen>=0x40)?0x40:wLen;		// get data length required 
//				buffer+=bufLen; 
//				SL811BufWrite(addr,buffer,xferLen); 			// data to transfer on USB 
//				SL811Write(EP0XferLen,xferLen); 				// select next xfer length 
//				SL811Write(EP0Address,addr);           			// data buffer addr 
//				SL811Write(IntStatus,INT_CLEAR);			// is a LS is on Hub. 
//				SL811Write(EP0Control,cmd);					// Enable USB transfer and re-arm 
//				} 
//			else 
//				break; 
//			} 
//		//-------------------------NAK---------------------------- 
//		if (result & EP0_NAK)									// NAK Detected 
//			break;											// main loop control the interval polling 
//		//-----------------------TIMEOUT-------------------------- 
//		if (result&EP0_TIMEOUT)								// TIMEOUT Detected 
//			{ 
//			TIMEOUT_ERR=TRUE;								// failed, set flag to terminate transfer 
//			break;											// happens when data transfer on a device 
//			} 
//		//-----------------------STALL---------------------------- 
//		if (result&EP0_STALL)  								// STALL detected 
//			return 	TRUE;										// for unsupported request. 
//		//----------------------OVEFLOW--------------------------- 
//		if (result&EP0_OVERFLOW)  							// OVERFLOW detected 
//			break; 
//		//-----------------------ERROR---------------------------- 
//		if (result&EP0_ERROR)  								// ERROR detected 
//			break; 
//		}	// end of While(1) 
//	if (result&EP0_ACK) 	// on ACK transmission 
//		return 	TRUE;		// return OK 
//	return 	FALSE;			// fail transmission 
//	} 
 
//***************************************************************************************** 
// usbXfer: 
// successful transfer = return TRUE 
// fail transfer = return FALSE 
//***************************************************************************************** 
bit usbXfer(uchar usbaddr,uchar endpoint,uchar pid,uint wPayload,uint wLen,uchar *buffer)	//完成所有的数据传输才退出 
	{ 
	uchar	remainder; 
	uchar	i=255; 
	uchar 	xferLen,cmd,result,intr; 
	idata uchar	bufLen,data0,data1,addr,timeout; 
	bit	dataX;	//切换PINGPONG用的标志 
	//------------------------------------------------ 
	// Default setting for usb trasnfer 
	//------------------------------------------------ 
	dataX=bufLen=timeout=0;			//初始化基本参数 
	TIMEOUT_ERR=DATA_STOP=FALSE; 
	data0=EP0_Buf;				// DATA0 buffer address,设定第1缓冲首地址 
	data1=data0+(uchar)wPayload;		// DATA1 buffer address	,设定第2缓冲首地址 
	//------------------------------------------------ 
	// Define data transfer payload 
	//------------------------------------------------ 
	if (wLen>=wPayload)  		// select proper data payload	//判断实际要求传送的长度 
		xferLen=wPayload;		// limit to wPayload size	//最大不能超过负载,超过部分下次再传 
	else						// else take < payload len 
		xferLen=wLen; 
	// For IN token 
	if (pid==PID_IN)			// for current IN tokens		//当前的任务是要读取数据 
		{ 
		cmd = sDATA0_RD;		// FS/FS on Hub, sync to sof	作为新的一帧传送 
		} 
	// For OUT token 
	else if(pid==PID_OUT)				// for OUT tokens	//当前的任务是要写入数据 
		{ 
		if(xferLen)							// only when there are,把需要加载的数据转移到811 
			SL811BufWrite(data0,buffer,xferLen); 	// data to transfer on USB 
		cmd=sDATA0_WR;		//将写命令的控制字准备好 
		bData1=uDev.bData1[endpoint];	//得到当前的切换状况 
        	uDev.bData1[endpoint]=!(uDev.bData1[endpoint]); // DataToggle,翻转,为下次准备 
		if(bData1) 
          		cmd|=0x40;                            // Set Data1 bit in command,根据状况修改命令字 
		} 
	// For SETUP/OUT token 
	else									// for current SETUP/OUT tokens 
		{ 
		if(xferLen)						// only when there are 
			{ 
			SL811BufWrite(data0,buffer,xferLen);  // data to transfer on USB 
			} 
		cmd = sDATA0_WR;					// FS/FS on Hub, sync to sof 
		} 
	//------------------------------------------------ 
	// For EP0's IN/OUT token data, start with DATA1 
	// Control Endpoint0's status stage. 
	// For data endpoint, IN/OUT data, start ???? 
	//------------------------------------------------ 
	if (endpoint==0&&pid!=PID_SETUP) 	// for Ep0's IN/OUT token 
		cmd|=0x40; 					// always set DATA1 
	//------------------------------------------------ 
	// Arming of USB data transfer for the first pkt,准备数据,送到SIE待传 
	//------------------------------------------------ 
	SL811Write(EP0Status,((endpoint&0x0F)|pid));	// PID + EP address 
	SL811Write(EP0Counter,usbaddr);			// USB address 
	SL811Write(EP0Address,data0);			// buffer address, start with "data0",首次传送的地址,一定从DATA0开始 
	SL811Write(EP0XferLen,xferLen);			// data transfer length,本次传送的长度 
	SL811Write(IntStatus,INT_CLEAR); 		// clear interrupt status,清除中断 
	SL811Write(EP0Control,cmd);				// Enable ARM and USB transfer start here,开始传送 
	//------------------------------------------------ 
	// Main loop for completing a wLen data trasnfer 
	//------------------------------------------------ 
	while(i--) 
		{ 
		//---------------Wait for done interrupt------------------ 
		while(TRUE)											// always ensure requested device is 
			{												// inserted at all time, then you will 
			intr=SL811Read(IntStatus);			//读取中断标志 
			if((intr&USB_RESET)||(intr&INSERT_REMOVE))			// proceed to parse result from slave 
				{											// device.设备被重置了要退出传送并给出标志 
				DATA_STOP=TRUE;								// if device is removed, set DATA_STOP 
				return	FALSE;								// flag true, so that main loop will 
				}											// know this condition and exit gracefully 
			if(intr& USB_A_DONE)		//本次传送完毕 
				break;										// interrupt done !!! 
			} 
		SL811Write(IntStatus,INT_CLEAR); 						// clear interrupt status,清除中断标志 
		result=SL811Read(EP0Status);								// read EP0status register,得到传送结果 
		remainder=SL811Read(EP0Counter);							// remainder value in last pkt xfer,得到剩余字节的数量 
		//-------------------------ACK---------------------------- 
		if (result&EP0_ACK)										// Transmission ACK,如果接收正确 
			{ 
			// OUT TOKEN 
			if(pid==PID_OUT) 
				{ 
				wLen-=(uint)xferLen;							// update remainding wLen value,得到剩余要传字节的数量 
				bufLen=xferLen;			//上次已经传掉的数量 
				if(wLen)	//如果还有数据要传送 
					{ 
			        	bData1=uDev.bData1[endpoint]; 
			        	uDev.bData1[endpoint]=!(uDev.bData1[endpoint]); 	// DataToggle,把标志切换到下一个 
					cmd^=0x40;    							// toggle DATA0/DATA1 
					cmd&=0xdf; 
					addr=bData1?data1:data0; 					// select next address for data 
					xferLen=(BYTE)(wLen>=wPayload)?wPayload:wLen;	// get data length required 
					buffer+=bufLen; 
					SL811BufWrite(addr,buffer,xferLen); 			// data to transfer on USB 
					SL811Write(EP0XferLen,xferLen); 				// select next xfer length 
					SL811Write(EP0Address,addr);           			// data buffer addr 
					SL811Write(IntStatus,INT_CLEAR);			// is a LS is on Hub. 
					SL811Write(EP0Control,cmd);					// Enable USB transfer and re-arm 
					} 
				else 
					break; 
				} 
			else if(pid==PID_IN)			// IN TOKEN 
				{ 
				wLen-=(uint)xferLen; 
				cmd^=0x40; 
				dataX=!dataX; 
				//------------------------------------------------ 
				// If host requested for more data than the slave 
				// have, and if the slave's data len is a multiple 
				// of its endpoint payload size/last xferLen. Do 
				// not overwrite data in previous buffer. 
				//------------------------------------------------ 
				if(remainder==xferLen) // empty data detected 
					bufLen = 0; // do not overwriten previous data 
				else // reset bufLen to zero 
					bufLen = xferLen; // update previous buffer length 
				//------------------------------------------------ 
				// Arm for next data transfer when requested data 
				// length have not reach zero, i.e. wLen!=0, and 
				// last xferlen of data was completed, i.e. 
				// remainder is equal to zero, not a short pkt 
				//------------------------------------------------ 
				if(!remainder&&wLen) // remainder==0 when last xferLen 
					{ 						// was all completed or wLen!=0 
					addr=dataX?data1:data0;	// select next address for data 
					xferLen=(uchar)(wLen>=wPayload)?wPayload:wLen; // get data length required 
					//cmd |= 0x20; // always sync SOF when FS, regardless 
					cmd&=0xdf; 
					SL811Write(EP0XferLen, xferLen);  // select next xfer length 
					SL811Write(EP0Address, addr);            // data buffer addr 
					SL811Write(IntStatus,INT_CLEAR); // is a LS is on Hub. 
					SL811Write(EP0Control,cmd); // Enable USB transfer and re-arm 
					} 
				//------------------------------------------------ 
				// Copy last IN token data pkt from prev transfer 
				// Check if there was data available during the 
				// last data transfer 
				//------------------------------------------------ 
				if(bufLen) 
					{ 
					SL811BufRead((dataX?data0:data1),buffer,bufLen); 
					buffer+=bufLen; 
					} 
				//------------------------------------------------ 
				// Terminate on short packets, i.e. remainder!=0 
				// a short packet or empty data packet OR when 
				// requested data len have completed, i.e.wLen=0 
				// For a LOWSPEED device, the 1st device descp, 
				// wPayload is default to 64-byte, LS device will 
				// only send back a max of 8-byte device descp, 
				// and host detect this as a short packet, and 
				// terminate with OUT status stage 
				//------------------------------------------------ 
				if(remainder||!wLen) 
					break; 
				} 
			// SETUP TOKEN 
			else if(pid==PID_SETUP)								// do nothing for SETUP/OUT token 
				break;											// exit while(1) immediately 
			} 
		//-------------------------NAK---------------------------- 
		if (result & EP0_NAK)									// NAK Detected 
			{ 
			if(endpoint==0)										// on ep0 during enumeration of LS device 
				{													// happen when slave is not fast enough, 
				SL811Write(IntStatus,INT_CLEAR);				// clear interrupt status, need to 
				SL811Write(EP0Control,cmd);						// re-arm and request for last cmd, IN token 
                		result=0;                                     				// respond to NAK status only 
				} 
			else												// normal data endpoint, exit now !!! , non-zero ep 
				break;											// main loop control the interval polling 
			} 
		//-----------------------TIMEOUT-------------------------- 
		if (result&EP0_TIMEOUT)								// TIMEOUT Detected 
			{ 
			if(endpoint==0)										// happens when hub enumeration 
				{ 
				if(++timeout>=TIMEOUT_RETRY) 
					{ 
				    	timeout--; 
					break;										// exit on the timeout detected 
					} 
				SL811Write(IntStatus,INT_CLEAR);				// clear interrupt status, need to 
				SL811Write(EP0Control,cmd);						// re-arm and request for last cmd again 
				} 
			else 
				{													// all other data endpoint, data transfer 
				TIMEOUT_ERR=TRUE;								// failed, set flag to terminate transfer 
				break;											// happens when data transfer on a device 
				}													// through the hub 
			} 
		//-----------------------STALL---------------------------- 
		if (result&EP0_STALL)  								// STALL detected 
			return 	TRUE;										// for unsupported request. 
		//----------------------OVEFLOW--------------------------- 
		if (result&EP0_OVERFLOW)  							// OVERFLOW detected 
			break; 
		//-----------------------ERROR---------------------------- 
		if (result&EP0_ERROR)  								// ERROR detected 
			break; 
		}	// end of While(1) 
	if (result&EP0_ACK) 	// on ACK transmission 
		return 	TRUE;		// return OK 
	return 	FALSE;			// fail transmission 
	} 
//***************************************************************************************** 
// Control Endpoint 0's USB Data Xfer 
// ep0Xfer, endpoint 0 data transfer 
//***************************************************************************************** 
bit ep0Xfer(uchar usbaddr,uint payload,pSetupPKG setup,uchar *pData) 
	{ 
	idata		uchar	pid=PID_IN; 
	//uchar	ep0=0;								// always endpoint zero 
	uint		wLen=SwapINT16(setup->wLength);		// swap back for correct length 
	//---------------------------------------------------- 
	// SETUP token with 8-byte request on endpoint 0 
	//---------------------------------------------------- 
	if (!usbXfer(usbaddr,0,PID_SETUP,payload,8,(uchar	*)setup)) 
   		return FALSE; 
	//---------------------------------------------------- 
	// IN or OUT data stage on endpoint 0 
	//---------------------------------------------------- 
   	if (wLen)											// if there are data for transfer 
		{ 
		if (setup->bmRequest&0x80)		// host-to-device : IN token 
			{ 
			pid=PID_OUT; 
			if(!usbXfer(usbaddr,0,PID_IN,payload,wLen,pData)) 
				return FALSE; 
			payload=0; 
			} 
		else											// device-to-host : OUT token 
   			{ 
			if(!usbXfer(usbaddr,0,PID_OUT,payload,wLen,pData)) 
				return FALSE; 
			} 
		} 
	//---------------------------------------------------- 
	// Status stage IN or OUT zero-length data packet 
	//---------------------------------------------------- 
	if(!usbXfer(usbaddr,0,pid,payload,0,NULL)) 
		return FALSE; 
	return TRUE; 
	} 
 
bit epBulkSend(unsigned char *pBuffer,unsigned int len) 
	{ 
//	usbstack.usbaddr=0x1; 
//	usbstack.endpoint=usbstack.epbulkout; 
//	usbstack.pid=PID_OUT; 
//	usbstack.wPayload=64; 
//	usbstack.wLen=len; 
//	usbstack.buffer=pBuffer; 
//	if(usbstack.wLen) 
//	      while(!usbXfer()); 
//	return TRUE; 
 
	if(usbXfer(1,uDev.epbulkout&0x0F,PID_OUT,uDev.wPayLoad[uDev.epbulkout&0x0F],len,pBuffer))	//64 
//	if(usbXfer(1,2,PID_OUT,64,len,pBuffer))	//64 
		return TRUE; 
	return FALSE; 
	} 
 
bit epBulkRcv(unsigned char *pBuffer,unsigned int len) 
	{ 
//	usbstack.usbaddr=0x1; 
//	usbstack.endpoint=usbstack.epbulkin; 
//	usbstack.pid=PID_IN; 
//	usbstack.wPayload=64; 
//	usbstack.wLen=len; 
//	usbstack.buffer=pBuffer; 
//	while(usbstack.wLen) 
//		while(!usbXfer()); 
//	return TRUE; 
 
	if(usbXfer(1,uDev.epbulkin&0x0F,PID_IN,uDev.wPayLoad[uDev.epbulkin&0x0F],len,pBuffer))		//64 
//	if(usbXfer(1,1,PID_IN,64,len,pBuffer))	//64 
		return TRUE; 
	return FALSE; 
	} 
//***************************************************************************************** 
// Control endpoint 
//***************************************************************************************** 
bit VendorCmd(uchar usbaddr,uchar bReq,uchar bCmd,uint wValue,uint wIndex,uint wLen,uchar *pData) 
	{ 
    	xdata SetupPKG setup; 
    	setup.bmRequest=bReq; 
	setup.bRequest=bCmd; 
    	setup.wValue=wValue; 
    	setup.wIndex=wIndex; 
    	setup.wLength=SwapINT16(wLen); 
   	return 	ep0Xfer(usbaddr,uDev.wPayLoad[0], &setup,pData); 
	} 
//***************************************************************************************** 
// Set Device Address : 
//***************************************************************************************** 
//bit SetAddress(uint addr) 
//	{ 
//	return VendorCmd(0,0,SET_ADDRESS,SwapINT16(addr),0,0,NULL); 
//	} 
//***************************************************************************************** 
// Set Device Configuration : 
//***************************************************************************************** 
//bit Set_Configuration(uchar usbaddr,uint wVal) 
//	{ 
//	return VendorCmd(usbaddr,0,SET_CONFIG,SwapINT16(wVal),0,0,NULL); 
//	} 
//***************************************************************************************** 
// Get Device Descriptor : Device, Configuration, String 
//***************************************************************************************** 
//bit GetDesc(uchar usbaddr,uint wValue,uint wIndex,uint wLen,uchar *desc) 
//	{ 
//	return VendorCmd(usbaddr,0x80,GET_DESCRIPTOR,wValue,wIndex,wLen,desc); 
//	} 
//***************************************************************************************** 
// USB Data Endpoint Read/Write 
// wLen is in low byte first format 
//***************************************************************************************** 
 
//bit DataRW(uchar usbaddr,uchar epaddr,uint wPayload,uint wLen,uchar *pData) 
//	{ 
//	xdata uchar pid=PID_OUT; 
//	if(epaddr&0x80)	// get direction of transfer 
//		pid=PID_IN; 
//	if(usbXfer(usbaddr,epaddr&0x0F,pid,wPayload,wLen,pData)) 
//		return TRUE; 
//	return FALSE; 
//	} 
//***************************************************************************************** 
// USB Device Enumeration Process 
// Support 1 confguration and interface #0 and alternate setting #0 only 
// Support up to 1 control endpoint + 4 data endpoint only 
//***************************************************************************************** 
bit EnumUsbDev(uchar usbaddr) 
	{ 
	int i;											// always reset USB transfer address 
	idata		uchar 	uAddr=0;							// for enumeration to Address #0 
	idata		uchar 	epLen; 
	idata uint 	strLang; 
	//------------------------------------------------ 
	// Reset only Slave device attached directly 
	//------------------------------------------------ 
	uDev.wPayLoad[0]=64;	// default 64-byte payload of Endpoint 0, address #0 
	if(usbaddr==1)			// bus reset for the device attached to SL811HS only 
		USBReset();		// that will always have the USB address = 0x01 (for a hub) 
    	DelayMs(25); 
 
	pDev =(pDevDesc)DBUF;					// ask for 64 bytes on Addr #0 
//	if (!GetDesc(uAddr,DEVICE,0,18,DBUF))		// and determine the wPayload size 
	if(!VendorCmd(uAddr,0x80,GET_DESCRIPTOR,DEVICE,0,18,DBUF)) 
		return FALSE;								// get correct wPayload of Endpoint 0 
	uDev.wPayLoad[0]=pDev->bMaxPacketSize0;// on current non-zero USB address 
	//------------------------------------------------ 
	// Set Slave USB Device Address 
	//------------------------------------------------ 
	if(!VendorCmd(0,0,SET_ADDRESS,SwapINT16((uint)usbaddr),0,0,NULL)) 
//	if (!SetAddress(usbaddr)) 						// set to specific USB address 
		return FALSE;								// 
	uAddr=usbaddr;								// transfer using this new address 
 
	//------------------------------------------------ 
	// Get USB Device Descriptors on EP0 & Addr X 
	//------------------------------------------------ 
//	if (!GetDesc(uAddr,DEVICE,0,(pDev->bLength),DBUF)) 
	if (!VendorCmd(uAddr,0x80,GET_DESCRIPTOR,DEVICE,0,(pDev->bLength),DBUF)) 
		return FALSE;						// For this current device: 
	uDev.wVID=pDev->idVendor;		// save VID 
	uDev.wPID=pDev->idProduct;		// save PID 
	uDev.iMfg=pDev->iManufacturer;	// save Mfg Index 
	uDev.iPdt=pDev->iProduct;			// save Product Index 
	//------------------------------------------------ 
	// Get String Descriptors 
	//------------------------------------------------ 
	pStr=(pStrDesc)DBUF; 
	if(VendorCmd(uAddr,0x80,GET_DESCRIPTOR,STRING,0,4,DBUF)) 
		{ 
		strLang=pStr->wLang;							// get iManufacturer String length 
		if(!VendorCmd(uAddr,0x80,GET_DESCRIPTOR,(uint)(uDev.iMfg<<8)|STRING,strLang,4,DBUF)) 
			return FALSE;								// get iManufacturer String descriptors 
		if(!VendorCmd(uAddr,0x80,GET_DESCRIPTOR,(uint)(uDev.iMfg<<8)|STRING,strLang,pStr->bLength,DBUF)) 
			return FALSE; 
		} 
	//------------------------------------------------ 
	// Get Slave USB Configuration Descriptors 
	//------------------------------------------------ 
	pCfg=(pCfgDesc)DBUF; 
//	if(!GetDesc(uAddr,CONFIGURATION,0,8,DBUF)) 
	if(!VendorCmd(uAddr,0x80,GET_DESCRIPTOR,CONFIGURATION,0,8,DBUF)) 
		return FALSE; 
//	if(!GetDesc(uAddr,CONFIGURATION,0,SwapINT16(pCfg->wLength),DBUF)) 
	if(!VendorCmd(uAddr,0x80,GET_DESCRIPTOR,CONFIGURATION,0,SwapINT16(pCfg->wLength),DBUF)) 
		return FALSE; 
 
	pIfc=(pIntfDesc)(DBUF+9);				// point to Interface Descp 
	uDev.bClass=pIfc->iClass;			// update to class type 
	uDev.bNumOfEPs=(pIfc->bEndPoints<=MAX_EP)?pIfc->bEndPoints:MAX_EP; 
 
	if(uDev.bClass==8) //mass storage device 
		bMassDevice=TRUE; 
	//------------------------------------------------ 
	// Set configuration (except for HUB device) 
	//------------------------------------------------ 
	if (uDev.bClass!=HUBCLASS)				// enumerating a FS/LS non-hub device 
		{ 
		if(!VendorCmd(uAddr,0,SET_CONFIG,SwapINT16(DEVICE),0,0,NULL)) 
//		if (!Set_Configuration(uAddr,DEVICE))			// connected directly to SL811HS 
				return FALSE; 
		} 
	//------------------------------------------------ 
	// For each slave endpoints, get its attributes 
	// Excluding endpoint0, only data endpoints 
	//------------------------------------------------ 
	epLen = 0; 
	for (i=1;i<=uDev.bNumOfEPs;i++)			// For each data endpoint 
		{ 
		pEnp=(pEPDesc)(DBUF+9+9+epLen);	   			// point to Endpoint Descp(non-HID) 
		uDev.bEPAddr[i]=pEnp->bEPAdd;			// Ep address and direction 
		uDev.bAttr[i]=pEnp->bAttr;			// Attribute of Endpoint 
		uDev.wPayLoad[i]=SwapINT16(pEnp->wPayLoad);		// Payload of Endpoint 
		uDev.bInterval[i]=pEnp->bInterval;		// Polling interval 
	    	uDev.bData1[i]=0;			            // init data toggle 
		epLen+=7; 
		if(uDev.bAttr[i]==0x2) 
			{ 
		    	if(uDev.bEPAddr[i]&0x80) 
		    		uDev.epbulkin=uDev.bEPAddr[i]; 
		    	else 
		    		uDev.epbulkout=uDev.bEPAddr[i]; 
			} 
		} 
	return TRUE; 
	} 
 
/////////////////////////////////////////////////////////////////////////////////////////// 
void SL811_Init(void) 
	{ 
	SLAVE_IS_ATTACHED=SLAVE_ENUMERATED=SLAVE_REMOVED=SLAVE_FOUND=SLAVE_ONLINE=FALSE; 
	SEL_OTHERS=1; 
	/////////////////////////////////////////////////////// 
	SL811Write(cDATASet,0xe0); 
	SL811Write(cSOFcnt,0xae); 
	SL811Write(CtrlReg,0x5);		//自动产生SOF 
 
	SL811Write(EP0Status,0x50); 
	SL811Write(EP0Counter,0); 
	SL811Write(EP0Control,0x01); 
 
	SL811Write(IntEna,0x20);      		// USB-A, Insert/Remove, USB_Resume. 
	SL811Write(IntStatus,INT_CLEAR);	// Clear Interrupt enable status 
	} 
void check_key_LED(void) 
	{ 
	uchar intr; 
	intr=SL811Read(IntStatus); 
	if(intr&USB_RESET) 
		{ 
		if(SLAVE_ONLINE==TRUE) 
			{ 
			SLAVE_REMOVED=TRUE; 
		   	SLAVE_ONLINE=FALSE; 
		   	} 
		} 
	else	 
		{ 
		if(SLAVE_ONLINE==FALSE) 
			SLAVE_ONLINE=SLAVE_FOUND=TRUE; 
		} 
	SL811Write(IntStatus,INT_CLEAR); 
	SL811Write(IntStatus,INSERT_REMOVE); 
	}