📄 slave.c
字号:
case GET_CONFIG:
SL811Write(EP0A_Slave_Buf,Slave_ConfigVal); // load current configuration value
EP0A_IN_Arm(EP0A_Slave_Buf,1,1); // send 1 byte data back to host
len_req = 0;
break;
case GET_INTERFACE:
SL811Write(EP0A_Slave_Buf,Slave_IfcAlt[dReq.wIndex>>8]);// load current alternate setting
EP0A_IN_Arm(EP0A_Slave_Buf,1,1); // send 1 byte data back to host
len_req = 0;
break;
case GET_STATUS:
switch(dReq.bmRequest&0x03) // check for recipients
{
case 0x00://RECIPIENT_DEV: // load current device status
SL811Write(EP0A_Slave_Buf,(Slave_RemoteWU<<1)|BUS_POWERED);
break;
case 0x01://RECIPIENT_IFC:
SL811Write(EP0A_Slave_Buf,0); // first byte = 0
break;
case 0x02://RECIPIENT_ENP:
if((dReq.wIndex>>8) & 0x80) // for IN direction endpoint
{
if(Slave_inEPstall & (0x01<<((dReq.wIndex>>8)&0x0F)))
SL811Write(EP0A_Slave_Buf,1); // first byte = 1 (IN endpoint stall)
else
SL811Write(EP0A_Slave_Buf,0); // first byte = 0 (IN endpoint not stall)
}
else // for OUT direction endpoint
{
if(Slave_outEPstall & (0x01<<((dReq.wIndex>>8)&0x0F)))
SL811Write(EP0A_Slave_Buf,1); // first byte = 1 (OUT endpoint stall)
else
SL811Write(EP0A_Slave_Buf,0); // first byte = 0 (OUT endpoint not stall)
}
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 0x00://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(0x00,0x27); //EP0AControl Stall unsupported requests
break;
case 0x02://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
Uart_Printf("枚举完毕\n");
}
}
}
}
}
//----------------------------------------------------------------------------------------
// 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
}
//*****************************************************************************************
// EP1 interrupt service routine
//*****************************************************************************************
int ep1_isr(void)
{
SL811Write(IntStatus,0x02); // clear EP1 interrupt
if(SL811Read(EP1AStatus) & 0x01) // check for ACK bit set
ep1_toggle = (((SL811Read(EP1AControl)&DATAX)==0) ? 1:0);
// toggle DATA sequence
return;
}
//*****************************************************************************************
// SOF interrupt service routine (act as 1ms timer)
//*****************************************************************************************
int sof_isr(void)
{
SL811Write(IntStatus,0x20); // clear SOF interrupt
sof_cnt++; // track msec timing
if(sof_cnt==TIME_OUT) // reset counter on specify
{ // time out.
sof_cnt = 0;
// timeout = 1; // set timeout flag
Uart_Printf("连接超时\n");
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -