#include "include.h"
#include "bsp_ch374.h"
const u8 SetupGetDevDescr[] = {0x80,0x06,0x00,0x01,0x00,0x00,0x12,0x00};/* 獲取設(shè)備描述符 */
constu8 SetupGetCfgDescr[] = {0x80,0x06,0x00,0x02,0x00,0x00,0x04,0x00};/* 獲取配置描述符 */
constu8 SetupSetUsbAddr[] = {0x00,0x05,0x02,0x00,0x00,0x00,0x00,0x00};/* 設(shè)置USB地址 */
const u8 SetupSetUsbConfig[] = {0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00};/* 設(shè)置USB配置 */
u8 SetupSetidle[]={0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00}; /* SET IDLE */
u8 SetupGetHidDes[]={0x81,0x06,0x00,0x22,0x00,0x00,0x81,0x00};/* 獲取HID 報(bào)告描述符 */
u8 SetupSetReport[]={0x21,0x09,0x00,0x02,0x00,0x00,0x01,0x00};/* SET REPORT */ ?
u8 endp_out_addr;//輸出地址(端口)
u8 endp_in_addr;//輸入地址(端口)
u8 endp_in_addr;// in 端點(diǎn)地址?
u8 ReadDataFlag;//讀取數(shù)據(jù)的同步標(biāo)志
u8 hid_des_leng;// HID類(lèi)報(bào)告描述符的長(zhǎng)度
u8 FlagDeviceStatus;// 當(dāng)前USB設(shè)備狀態(tài),通常用于中斷方式的全局變量,本程序中未使用?
u8 UsbDevEndpSize = DEFAULT_ENDP0_SIZE;
/**
? *@Name:SetHostLeisure
*@Describe:設(shè)定USB主機(jī)空閑
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
void SetHostLeisure(void)
{
//CH374_WRITE_REGISTER( REG_USB_SETUP, M_SET_USB_BUS_FREE( Read374Byte( REG_USB_SETUP ) ) ); ? ?// USB總線空閑
CH374_WRITE_REGISTER( REG_USB_SETUP, BIT_SETP_HOST_MODE| BIT_SETP_AUTO_SOF ); ? ? ? ? ? ? ? ? // USB總線復(fù)位
}
/**
? *@Name:SetHostUsbAddr
*@Describe:設(shè)置USB主機(jī)當(dāng)前操作的USB設(shè)備地址
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
void SetHostUsbAddr( u8 addr ) ?
{
CH374_WRITE_REGISTER(REG_USB_ADDR,addr);
}
/**
? *@Name:Init374Host
*@Describe:初始化USB主機(jī)
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
void Init374Host(void)
{
CH374_WRITE_REGISTER( REG_USB_SETUP,0x00);
SetHostUsbAddr(0x00);
CH374_WRITE_REGISTER( REG_USB_H_CTRL,0x00);
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG ); ?// 清所有中斷標(biāo)志
//CH374_WRITE_REGISTER( REG_INTER_EN, BIT_IE_TRANSFER ); ? ? ? ? ? ? ? ? ? ? ? ? // 允許傳輸完成中斷,因?yàn)楸境绦蚴褂貌樵?xún)方式檢測(cè)USB設(shè)備插拔,所以無(wú)需USB設(shè)備檢測(cè)中斷
CH374_WRITE_REGISTER( REG_INTER_EN, BIT_IE_TRANSFER | BIT_IE_DEV_DETECT ); ? ? // 允許傳輸完成中斷和USB設(shè)備檢測(cè)中斷
CH374_WRITE_REGISTER( REG_SYS_CTRL, BIT_CTRL_OE_POLAR ); ? ? ? ? ? ? ? ? ? ? ? // 對(duì)于CH374T或者UEN引腳懸空的CH374S必須置BIT_CTRL_OE_POLAR為1
SetHostLeisure(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // USB總線空閑
}
/**
? *@Name:HostSetReset
*@Describe:USB總線復(fù)位
*@Output:Not
*@Input:Not
*@Date:2017-02-20
**/
void HostSetReset(void)
{
UsbDevEndpSize = DEFAULT_ENDP0_SIZE; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// USB設(shè)備的端點(diǎn)0的最大包尺寸?
SetHostUsbAddr(0x00);
CH374_WRITE_REGISTER(REG_USB_H_CTRL,0x00);
//Write374Byte( REG_USB_SETUP, M_SET_USB_BUS_RESET( Read374Byte( REG_USB_SETUP ) & ~ BIT_SETP_AUTO_SOF ) ); ?// USB總線復(fù)位
CH374_WRITE_REGISTER( REG_USB_SETUP, M_SET_USB_BUS_RESET( BIT_SETP_HOST_MODE ) ); ? ? ? ? ? // USB總線復(fù)位
? OSTimeDly(1); //延時(shí)1*20ms = 20ms ?// USB總線復(fù)位期間
//Write374Byte( REG_USB_SETUP, M_SET_USB_BUS_FREE( Read374Byte( REG_USB_SETUP ) ) ); ?// USB總線空閑
SetHostLeisure(); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// USB總線空閑
delay_us(1000);
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_USB_SUSPEND ); ?// 清中斷標(biāo)志
}
/**
? *@Name:Query374DevFullSpeed
*@Describe:查詢(xún)當(dāng)前的USB設(shè)備是全速還是低速, 返回TRUE為全速?
*@Output:返回1則全速,返回0則低速
*@Input:Not
*@Date:2017-02-20
**/
u8 Query374DevFullSpeed(void)
{
if((CH374_READ_REGISTER(REG_SYS_INFO) & BIT_INFO_USB_DP))
return 1;
else
return 0;
}
/**
? *@Name:HostSetFullSpeed
*@Describe:設(shè)定全速USB設(shè)備運(yùn)行環(huán)境?
*@Output:Not
*@Input:Not
*@Date:2017-02-20
**/
void HostSetFullSpeed( void ) ?
{
CH374_WRITE_REGISTER(REG_USB_SETUP, (CH374_READ_REGISTER(REG_USB_SETUP) & (~BIT_SETP_USB_SPEED)) | BIT_SETP_AUTO_SOF );// 全速且發(fā)SOF
delay_us(1000);
}
/**
? *@Name:HostSetLowSpeed
*@Describe:設(shè)定低速USB設(shè)備運(yùn)行環(huán)境?
*@Output:Not
*@Input:Not
*@Date:2017-02-20
**/
void HostSetLowSpeed( void ) ?
{
CH374_WRITE_REGISTER(REG_USB_SETUP, CH374_READ_REGISTER(REG_USB_SETUP) | BIT_SETP_USB_SPEED | BIT_SETP_AUTO_SOF );// 低速且發(fā)SOF
delay_us(1000);
}
/**
? *@Name:Query374Interrupt
*@Describe:查詢(xún)CH374的中斷
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
u8 Query374Interrupt(void)
{
#ifdef CH374_INT_WIRE ??
?if(CH374_INT_WIRE) return 0;
?else return 1;
? ? //return( CH374_INT_WIRE ? FALSE : TRUE ); ?/* 如果連接了CH374的中斷引腳則直接查詢(xún)中斷引腳 */ ??
? #else ?
?if(CH374_READ_REGISTER( REG_INTER_FLAG ) & ( BIT_IF_DEV_DETECT | BIT_IF_TRANSFER )) return 1;
?else return 0;
? ?// return( Read374Byte( REG_INTER_FLAG ) & BIT_IF_INTER_FLAG ? TRUE : FALSE );/* 如果未連接CH374的中斷引腳則查詢(xún)中斷標(biāo)志寄存器 */ ??
? #endif ?
}
/**
? *@Name:Query374DeviceIn
*@Describe:檢測(cè)是否有USB設(shè)備插入
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
u8 Query374DeviceIn(void)
{
if(CH374_READ_REGISTER( REG_INTER_FLAG ) & BIT_IF_DEV_ATTACH ) ?
return 1;
else?
return 0;
}
/**
? *@Name:HostDetectInterrupt
*@Describe:處理USB設(shè)備插拔事件中斷
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
void HostDetectInterrupt( void ) ? ? ?
{
u8s,u;
? ?
s = CH374_READ_REGISTER( REG_INTER_FLAG );// 獲取中斷狀態(tài)
if( s & BIT_IF_DEV_DETECT )// USB設(shè)備插拔事件
? {
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT );// 清中斷標(biāo)志
if ( s & BIT_IF_DEV_ATTACH ) ? ? ? ? ? // USB設(shè)備連接事件
? ? {
u = CH374_READ_REGISTER( REG_USB_SETUP );
if ( s & BIT_IF_USB_DX_IN )// 速度匹配,不需要切換速度
? ? ? {
if ( u & BIT_SETP_USB_SPEED ) FlagDeviceStatus = USB_INT_CONNECT_LS;// 低速USB設(shè)備
else FlagDeviceStatus = USB_INT_CONNECT;// 全速USB設(shè)備
}
else// 速度失配,需要切換速度
? ? ? {
if ( u & BIT_SETP_USB_SPEED ) FlagDeviceStatus = USB_INT_CONNECT;// 全速USB設(shè)備
else FlagDeviceStatus = USB_INT_CONNECT_LS;// 低速USB設(shè)備
}
}
else FlagDeviceStatus = USB_INT_DISCONNECT;// USB設(shè)備斷開(kāi)事件
}
else // 意外的中斷
? {?
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER | BIT_IF_USB_SUSPEND | BIT_IF_WAKE_UP );// 清中斷標(biāo)志
}
}
/**
? *@Name:Wait374Interrupt
*@Describe:等待CH374中斷(INT#低電平),超時(shí)則返回ERR_USB_UNKNOWN?
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-21
**/
u8 Wait374Interrupt(void) ??
{ ??
u16 i;?
??
for(i = 0; i < 10000; i++ ) // 計(jì)數(shù)防止超時(shí)?
{ ? ?
if(Query374Interrupt())?
return 0; ??
} ??
return ERR_USB_UNKNOWN; // 不應(yīng)該發(fā)生的情況 ??
}?
/**
? *@Name:HostTransact374
*@Describe: CH374傳輸事務(wù)
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-21
**/
/* CH374傳輸事務(wù),輸入目的端點(diǎn)地址/PID令牌/同步標(biāo)志,返回同CH375,NAK不重試,超時(shí)/出錯(cuò)重試 */
u8HostTransact374(u8 endp_addr,u8 pid,u8 tog )
{ ?// 本子程序著重于易理解,而在實(shí)際應(yīng)用中,為了提供運(yùn)行速度,應(yīng)該對(duì)本子程序代碼進(jìn)行優(yōu)化
u8retry;
u8s,r,u;
for(retry = 0;retry < 3;retry++)
{
CH374_WRITE_REGISTER( REG_USB_H_PID,M_MK_HOST_PID_ENDP(pid,endp_addr) ); // 指定令牌PID和目的端點(diǎn)號(hào)
//Write374Byte( REG_USB_H_CTRL, BIT_HOST_START | ( tog ? ( BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : 0x00 ) ); ?// 設(shè)置同步標(biāo)志并啟動(dòng)傳輸
CH374_WRITE_REGISTER( REG_USB_H_CTRL, ( tog ? ( BIT_HOST_START | BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : BIT_HOST_START ) );// 設(shè)置同步標(biāo)志并啟動(dòng)傳輸
/*
if(tog)
?CH374_WRITE_REGISTER( REG_USB_H_CTRL, ( BIT_HOST_START | BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) );// 設(shè)置同步標(biāo)志并啟動(dòng)傳輸
else
?CH374_WRITE_REGISTER( REG_USB_H_CTRL, BIT_HOST_START ); ?// 設(shè)置同步標(biāo)志并啟動(dòng)傳輸
*/
s = Wait374Interrupt();
if(s == ERR_USB_UNKNOWN ) return( s ); // 中斷超時(shí),可能是硬件異常
s = CH374_READ_REGISTER(REG_INTER_FLAG);// 獲取中斷狀態(tài)
if( s & BIT_IF_DEV_DETECT ) // USB設(shè)備插拔事件
{ ? ? ? ? ? ? ? ? ?
//delay_us( 250 ); // 等待傳輸完成
OSTimeDly(1);//1*20ms
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER );// 清中斷標(biāo)志
if ( s & BIT_IF_DEV_ATTACH )// USB設(shè)備連接事件
{ ? ? ? ? ? ??
//delay_us( 200 ); ?// 等待傳輸完成
OSTimeDly(1);//1*20ms
u = CH374_READ_REGISTER( REG_USB_SETUP );
if( s & BIT_IF_USB_DX_IN )// 速度匹配,不需要切換速度
{ ? ? ? ? ??
if( u & BIT_SETP_USB_SPEED )?
return( USB_INT_CONNECT_LS );// 低速USB設(shè)備
return( USB_INT_CONNECT );// 全速USB設(shè)備
}
else // 速度失配,需要切換速度
{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
if( u & BIT_SETP_USB_SPEED )?
return( USB_INT_CONNECT );// 全速USB設(shè)備
return( USB_INT_CONNECT_LS );// 低速USB設(shè)備
}
}
else return( USB_INT_DISCONNECT );// USB設(shè)備斷開(kāi)事件
}
else if( s & BIT_IF_TRANSFER ) // 傳輸完成
{ ? ? ? ? ? ? ?
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER ); ?// 清中斷標(biāo)志
s = CH374_READ_REGISTER(REG_USB_STATUS);// USB狀態(tài)
r = s & BIT_STAT_DEV_RESP;// USB設(shè)備應(yīng)答狀態(tài)
switch( pid )?
{
case DEF_USB_PID_SETUP:
case DEF_USB_PID_OUT:
if ( r == DEF_USB_PID_ACK )
return( USB_INT_SUCCESS );
else if ((r == DEF_USB_PID_STALL) || (r == DEF_USB_PID_NAK) )?
return( r | 0x20 );
else if ( ! M_IS_HOST_TIMEOUT( s ) )?
return( r | 0x20 ); ?// 不是超時(shí)/出錯(cuò),意外應(yīng)答
break;
case DEF_USB_PID_IN:
if( M_IS_HOST_IN_DATA( s ) ) // DEF_USB_PID_DATA0 or DEF_USB_PID_DATA1
{ ?
if( s & BIT_STAT_TOG_MATCH )?
return( USB_INT_SUCCESS ); ?// 不同步則需丟棄后重試
}
else if ((r == DEF_USB_PID_STALL) || (r == DEF_USB_PID_NAK) )?
return( r | 0x20 );
else if ( ! M_IS_HOST_TIMEOUT( s ) )?
return( r | 0x20 ); ?// 不是超時(shí)/出錯(cuò),意外應(yīng)答
break;
default:
return( ERR_USB_UNKNOWN ); ? ? ? // 不可能的情況
}
}
else // 其它中斷,不應(yīng)該發(fā)生的情況
{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
//delay_us(200);// 等待傳輸完成
OSTimeDly(1); //延時(shí)1*20ms = 20ms ? ?
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG ); /* 清中斷標(biāo)志 */
if(retry) return( ERR_USB_UNKNOWN ); ?// 不是第一次檢測(cè)到則返回錯(cuò)誤 ?FA
}
}
return( 0x20 );// 應(yīng)答超時(shí)
}
/**
? *@Name:WaitHostTransact374
*@Describe: CH374傳輸事務(wù)
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-21
**/
/* ?CH374傳輸事務(wù),輸入目的端點(diǎn)地址/PID令牌/同步標(biāo)志/以mS為單位的NAK重試總時(shí)間(0xFFFF無(wú)限重試),返回同CH375,NAK重試,超時(shí)出錯(cuò)重試 */
u8 WaitHostTransact374(u8 endp_addr,u8 pid,u8 tog,u16 timeout )
{
u8 i, s;
while(1)?
{
for(i = 0; i < 1; i++ )?
{
s = HostTransact374( endp_addr, pid, tog );//01 09 00
/*
if(s == 0x14)
?printf("獲取按鍵成功:%02X\r\n",s);
else
?printf("獲取按鍵失敗:%02X\r\n",s);
*/
if( (s != ( DEF_USB_PID_NAK | 0x20 )) || (timeout == 0) ) // 0X0A | 0X20
return( s );//返回 0X2A ?和 ?0X20
delay_us( 20 );
//OSTimeDly(1); //延時(shí)14*20ms = 280ms ? ?
}
if(timeout < 0xFFFF) timeout --;
}
}
/**
? *@Name:HostCtrlTransfer374
*@Describe: 執(zhí)行控制傳輸
*@Output:Not
*@Input:
*@Date:2017-02-20
**/
/* 執(zhí)行控制傳輸,ReqBuf指向8字節(jié)請(qǐng)求碼,DatBuf為收發(fā)緩沖區(qū) */
u8 HostCtrlTransfer374(u8 *ReqBuf,u8 *DatBuf,u8 *RetLen ) ?
{// 如果需要接收和發(fā)送數(shù)據(jù),那么DatBuf需指向有效緩沖區(qū)用于存放后續(xù)數(shù)據(jù),實(shí)際成功收發(fā)的總長(zhǎng)度保存在ReqLen指向的字節(jié)變量中
u8 s,len,count,total;
u8 tog;
CH374_WRITE_BLOCK(RAM_HOST_TRAN,8,ReqBuf );
CH374_WRITE_REGISTER( REG_USB_LENGTH, 8 );
delay_us(100);
s = WaitHostTransact374(0,DEF_USB_PID_SETUP,0,200 ); // SETUP階段,200mS超時(shí)
if( s == USB_INT_SUCCESS )// SETUP成功
? {
tog = 1;// 默認(rèn)DATA1,默認(rèn)無(wú)數(shù)據(jù)故狀態(tài)階段為IN
if((*(ReqBuf+3))==0x22)
? ? {
total = *( ReqBuf+6) - 0x40;
?}
else?
{
total = *( ReqBuf + 6 );
}
if(total && DatBuf)// 需要收數(shù)據(jù)
? ? {
len = total;
if( *ReqBuf & 0x80 )// 收
? ? ? {
while(len)?
? ? ? ? {
delay_us(100);
s = WaitHostTransact374( 0, DEF_USB_PID_IN, tog, 200 ); ?// IN數(shù)據(jù)
if ( s != USB_INT_SUCCESS ) break;
count = CH374_READ_REGISTER( REG_USB_LENGTH );
CH374_READ_BLOCK( RAM_HOST_RECV, count, DatBuf );
DatBuf += count;
if( count <= len )?
len -= count;
else?
len = 0;
if( count & (UsbDevEndpSize - 1) )?
break; ?// 短包
if(tog)
tog = 0;
else
tog = 1;
}
tog = 0;// 狀態(tài)階段為OUT
}
else?
{// 發(fā)
while( len )?
? ? ? ? {
delay_us(100);
count = len >= UsbDevEndpSize ? UsbDevEndpSize : len;
/*
if(len >= UsbDevEndpSize)
count = UsbDevEndpSize;
else
?count = len;
*/
CH374_WRITE_BLOCK( RAM_HOST_TRAN, count, DatBuf );
CH374_WRITE_REGISTER( REG_USB_LENGTH, count );
s = WaitHostTransact374(0,DEF_USB_PID_OUT,tog,200); ?// OUT數(shù)據(jù)
if ( s != USB_INT_SUCCESS ) break;
DatBuf += count;
len -= count;
if(tog)
tog = 0;
else
tog = 1;
}
tog = 1; ? ? ? ? ? ? ? ?// 狀態(tài)階段為IN
}
total -= len; ? ? ? ? ? ? ? ? ?// 減去剩余長(zhǎng)度得實(shí)際傳輸長(zhǎng)度
}
if( s == USB_INT_SUCCESS ) ? ? ? ?// 數(shù)據(jù)階段成功
? ? {
CH374_WRITE_REGISTER( REG_USB_LENGTH,0);
delay_us( 100 );
if(tog)
?s = WaitHostTransact374(0,DEF_USB_PID_IN,1,200); ?// STATUS階段
else
s = WaitHostTransact374(0,DEF_USB_PID_OUT,1,200); ?// STATUS階段
if ( tog && s == USB_INT_SUCCESS ) ? ?// 檢查IN狀態(tài)返回?cái)?shù)據(jù)長(zhǎng)度
? ? ? {
if( CH374_READ_REGISTER(REG_USB_LENGTH) )?
s = USB_INT_BUF_OVER; ?// 狀態(tài)階段錯(cuò)誤
}
}
}
if( RetLen )?
*RetLen = total;// 實(shí)際成功收發(fā)的總長(zhǎng)度
return s;
}
/**
? *@Name:SetUsbAddress
*@Describe:設(shè)置USB設(shè)備地址?
*@Output:Not
*@Input:addr 地址
*@Date:2017-02-20
**/
u8 SetUsbAddress(u8 addr ) ?
{
u8 s;
u8 BufSetAddr[sizeof(SetupSetUsbAddr)] ;
memcpy ( BufSetAddr,SetupSetUsbAddr, sizeof( SetupSetUsbAddr ) );
((PUSB_SETUP_REQ)BufSetAddr) -> wValueL = addr;// USB設(shè)備地址
s = HostCtrlTransfer374( BufSetAddr, NULL, NULL );// 執(zhí)行控制傳輸
if (s == USB_INT_SUCCESS)?
{
SetHostUsbAddr(addr);// 設(shè)置USB主機(jī)當(dāng)前操作的USB設(shè)備地址
}
delay_us(3000);// 等待USB設(shè)備完成操作
return(s);
}
/**
? *@Name:GetDeviceDescr
*@Describe:設(shè)置USB設(shè)備配置?
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-20
**/
u8 SetUsbConfig(u8 cfg ) ?
{
u8 BufSetCfg[ sizeof( SetupSetUsbConfig ) ] ;
memcpy ( BufSetCfg, SetupSetUsbConfig, sizeof( SetupSetUsbConfig ) );
((PUSB_SETUP_REQ)BufSetCfg )-> wValueL = cfg;// USB設(shè)備配置
return(HostCtrlTransfer374(BufSetCfg,NULL, NULL )); ?// 執(zhí)行控制傳輸
}
/**
? *@Name:GetDeviceDescr
*@Describe:獲取設(shè)備描述符
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-20
**/
u8 GetDeviceDescr(u8 *buf ) ?
{
u8 s,len;
s = HostCtrlTransfer374((u8 *)SetupGetDevDescr,buf,&len );// 執(zhí)行控制傳輸
if ( s == USB_INT_SUCCESS )?
{
UsbDevEndpSize = ((PUSB_DEV_DESCR)buf) -> bMaxPacketSize0; // 端點(diǎn)0最大包長(zhǎng)度,這是簡(jiǎn)化處理,正常應(yīng)該先獲取前8字節(jié)后立即更新UsbDevEndpSize再繼續(xù)
if( len < ((PUSB_SETUP_REQ)SetupGetDevDescr) -> wLengthL ) s = USB_INT_BUF_OVER; ?// 描述符長(zhǎng)度錯(cuò)誤
}
return(s);
}
/**
? *@Name:GetConfigDescr
*@Describe:獲取配置描述符?
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-20
**/
u8 GetConfigDescr(u8 *buf) ?
{
u8 s,len,i,c,j;
u8 BufLogDescr[sizeof(SetupGetCfgDescr)] ;
s = HostCtrlTransfer374((u8*)SetupGetCfgDescr,buf,&len ); ? ?// 執(zhí)行控制傳輸
if(s == USB_INT_SUCCESS)?
? {
// for(i=0;i!=len;i++)
// ?printf("%02x ",(unsigned short)buf[i]);
// printf("\n");
if( len < ((PUSB_SETUP_REQ)SetupGetCfgDescr) -> wLengthL )?
{
s = USB_INT_BUF_OVER; ?// 返回長(zhǎng)度錯(cuò)誤
}
else?
? ? {
memcpy(BufLogDescr,SetupGetCfgDescr,sizeof( SetupGetCfgDescr));
((PUSB_SETUP_REQ)BufLogDescr ) -> wLengthL = ((PUSB_CFG_DESCR)buf) -> wTotalLengthL; ?// 完整配置描述符的總長(zhǎng)度
s = HostCtrlTransfer374(BufLogDescr,buf,&len); ? // 執(zhí)行控制傳輸
if(s == USB_INT_SUCCESS )?
? ? ? {
? ? ? ? //簡(jiǎn)單分析配置描述符,獲取端點(diǎn)地址,這里只處理一個(gè)端點(diǎn)的情況
printf("獲取配置描述符:\r\n");
for ( i = 0; i < ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL; i ++ )?
?printf("%02X ", (UINT16)( buf[i] ) ); ?//配置描述符
printf( "\r\n" );
for(i=0;i<((PUSB_CFG_DESCR)buf) -> wTotalLengthL;i++)?
{
if((buf[i]==0x09) && (buf[i+1]==0x21) && (buf[i+6]==0x22))
{
hid_des_leng=buf[i+7]; ? ?//獲取報(bào)告描述符的長(zhǎng)度 ? ? ? ?
? ? ? ? ? ? break;
}
}
printf("hid_des_leng=%02x\r\n",hid_des_leng);
endp_out_addr =0;
endp_in_addr = 0;
c = 0;
for(i=0;i<( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL;i++)?
{
if(((buf[i]==0x09) && (buf[i+1]==0x04)&&(buf[i+5]==0x03) && (buf[i+7]==0x01)) || (buf[i+7]==0x02)) ?//接口描述符為HID的鼠標(biāo)、鍵盤(pán) ??
{?
for(j=0;j<(((PUSB_CFG_DESCR)buf ) -> wTotalLengthL-i);j++)?
{
?if((buf[i+j]==0x07) && (buf[i+j+1]==0x05) && (buf[i+j+3]==0x03)) ??
c = buf[i+j+2];//判斷是否為中斷端點(diǎn)
if(c & 0x80) ? ?
endp_in_addr = (c&0x0f);// IN端點(diǎn)的地址 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
else ? ? ? ? ? ??
endp_out_addr = (c&0x0f);
if((endp_out_addr!=0)||(endp_in_addr!=0)) ??
break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
}
}
if((endp_out_addr!=0)||(endp_in_addr!=0)) ??
break; ? ? ? ? ??
}
printf("endp_in_addr=%02x\r\n",(unsigned short)endp_in_addr);
printf("endp_out_addr=%02x\r\n",(unsigned short)endp_out_addr);
}
}
? }
return s ;
}
/**
? *@Name:SetIdle
*@Describe:設(shè)置IDLE
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-21
**/
u8 SetIdle(void)//設(shè)置IDLE
{
u8 s;
s = HostCtrlTransfer374(SetupSetidle,NULL,NULL);
return s;
}
/**
? *@Name:GetHidDes
*@Describe:獲取報(bào)表描述符
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-21
**/
u8 GetHidDes(u8 *p)//獲取報(bào)表描述符
{
u8 s;
u8 buffer[8];
//leng=SetupGetHidDes[0x06]-0x40;//報(bào)表描述符的長(zhǎng)度在發(fā)送數(shù)據(jù)長(zhǎng)度的基礎(chǔ)上減去0X40
//0x81,0x06,0x00,0x22,0x00,0x00,0x81,0x00
memcpy(buffer,SetupGetHidDes,8);
buffer[0x06] = hid_des_leng+0x40;
s=HostCtrlTransfer374(buffer,p,&buffer[0x06]);
return s;
}
/**
? *@Name:SetReport
*@Describe:
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-21
**/
u8 SetReport(u8 *p)
{
u8 s,l=1;
s = HostCtrlTransfer374(SetupSetReport,p,&l);//實(shí)際的數(shù)據(jù)可以寫(xiě)別的數(shù)據(jù),這個(gè)你可以用計(jì)算機(jī)抓下數(shù)據(jù)在發(fā)下去
return s;
}
?
/**
? *@Name:SetReport
*@Describe:通過(guò)中斷端點(diǎn)獲取鼠標(biāo)、鍵盤(pán)上傳的數(shù)據(jù)?
*@Output:Not
*@Input:返回是否獲取設(shè)備描述符成功
*@Date:2017-02-21
**/
u8 Interrupt_Data_Trans(u8 *p)
{
u8 s,count;
s = WaitHostTransact374(endp_in_addr,DEF_USB_PID_IN,ReadDataFlag,1000 );// IN數(shù)據(jù) 01 09 00 1000
if(s != USB_INT_SUCCESS )
? {
? ? //delay_us(5000);?
OSTimeDly(3); //延時(shí)14*20ms = 280ms ? ?
? ? return s;
? }
else
? {
count = CH374_READ_REGISTER(REG_USB_LENGTH);
CH374_READ_BLOCK(RAM_HOST_RECV,count,p);
if(ReadDataFlag)
ReadDataFlag = 0;
else
ReadDataFlag = 1;
}
return s;
}
/**
? *@Name:USB_Equipment
*@Describe:USB設(shè)備初始化,枚舉
*@Output:Not
*@Input:
*@Date:2017-02-19
**/
int USB_Equipment(void)
{
u8 i=0,s=0;
u8 close_bit_flag=0;
u8 DeviceDescribe_buf[80];//由于報(bào)告描述符大小不定,緩沖區(qū)的大小最好定義大些
Init374Host();// 初始化USB主機(jī)
while(1)
{
SetHostLeisure();//設(shè)定USB主機(jī)空閑
while(1)
{
if (Query374Interrupt()) HostDetectInterrupt(); ?// 如果有USB主機(jī)中斷則處理
if (Query374DeviceIn()) break; ? ? ? ? ? ? ? ? ? // 有USB設(shè)備
?OSTimeDly(5); //100ms
}
OSTimeDly(14); //延時(shí)14*20ms = 280ms ? ? ?// 由于USB設(shè)備剛插入尚未穩(wěn)定,故等待USB設(shè)備數(shù)百毫秒,消除插拔抖動(dòng)
if(Query374Interrupt()) HostDetectInterrupt(); // 如果有USB主機(jī)中斷則處理
? ??
HostSetReset();// USB總線復(fù)位
for(i=0;i<100;i++ )// 等待USB設(shè)備復(fù)位后重新連接
? ? {
if(Query374DeviceIn()) ?break; // 有USB設(shè)備
delay_us(1000);
}
if(Query374Interrupt()) HostDetectInterrupt( ); // 如果有USB主機(jī)中斷則處理
if(Query374DeviceIn())// 有USB設(shè)備
? ? { ?
if(Query374DevFullSpeed())
? ? ? {
HostSetFullSpeed();// 檢測(cè)到全速USB設(shè)備
// printf("全速USB設(shè)備插入:\r\n");
printf("Full-Speed Device\r\n");
}
else?
? ? ? {
HostSetLowSpeed();// 檢測(cè)到低速USB設(shè)備
//printf("低速USB設(shè)備插入:\r\n");
printf("Low-Speed Device\r\n");
}
}
else?
? ? {
continue;// 設(shè)備已經(jīng)斷開(kāi),繼續(xù)等待
}
OSTimeDly(3); //延時(shí)3*20ms = 60ms?
close_bit_flag=0;//設(shè)備是否拔出
//1、獲取設(shè)備描述符
s = GetDeviceDescr(DeviceDescribe_buf); // 獲取設(shè)備描述符
if(s != USB_INT_SUCCESS )
? ? {
printf("獲取設(shè)備描述符失敗\r\n");
goto WaitDeviceOut;// 終止操作,等待USB設(shè)備拔出
}
printf("設(shè)備描述符:");
for(i=0;i <((PUSB_SETUP_REQ)SetupGetDevDescr ) -> wLengthL;i++ )?
?printf("%02X ",DeviceDescribe_buf[i]);//輸出描述符
printf( "\r\n" );
//2、設(shè)置USB設(shè)備地址 ? ?
s = SetUsbAddress(0x02);// 設(shè)置USB設(shè)備地址
if(s != USB_INT_SUCCESS )
{
printf("設(shè)置USB設(shè)備地址錯(cuò)誤\r\n");
goto WaitDeviceOut;// 終止操作,等待USB設(shè)備拔出
}
printf("設(shè)置USB設(shè)備地址0X02成功\r\n");
//3、獲取配置描述符
s = GetConfigDescr(DeviceDescribe_buf); // 獲取配置描述符
//printf("config_status=%02x\r\n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
printf("獲取配置描述符錯(cuò)誤\r\n");
goto WaitDeviceOut;// 終止操作,等待USB設(shè)備拔出
}
//4、設(shè)置USB設(shè)備配置
// 分析配置描述符,獲取端點(diǎn)數(shù)據(jù)/各端點(diǎn)地址/各端點(diǎn)大小等,更新變量endp_addr和endp_size等?
s = SetUsbConfig( ( (PUSB_CFG_DESCR)DeviceDescribe_buf ) -> bConfigurationValue ); // 設(shè)置USB設(shè)備配置
if ( s != USB_INT_SUCCESS )?
{
printf("獲取配置描述符錯(cuò)誤\r\n");
? ? goto WaitDeviceOut;// 終止操作,等待USB設(shè)備拔出
}
printf("設(shè)置USB設(shè)備配置成功\r\n");
//-------------------------以下進(jìn)行HID類(lèi)的簡(jiǎn)單操作-----------------------------------------------------------
//5、設(shè)置IDLE
s = SetIdle();//設(shè)置IDLE,這個(gè)步驟是按照HID類(lèi)的協(xié)議來(lái)做的
if(s != USB_INT_SUCCESS)
? ? {
? ? ? if((s&0x0f) == USB_INT_RET_STALL) ?goto next_operate1; //返回STALL可能本身不支持
}
printf("設(shè)置IDLE成功\r\n");
next_operate1:
//6、獲取報(bào)表描述符
s=GetHidDes(DeviceDescribe_buf);// 獲取報(bào)表描述符
if(s==USB_INT_SUCCESS)
? ? {
printf("HID_Desc: ");
for(i=0;i!=hid_des_leng;i++) ?
?printf("%02x ",DeviceDescribe_buf[i]);
printf("\r\n");
}
else
? ? {
printf("獲取報(bào)表描述符描述符錯(cuò)誤\r\n");
goto WaitDeviceOut;//出錯(cuò)退出
}
DeviceDescribe_buf[0]=0x01;
//設(shè)置報(bào)表
s = SetReport(DeviceDescribe_buf);//設(shè)置報(bào)表
if(s==USB_INT_SUCCESS) ??
{
printf("Set_Report success\r\n");
}
else //設(shè)置報(bào)告出錯(cuò)
? ? {?
? ? ?if((s&0x0f) == USB_INT_RET_STALL) ?goto next_operate2; ? ? ?//返回STALL可能本身不支持 ?
}
next_operate2:
// 下面開(kāi)始讀取數(shù)據(jù) ( 實(shí)際在讀取數(shù)據(jù)的時(shí)候,要先發(fā)送中斷端點(diǎn)的令牌來(lái)讀取數(shù)據(jù),接著才能獲取到數(shù)據(jù) )
ReadDataFlag = 0; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//開(kāi)始取DATA0
while(1)
? ? {
s = Interrupt_Data_Trans(DeviceDescribe_buf);
printf("s = %X\r\n",s);
if(s==USB_INT_SUCCESS)
? ? ? {
for(i=0;i!=8;i++)
?printf("%02x ",DeviceDescribe_buf[i]);
printf("\r\n");
}
else if(s == USB_INT_DISCONNECT)// ?這個(gè)是為了知道設(shè)備拔出產(chǎn)生的中斷狀態(tài)
? ? ? {
close_bit_flag=1;
break;
}
OSTimeDly(5); //100ms
}
//-------------------------------------------------------------------------------------------------------
WaitDeviceOut: // 等待USB設(shè)備拔出
?printf( "Wait Device Out\r\n" );
?if(close_bit_flag==0)//設(shè)備拔出
{
while(1)
{
if(Query374Interrupt()) HostDetectInterrupt( );// 如果有USB主機(jī)中斷則處理
if(Query374DeviceIn() == FALSE ) break; ? // 沒(méi)有USB設(shè)備
OSTimeDly(5); //100ms?
}
?}
OSTimeDly(5); //延時(shí)5*20ms = 100ms ?
}
}
//--------------------------------------------------------------------------------------
串口輸出信息:
Low-Speed Device
設(shè)備描述符:12 01 10 01 00 00 00 08 D5 05 89 06 03 01 00 01 00 01?
設(shè)置USB設(shè)備地址0X02成功
獲取配置描述符:
09 02 3B 00 02 01 00 A0 32?
09 04 00 00 01 03 01 01 00?
09 21 10 01 00 01 22 41 00?
07 05 81 03 08 00 0A?
09 04 01 00 01 03 00 00 00?
09 21 10 01 00 01 22 32 00?
07 05 82 03 05 00 0A?
hid_des_leng=41
endp_in_addr=01
endp_out_addr=00
設(shè)置USB設(shè)備配置成功
設(shè)置IDLE成功
HID_Desc: 05 01 09 06 a1 01 05 07 19 e0 29 e7 15 00 25 01 95 08 75 01 81 02 95 08 75 01 81 01 05 08 19 01 29 03 95 03 75 01 91 02 95 01 75 05 91 01 05 07 19 00 2a ff 00 15 00 26 ff 00 95 06 75 08 81 00 c0?
Set_Report success
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 2A
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
s = 20
Wait Device Out