📄 usbstd.c
字号:
/***************************************************************************
* C Source File: USBStd.C
*
* Copyright 2001 DeVaSys
* All rights are reserved.
* No part of this document may be reproduced, stored, or transmitted in any
* form or by any means without the prior written permission of DeVaSys
*
* Description:
*
* This module provides support for handling standard USB requests.
*
* ........................ Revision History ................................
*
* Creation date: 02/22/2001 - Michael A. DeVault, DeVaSys
*
* Revision History Summary:
*
* Rev 1.0 22 February 2001 12:00:00 mad
* Initial revision.
*
***************************************************************************/
#include "usbstd.h"
#include "usbdesc.h"
#include "usbrpt.h"
#include "usbd11.h"
#include "i2c.h"
#include <stdio.h>
#define USB_UNUSED_IRQ_MASK 0xF37F
#define USB_HID_REQUEST_GET_REPORT 0x01
#define USB_HID_REQUEST_GET_IDLE 0x02
#define USB_HID_REQUEST_GET_PROTOCOL 0x03
#define USB_HID_REQUEST_SET_REPORT 0x09
#define USB_HID_REQUEST_SET_IDLE 0x0A
#define USB_HID_REQUEST_SET_PROTOCOL 0x0B
BYTE CtlDataRdBuf[8];
BYTE byUsbAddress = 0x00;
BYTE byUsbConfig = 0x00;
BYTE byUsbInterface = 0x00;
BYTE byUsbAltInterface = 0x00;
BOOL bProtocol = 0x01;
BYTE byTxCtl = 0;
BYTE byTxCtlCnt = 0;
BYTE * pbyTxCtl;
BOOL bRxCtl = 0;
BYTE byRxCtlCnt = 0;
BYTE * pbyRxCtl;
// local functions
void USB_ProcIrq(WORD wIrq);
void USB_CtlRxSetup(void);
void USB_CtlRxData(void);
void USB_CtlTx(WORD byReqCnt, WORD wActCnt);
// request handler functons
void StdDevReqHdlr(PUSB_REQUEST pSetupPkt);
void StdIntReqHdlr(PUSB_REQUEST pSetupPkt);
void StdEndReqHdlr(PUSB_REQUEST pSetupPkt);
void ClsIntReqHdlr(PUSB_REQUEST pSetupPkt);
void UsbUnspReqHdlr(PUSB_REQUEST pSetupPkt);
void StdDev_GetStatus(void);
void StdDev_GetDescr(PUSB_REQUEST pSetupPkt);
void StdDev_SetAddress(PUSB_REQUEST pSetupPkt);
void StdDev_SetConfig(PUSB_REQUEST pSetupPkt);
void StdInt_GetStatus(void);
void StdInt_GetDescr(PUSB_REQUEST pSetupPkt);
void StdInt_GetInt(PUSB_REQUEST pSetupPkt);
void StdInt_SetInterface(PUSB_REQUEST pSetupPkt);
void StdEnd_GetStatus(PUSB_REQUEST pSetupPkt);
void StdEnd_ClrFeature(PUSB_REQUEST pSetupPkt);
void StdEnd_SetFeature(PUSB_REQUEST pSetupPkt);
void ClsInt_GetReport(PUSB_REQUEST pSetupPkt);
void ClsInt_GetIdle(PUSB_REQUEST pSetupPkt);
void ClsInt_GetProtocol(void);
void ClsInt_SetReport(PUSB_REQUEST pSetupPkt);
void ClsInt_SetIdle(PUSB_REQUEST pSetupPkt);
void USB_Init(void) {
// zero variables
byTxCtl = 0;
byTxCtlCnt = 0;
byUsbAddress = 0x80;
byUsbConfig = 0x00;
byUsbInterface = 0x00;
byUsbAltInterface = 0x00;
D11_CfgInit();
D11_WrEp(D11_EP1IN_IDX, (BYTE*)&RptMouse, sizeof(RptMouse)); // write report
}
void USB_Clear(void) {
D11_CfgClr();
}
BYTE USB_ChkIrq(void) {
WORD wIrq;
BYTE byRetVal = 0;
WaitForInterrupt();
wIrq = D11_GetIrq();
while(wIrq) { /* Keep reading and processing IRQs in queue */
printf("\n wIrq = 0x%04x ",wIrq); /* until all have been processed */
USB_ProcIrq(wIrq);
wIrq = D11_GetIrq();
byRetVal++;
}
return byRetVal;
}
void USB_ProcIrq(WORD wIrq) {
BYTE byLtStat;
if(wIrq & D11_INT_BUSRESET) {
/* Bus Reset Occured - Highest Priority */
printf(" A bus reset occured - Reinitalising PDIUSBD11\n\n");
USB_Init();
}
else {
if(wIrq & D11_INT_EP0OUT) {
printf(" Irq - Ep0_Out (EpIdx2)");
/* Endpoint Zero - Check if packet is Setup or Data */
byLtStat = D11_GetLtStat(D11_EP0OUT_IDX);
if(byLtStat & D11_LTSTAT_SETUP) USB_CtlRxSetup();
else USB_CtlRxData();
}
if(wIrq & D11_INT_EP0IN) {
// Ep0 In
printf(" Irq - Ep0_In (EpIdx3)");
if(byTxCtl==2) { /* Interrupt Set Address */
D11_CmdDataI2C(D11_CMD_SET_ADDRESS, &byUsbAddress, 1, WR_DATA);
byLtStat = D11_GetLtStat(D11_EP0IN_IDX);
printf(" Set Device Address %x", byUsbAddress);
byTxCtl = 0;
}
else if(byTxCtl) {
byLtStat = D11_GetLtStat(D11_EP0IN_IDX);
if(byTxCtlCnt >= 8) {
printf(" %d Sending packet of 8 bytes p=0x%X",byTxCtlCnt, pbyTxCtl);
// Tx Next 8 bytes
D11_WrEp(D11_EP0IN_IDX, pbyTxCtl, 8);
pbyTxCtl+=8;
byTxCtlCnt-=8;
}
else if(byTxCtlCnt == 0) {
// Tx Null Termination packet
printf(" Sending Null Termination Packet ");
D11_TxNull(D11_EP0IN_IDX);
byTxCtl = 0;
}
else {
// Tx byTxCnt bytes (less than 8, more than 0)
printf(" Sending last %d bytes at p=0x%x",byTxCtlCnt, pbyTxCtl);
D11_WrEp(D11_EP0IN_IDX, pbyTxCtl, byTxCtlCnt);
byTxCtl = 0;
}
}
else {
// end of transmission, status cycle
byLtStat = D11_GetLtStat(D11_EP0IN_IDX);
printf(" End of Transmission, Getting Status Byte %x",byLtStat);
}
}
if(wIrq & USB_UNUSED_IRQ_MASK) {
// activity on unused endpoint, clear irq
if(wIrq & D11_INT_EP1IN) {
// Ep1 In
printf(" Irq - Ep1_In (EpIdx4)");
D11_CmdDataI2C(D11_CMD_GET_LTSTAT+D11_EP1IN_IDX,
&byLtStat, 1, RD_DATA);
bLastReportRead = 1; // hid report last read
}
if(wIrq & D11_INT_EP1OUT) {
// Ep1 Out
printf(" Irq - Ep1_Out (EpIdx5)");
D11_CmdDataI2C(D11_CMD_GET_LTSTAT+D11_EP1OUT_IDX,
&byLtStat, 1, RD_DATA);
}
if(wIrq & D11_INT_EP2IN) {
// Ep2 In
printf(" Irq - Ep2_In (EpIdx7)");
D11_CmdDataI2C(D11_CMD_GET_LTSTAT+D11_EP2IN_IDX,
&byLtStat, 1, RD_DATA);
}
if(wIrq & D11_INT_EP2OUT) {
// Ep2 Out
printf(" Irq - Ep2_Out (EpIdx6)");
D11_CmdDataI2C(D11_CMD_GET_LTSTAT+D11_EP2OUT_IDX,
&byLtStat, 1, RD_DATA);
}
if(wIrq & D11_INT_EP3IN) {
// Ep3 In
printf(" Irq - Ep3_In (EpIdx9)");
D11_CmdDataI2C(D11_CMD_GET_LTSTAT+D11_EP3IN_IDX,
&byLtStat, 1, RD_DATA);
}
if(wIrq & D11_INT_EP3OUT) {
// Ep3 Out
printf(" Irq - Ep3_Out (EpIdx8)");
D11_CmdDataI2C(D11_CMD_GET_LTSTAT+D11_EP3OUT_IDX,
&byLtStat, 1, RD_DATA);
}
}
}
}
void USB_CtlRxSetup(void) {
// Processes a received setup packet
USB_REQUEST SetupPkt;
BYTE bySelector;
// abort any control transfers on receipt of setup packet
byTxCtl = 0;
byTxCtlCnt = 0;
bRxCtl = 0;
byRxCtlCnt = 0;
// transfer the 8 byte Setup packet from the Control OUT endpoint to memory
D11_RdEp((BYTE*)&SetupPkt, D11_EP0OUT_IDX);
D11_AckSetup(); // special ACK required for setup
#ifdef __BIGENDIAN__
SetupPkt.wValue = SWAPWORD(SetupPkt.wValue);
SetupPkt.wIndex = SWAPWORD(SetupPkt.wIndex);
SetupPkt.wLength = SWAPWORD(SetupPkt.wLength);
#endif
// x00x xxXX valid Standard request type and recepients
// x01x xx01 valid Class request type and recepient for HID class
// x10x xxuu valid Vendor request type and recepient
//
// we can use certain bits of the bmRequestType to construct a nice
// selector value for processing the request
bySelector = ( (SetupPkt.byReqType & 0x60) >>3 );
bySelector |= ( SetupPkt.byReqType & 0x03);
// analyze request using fast selector
// good compilers will turn this into a jump table
switch(bySelector) {
case 0x00:
// Standard Device request
StdDevReqHdlr(&SetupPkt);
break;
case 0x01:
// Standard Interface request
StdIntReqHdlr(&SetupPkt);
break;
case 0x02:
// Standard Endpoint request
StdEndReqHdlr(&SetupPkt);
break;
case 0x03:
// Standard Other or Reserved requests (unsupported)
// fall through on purpose
case 0x04:
// Class Device request (unsupported)
UsbUnspReqHdlr(&SetupPkt);
break;
case 0x05:
// Class Interface request
ClsIntReqHdlr(&SetupPkt);
break;
default:
UsbUnspReqHdlr(&SetupPkt);
// Class endpoint or other request
// or Vendor requests
// or Reserved requests (unsupported)
}
}
void StdDevReqHdlr(PUSB_REQUEST pSetupPkt) {
// Standard Device request
printf(" Standard Device request - ");
// call correct handler using jumptable and 4 bit selector
// determine request
switch(pSetupPkt->byRequest) {
case USB_REQUEST_GET_STATUS:
printf("Get Status ");
StdDev_GetStatus();
break;
case USB_REQUEST_GET_DESCRIPTOR:
printf("Get Descriptor ");
StdDev_GetDescr(pSetupPkt);
break;
case USB_REQUEST_GET_CONFIGURATION:
printf("Get Configuration ");
D11_WrEp(D11_EP0IN_IDX, &byUsbConfig, 1);
break;
/* case USB_REQUEST_CLEAR_FEATURE:
DbgWrStr("Clear Feature\n",1);
StdDev_ClrFeature(pSetupPkt);
break; */
case USB_REQUEST_SET_FEATURE:
printf("Set Feature ");
D11_TxNull(D11_EP0IN_IDX); // Send TxNull Packet
break;
case USB_REQUEST_SET_ADDRESS:
printf("Set Address ");
byUsbAddress = (LOBYTE(pSetupPkt->wValue) | 0x80);
byTxCtl = 2; // setup to set address next interrupt
D11_TxNull(D11_EP0IN_IDX); // Send TxNull Packet
break;
// case USB_REQUEST_SET_DESCRIPTOR:
// DbgWrStr("Set Descriptor\n",1);
// StdDev_SetDescr(pSetupPkt);
// break;
case USB_REQUEST_SET_CONFIGURATION:
printf("Set Configuration ");
StdDev_SetConfig(pSetupPkt);
break;
default:
// Unsupported Request
UsbUnspReqHdlr(pSetupPkt);
break;
}
}
void StdIntReqHdlr(PUSB_REQUEST pSetupPkt) {
// Standard Interface request
printf(" Standard Interface request - ");
switch(pSetupPkt->byRequest) {
case USB_REQUEST_GET_STATUS:
printf("Get Status ");
StdInt_GetStatus();
break;
case USB_REQUEST_GET_DESCRIPTOR:
printf("Get Descriptor ");
StdInt_GetDescr(pSetupPkt);
break;
case USB_REQUEST_GET_INTERFACE:
printf("Get Interface ");
StdInt_GetInt(pSetupPkt);
break;
// case USB_REQUEST_CLEAR_FEATURE:
// DbgWrStr("Clear Feature\n",1);
// StdInt_ClrFeature(pSetupPkt);
// break;
case USB_REQUEST_SET_FEATURE:
printf("Set Feature ");
D11_TxNull(D11_EP0IN_IDX); // TxNull Packet
break;
case USB_REQUEST_SET_INTERFACE:
printf("Set Interface ");
StdInt_SetInterface(pSetupPkt);
break;
default:
// Unsupported Request
printf("Unsupported Request %X ",pSetupPkt->byRequest);
UsbUnspReqHdlr(pSetupPkt);
break;
}
}
void StdEndReqHdlr(PUSB_REQUEST pSetupPkt) {
printf(" Standard Endpoint request - ");
switch(pSetupPkt->byRequest) {
case USB_REQUEST_GET_STATUS:
printf("Status ");
StdEnd_GetStatus(pSetupPkt);
break;
// case USB_REQUEST_SYNC_FRAME:
// DbgWrStr("Sync Frame\n",1);
// StdEnd_SyncFrame(pSetupPkt);
// break;
case USB_REQUEST_CLEAR_FEATURE:
printf("Clear Feature ");
StdEnd_ClrFeature(pSetupPkt);
break;
case USB_REQUEST_SET_FEATURE:
printf("Set Feature ");
StdEnd_SetFeature(pSetupPkt);
break;
default:
// Unsupported Request
UsbUnspReqHdlr(pSetupPkt);
break;
}
}
void ClsIntReqHdlr(PUSB_REQUEST pSetupPkt) {
printf(" Class Interface request - ");
switch(pSetupPkt->byRequest) {
case USB_HID_REQUEST_GET_REPORT:
printf("Report ");
ClsInt_GetReport(pSetupPkt);
break;
case USB_HID_REQUEST_GET_IDLE:
printf("Idle ");
ClsInt_GetIdle(pSetupPkt);
break;
case USB_HID_REQUEST_GET_PROTOCOL:
printf("Protocol ");
ClsInt_GetProtocol();
break;
case USB_HID_REQUEST_SET_REPORT:
printf("Report ");
ClsInt_SetReport(pSetupPkt);
break;
case USB_HID_REQUEST_SET_IDLE:
printf("Idle ");
ClsInt_SetIdle(pSetupPkt);
break;
case USB_HID_REQUEST_SET_PROTOCOL:
printf("Protocol ");
bProtocol = (BOOL)LOBYTE(pSetupPkt->wValue);
D11_TxNull(D11_EP0IN_IDX); // TxNull Packet
break;
default:
// Unsupported Request
UsbUnspReqHdlr(pSetupPkt);
break;
}
}
void UsbUnspReqHdlr(PUSB_REQUEST pSetupPkt) {
// unsupported request handler
}
void StdDev_SetConfig(PUSB_REQUEST pSetupPkt) {
printf(" Setup - Set Standard Device Configuration %x ",pSetupPkt->wValue);
// in configured state value must be a valid configuration #
if( LOBYTE(pSetupPkt->wValue) ) {
// set current configuration
byUsbConfig = LOBYTE(pSetupPkt->wValue);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -