📄 sl811s.c
字号:
}
break;
}
SL811Write(EP0A_Slave_Buf+1,0); // second byte = 0
EP0A_IN_Arm(EP0A_Slave_Buf,2,1); // send 2 bytes data back to host
len_req = 0; // reset request length to zero
break;
case SET_FEATURE:
case CLEAR_FEATURE:
switch(dReq.bmRequest&0x03) // check for recipients
{
case RECIPIENT_DEV:
if((dReq.wValue>>8) == 1) // feature selector = 1 (remote wakeup)
{
if(dReq.bRequest==SET_FEATURE) // set remote wake up status
Slave_RemoteWU = 1;
if(dReq.bRequest==CLEAR_FEATURE) // clear remote wake up status
Slave_RemoteWU = 0;
EP0A_IN_Arm(0,0,1); // IN status stage
}
else
SL811Write(EP0AControl,SEND_STALL); // Stall unsupported requests
break;
case RECIPIENT_ENP:
if((dReq.wValue>>8) == 0) // feature selector = 0 (endpoint stall)
{
if((dReq.wIndex>>8) & 0x80) // for IN direction endpoint
{
if(dReq.bRequest==SET_FEATURE) // set endpoint stall (limit to 7 IN's data endpoint)
Slave_inEPstall |= (0x01<<((dReq.wIndex>>8)&0x0F));
if(dReq.bRequest==CLEAR_FEATURE) // clear endpoint stall (limit to 7 IN's data endpoint)
Slave_inEPstall &= ~(0x01<<((dReq.wIndex>>8)&0x0F));
}
else // for OUT direction endpoint
{
if(dReq.bRequest==SET_FEATURE) // set endpoint stall (limit to 7 OUT's data endpoint)
Slave_outEPstall |= (0x01<<((dReq.wIndex>>8)&0x0F));
if(dReq.bRequest==CLEAR_FEATURE) // clear endpoint stall (limit to 7 OUT's data endpoint)
Slave_outEPstall &= ~(0x01<<((dReq.wIndex>>8)&0x0F));
}
EP0A_IN_Arm(0,0,1); // IN status stage
}
else
SL811Write(EP0AControl,SEND_STALL); // Stall unsupported requests
break;
default:
SL811Write(EP0AControl,SEND_STALL); // Stall all unsupported requests
break;
}
break;
case SET_ADDRESS:
Slave_USBaddr = dReq.wValue>>8; // update new USB address assigned by host
EP0A_IN_Arm(0,0,1); // IN status stage
break;
case SET_CONFIG:
Slave_ConfigVal = dReq.wValue>>8; // update configuration value
EP0A_IN_Arm(0,0,1); // IN status stage
if(Slave_ConfigVal)
SL811Write(EP1AControl,DATA0_IN_ENABLE); // Enable EP1 (reponse with NAK)
else
SL811Write(EP1AControl,DATA0_IN_DISABLE); // Disable EP1
break;
case SET_INTERFACE: // update alternate setting for
Slave_IfcAlt[dReq.wIndex>>8] = dReq.wValue>>8; // selected interface number
EP0A_IN_Arm(0,0,1); // IN status stage
break;
default:
SL811Write(EP0AControl,SEND_STALL); // Stall all unsupported requests
break;
}
break;
//---------------------------------------------------------------------
// Specific Class Requests (HID)
//---------------------------------------------------------------------
case CLASS_REQUEST:
switch (dReq.bRequest) // Parse bRequest
{
case GET_IDLE:
SL811Write(EP0A_Slave_Buf,Slave_IdleRate); // load current idle rate value
EP0A_IN_Arm(EP0A_Slave_Buf,1,1); // send 1 byte data back to host
len_req = 0;
break;
case GET_PROTOCOL:
SL811Write(EP0A_Slave_Buf,Slave_Protocol); // load current protocol state
EP0A_IN_Arm(EP0A_Slave_Buf,1,1); // send 1 byte data back to host
len_req = 0;
break;
case SET_IDLE:
Slave_IdleRate = (BYTE)dReq.wValue; // update Idle Rate (upper byte of wValue)
EP0A_IN_Arm(0,0,1); // IN status stage
break;
case SET_PROTOCOL:
Slave_Protocol = dReq.wValue>>8; // update protocol value, 0=Boot, 1=report
EP0A_IN_Arm(0,0,1); // IN status stage
break;
default:
SL811Write(EP0AControl,SEND_STALL); // Stall all unsupported requests
break;
}
break;
//---------------------------------------------------------------------
// Specific Vendor Requests
//---------------------------------------------------------------------
case VENDOR_REQUEST:
SL811Write(EP0AControl,SEND_STALL); // Stall all unsupported requests
break;
//---------------------------------------------------------------------
// Unsupported Requests
//---------------------------------------------------------------------
default:
SL811Write(EP0AControl,SEND_STALL); // Stall all unsupported requests
break;
}
}
//================================================================
// IN/OUT token received from host
//================================================================
else
{
//---------------------------------
// IN's ACKed
//---------------------------------
if(SL811Read(EP0AControl)&DIRECTION)
{
if(dev_first==0) // happens on the first get device descp
{ // the host terminate IN transfer prematurely
len_req = 0; // (if EP0 maxpktsize is only 8 bytes)
dev_first = 1; // reset len_req, end with OUT status stage
}
//--------------------------------------
// Continue with next IN if needed
//--------------------------------------
if(len_req)
{
data_seq = (((SL811Read(EP0AControl)&DATAX)==0) ? 1:0); // toggle DATA sequence
len_xfr = (len_req>=EP0_LEN) ? EP0_LEN:(BYTE)len_req; // get transfer length for EP0
if(!IN_NULL) // point to correct buffer location
EP0A_IN_Arm(EP0A_Slave_Buf+in_buffer_idx, len_xfr, data_seq);
else
EP0A_IN_Arm(0,0,data_seq); // transfer zero Null packet
in_buffer_idx += len_xfr; // update buffer location
len_req -= len_xfr; // update remaining data length
if(len_req==0 && len_xfr==EP0_LEN && !IN_EXACT) // handles null packet of data length
{ // to host is multiple of EP0_LEN, and
len_req = 1; // only if host request more than this
IN_NULL = TRUE; // value of length, otherwise, the extra
} // null pkt is not require.
}
//--------------------------------------
// Arm Status Stage OUT or new SETUP
//--------------------------------------
else // Arm status OUT or next SETUP requests
EP0A_OUT_Arm(EP0_LEN); // i.e. end of IN status stage.
}
//---------------------------------
// OUT's ACKed
//---------------------------------
else
{
if(byte_rx==0) // zero data packet received
{
EP0A_OUT_Arm(EP0_LEN); // get ready for next SETUP token
if((BYTE)dReq.wValue == HID_REPORT) // end of a report descp, indicate
{
enum_done = 1; // end of complete enumeration
OUTB &= ~ACTIVE_LED; // Turn on Active LED
}
}
}
}
}
//----------------------------------------------------------------------------------------
// End of ACK received
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
// If a STALL was sent out by device, it will still interrupt, but
// STALL bit in status register does not reflect this when in slave mode.
//----------------------------------------------------------------------------------------
else if( SL811Read(EP0AControl)&0x20 ) // check for previous stall sent
EP0A_OUT_Arm(EP0_LEN); // get ready for next SETUP token
return;
}
//*****************************************************************************************
// EP0's IN Token Arming (using Set A)
//*****************************************************************************************
void EP0A_IN_Arm(BYTE buf_adr, BYTE len, BYTE seq)
{
SL811Write(EP0AAddress,buf_adr); // ep0 address buffer start adress
SL811Write(EP0AXferLen,len); // max length of transfer allowed
if(seq)
SL811Write(EP0AControl,DATA1_IN); // armed to transmit to host, DATA1
else
SL811Write(EP0AControl,DATA0_IN); // armed to transmit to host, DATA0
}
//*****************************************************************************************
// EP0's SETUP/OUT Token Arming (using Set A)
//*****************************************************************************************
void EP0A_OUT_Arm(BYTE len)
{
SL811Write(EP0AAddress,EP0A_Slave_Buf); // ep0 address buffer start adress
SL811Write(EP0AXferLen,len); // max length of transfer allowed
SL811Write(EP0AControl,DATA0_OUT); // armed to receive from host
}
//*****************************************************************************************
// SL811S variables initialization
//*****************************************************************************************
void sl811s_init(void)
{
int i;
//----------------------------
// Application-Specific
//----------------------------
OUTB |= ACTIVE_LED; // Clear Active LED
OUTC |= PORTX_LED; // turn off all LEDs
flags = 0; // clear flag
sof_cnt = 0; // sof counter equal zero
ep1_toggle = 0; // ep1 toggle state
Audio_Keys = 0; // clear Audio Control Keys
Prev_Audio_Keys = 0;
Internet_Keys = 0; // clear Internet Control Keys
Prev_Internet_Keys = 0;
//----------------------------
// SL811S-Specific
//----------------------------
BUS_POWERED = 1; // define as a bus powered device
Slave_USBaddr = 0; // set to default USB address zero
Slave_ConfigVal = 0; // default device config value
Slave_Protocol = 0; // HID class default boot protocol
Slave_IdleRate = 0; // HID class default idle rate
Slave_RemoteWU = 0; // device remote wakeup support
Slave_inEPstall = 0; // EP0 ~ EP7's IN
Slave_outEPstall = 0; // EP0 ~ EP7's OUT
for(i=0;i<MAXIFCNUM;i++) // reset alternate setting
Slave_IfcAlt[i] = 0;
for(i=0;i<EP0_LEN;i++) // clear EP0 Buffer
SL811Write(EP0A_Slave_Buf+i,0);
for(i=0;i<EP1_LEN;i++) // clear EP1 Buffer
SL811Write(EP1A_Slave_Buf+i,0);
SL811Write(USBAddress,0x00); // usb address
SL811Write(IntEna,0x63); // enable SOF, EP0, EP1, USB Reset interrupts
SL811Write(IntStatus,0xFF); // clear all interrupts
EP0A_OUT_Arm(EP0_LEN); // ready to receive from host
}
//*****************************************************************************************
// 8051 variables initialization
//*****************************************************************************************
void uC8051_init(void)
{
ISOCTL |= 0x01; // free up iso endpoints for external data space (1024)
//----------------------------
// Variable initialization
//----------------------------
SL811H_DATA = 0x00;
SL811H_ADDR = 0x00;
//----------------------------
// 8051's I/Os Setup
//----------------------------
PORTACFG = 0x00; // Set to output
OEA = 0xFF; // Set PA7~PA0(Output)
OUTA = 0xFF; // Default output high
PORTBCFG = 0x20; // Select i/o function for PB7~PB0, except PB5-INT#5
OEB = 0xDF; // Set PB6(O),PB4(I),PB1(O),PB0(O) - PB2(0),PB3(O),PB5(I),PB7(O)
OUTB = 0xDF; // Default output high
PORTCCFG = 0xC0; // Select alternate function nWR(PC6) & nRD(PC7),
// OEC = 0x3F; // Set PC5~PC0 (Output) For LEDs only
// OUTC = 0x3F; // Default output high
OEC = 0x38; // Set PC5~PC3(Output) For LEDs, PC2~PC0 (Input) For Audio Buttons
OUTC = 0x38; // Default output high
EA = 1; // enable 8051 interrupt
EIEX5 = 1; // enable INT#5 for toggle switch
EXIF &= 0x7F; // clear INT#5 flag
//----------------------------
// SL811ST hardware reset
//----------------------------
OUTB &= ~nRESET; // reset SL811HST
EZUSB_Delay(5); // for 5ms
OUTB |= nRESET; // clear reset
// OUTB &= ~nHOST_SLAVE_MODE; // set to Host mode
OUTB |= nHOST_SLAVE_MODE; // set to Slave mode
SL811Write(IntEna,0x40); // enable USB Reset interrupt
SL811Write(CtrlReg,0x01); // enable USB, FullSpeed
SL811Write(IntStatus,0xFF); // clear all interrupts
}
//*****************************************************************************************
// Main loop start here
//*****************************************************************************************
void main(void)
{
BYTE int_status;
uC8051_init(); // initialized 8051 uC
while(TRUE) // Main Loop
{
//--------------------------------------------
// USB-Specific Tasks
//--------------------------------------------
int_status = SL811Read(IntStatus);
if(int_status & USB_RESET_DONE) // wait for USB Reset interrupt
sl811s_init();
else if(int_status & EP0_DONE) // wait for EP0 interrupt
ep0_isr();
else if(int_status & EP1_DONE) // wait for EP1 interrupt
ep1_isr();
else if(int_status & SOF_DONE) // wait for SOF interrupt
sof_isr();
//--------------------------------------------
// Application-Specific Tasks (every 5msec)
//--------------------------------------------
if(timeout && enum_done) // do some task now
{
audio_key_scan(); // Audio Keys Scan
internet_key_scan(); // Internet Keys Scan
timeout = 0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -