#include "include.h"
#include "bsp_ch374.h"
const u8 SetupGetDevDescr[] = {0x80,0x06,0x00,0x01,0x00,0x00,0x12,0x00};/* 获取设备描述符 */
constu8 SetupGetCfgDescr[] = {0x80,0x06,0x00,0x02,0x00,0x00,0x04,0x00};/* 获取配置描述符 */
constu8 SetupSetUsbAddr[] = {0x00,0x05,0x02,0x00,0x00,0x00,0x00,0x00};/* 设置USB地址 */
const u8 SetupSetUsbConfig[] = {0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00};/* 设置USB配置 */
u8 SetupSetidle[]={0x21,0x0a,0x00,0x00,0x00,0x00,0x00,0x00}; /* SET IDLE */
u8 SetupGetHidDes[]={0x81,0x06,0x00,0x22,0x00,0x00,0x81,0x00};/* 获取HID 报告描述符 */
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 端点地址
u8 ReadDataFlag;//读取数据的同步标志
u8 hid_des_leng;// HID类报告描述符的长度
u8 FlagDeviceStatus;// 当前USB设备状态,通常用于中断方式的全局变量,本程序中未使用
u8 UsbDevEndpSize = DEFAULT_ENDP0_SIZE;
/**
*@Name:SetHostLeisure
*@Describe:设定USB主机空闲
*@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总线复位
}
/**
*@Name:SetHostUsbAddr
*@Describe:设置USB主机当前操作的USB设备地址
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
void SetHostUsbAddr( u8 addr )
{
CH374_WRITE_REGISTER(REG_USB_ADDR,addr);
}
/**
*@Name:Init374Host
*@Describe:初始化USB主机
*@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 ); // 清所有中断标志
//CH374_WRITE_REGISTER( REG_INTER_EN, BIT_IE_TRANSFER ); // 允许传输完成中断,因为本程序使用查询方式检测USB设备插拔,所以无需USB设备检测中断
CH374_WRITE_REGISTER( REG_INTER_EN, BIT_IE_TRANSFER | BIT_IE_DEV_DETECT ); // 允许传输完成中断和USB设备检测中断
CH374_WRITE_REGISTER( REG_SYS_CTRL, BIT_CTRL_OE_POLAR ); // 对于CH374T或者UEN引脚悬空的CH374S必须置BIT_CTRL_OE_POLAR为1
SetHostLeisure(); // USB总线空闲
}
/**
*@Name:HostSetReset
*@Describe:USB总线复位
*@Output:Not
*@Input:Not
*@Date:2017-02-20
**/
void HostSetReset(void)
{
UsbDevEndpSize = DEFAULT_ENDP0_SIZE; // USB设备的端点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总线复位
CH374_WRITE_REGISTER( REG_USB_SETUP, M_SET_USB_BUS_RESET( BIT_SETP_HOST_MODE ) ); // USB总线复位
OSTimeDly(1); //延时1*20ms = 20ms // USB总线复位期间
//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 ); // 清中断标志
}
/**
*@Name:Query374DevFullSpeed
*@Describe:查询当前的USB设备是全速还是低速, 返回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:设定全速USB设备运行环境
*@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 );// 全速且发SOF
delay_us(1000);
}
/**
*@Name:HostSetLowSpeed
*@Describe:设定低速USB设备运行环境
*@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 );// 低速且发SOF
delay_us(1000);
}
/**
*@Name:Query374Interrupt
*@Describe:查询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的中断引脚则直接查询中断引脚 */
#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的中断引脚则查询中断标志寄存器 */
#endif
}
/**
*@Name:Query374DeviceIn
*@Describe:检测是否有USB设备插入
*@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设备插拔事件中断
*@Output:Not
*@Input:Not
*@Date:2017-02-19
**/
void HostDetectInterrupt( void )
{
u8s,u;
s = CH374_READ_REGISTER( REG_INTER_FLAG );// 获取中断状态
if( s & BIT_IF_DEV_DETECT )// USB设备插拔事件
{
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT );// 清中断标志
if ( s & BIT_IF_DEV_ATTACH ) // USB设备连接事件
{
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设备
else FlagDeviceStatus = USB_INT_CONNECT;// 全速USB设备
}
else// 速度失配,需要切换速度
{
if ( u & BIT_SETP_USB_SPEED ) FlagDeviceStatus = USB_INT_CONNECT;// 全速USB设备
else FlagDeviceStatus = USB_INT_CONNECT_LS;// 低速USB设备
}
}
else FlagDeviceStatus = USB_INT_DISCONNECT;// USB设备断开事件
}
else // 意外的中断
{
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER | BIT_IF_USB_SUSPEND | BIT_IF_WAKE_UP );// 清中断标志
}
}
/**
*@Name:Wait374Interrupt
*@Describe:等待CH374中断(INT#低电平),超时则返回ERR_USB_UNKNOWN
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-21
**/
u8 Wait374Interrupt(void)
{
u16 i;
for(i = 0; i < 10000; i++ ) // 计数防止超时
{
if(Query374Interrupt())
return 0;
}
return ERR_USB_UNKNOWN; // 不应该发生的情况
}
/**
*@Name:HostTransact374
*@Describe: CH374传输事务
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-21
**/
/* CH374传输事务,输入目的端点地址/PID令牌/同步标志,返回同CH375,NAK不重试,超时/出错重试 */
u8HostTransact374(u8 endp_addr,u8 pid,u8 tog )
{ // 本子程序着重于易理解,而在实际应用中,为了提供运行速度,应该对本子程序代码进行优化
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和目的端点号
//Write374Byte( REG_USB_H_CTRL, BIT_HOST_START | ( tog ? ( BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : 0x00 ) ); // 设置同步标志并启动传输
CH374_WRITE_REGISTER( REG_USB_H_CTRL, ( tog ? ( BIT_HOST_START | BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) : BIT_HOST_START ) );// 设置同步标志并启动传输
/*
if(tog)
CH374_WRITE_REGISTER( REG_USB_H_CTRL, ( BIT_HOST_START | BIT_HOST_TRAN_TOG | BIT_HOST_RECV_TOG ) );// 设置同步标志并启动传输
else
CH374_WRITE_REGISTER( REG_USB_H_CTRL, BIT_HOST_START ); // 设置同步标志并启动传输
*/
s = Wait374Interrupt();
if(s == ERR_USB_UNKNOWN ) return( s ); // 中断超时,可能是硬件异常
s = CH374_READ_REGISTER(REG_INTER_FLAG);// 获取中断状态
if( s & BIT_IF_DEV_DETECT ) // USB设备插拔事件
{
//delay_us( 250 ); // 等待传输完成
OSTimeDly(1);//1*20ms
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_DEV_DETECT | BIT_IF_TRANSFER );// 清中断标志
if ( s & BIT_IF_DEV_ATTACH )// USB设备连接事件
{
//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设备
return( USB_INT_CONNECT );// 全速USB设备
}
else // 速度失配,需要切换速度
{
if( u & BIT_SETP_USB_SPEED )
return( USB_INT_CONNECT );// 全速USB设备
return( USB_INT_CONNECT_LS );// 低速USB设备
}
}
else return( USB_INT_DISCONNECT );// USB设备断开事件
}
else if( s & BIT_IF_TRANSFER ) // 传输完成
{
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_TRANSFER ); // 清中断标志
s = CH374_READ_REGISTER(REG_USB_STATUS);// USB状态
r = s & BIT_STAT_DEV_RESP;// USB设备应答状态
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 ); // 不是超时/出错,意外应答
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 ); // 不是超时/出错,意外应答
break;
default:
return( ERR_USB_UNKNOWN ); // 不可能的情况
}
}
else // 其它中断,不应该发生的情况
{
//delay_us(200);// 等待传输完成
OSTimeDly(1); //延时1*20ms = 20ms
CH374_WRITE_REGISTER( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG ); /* 清中断标志 */
if(retry) return( ERR_USB_UNKNOWN ); // 不是第一次检测到则返回错误 FA
}
}
return( 0x20 );// 应答超时
}
/**
*@Name:WaitHostTransact374
*@Describe: CH374传输事务
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-21
**/
/* CH374传输事务,输入目的端点地址/PID令牌/同步标志/以mS为单位的NAK重试总时间(0xFFFF无限重试),返回同CH375,NAK重试,超时出错重试 */
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); //延时14*20ms = 280ms
}
if(timeout < 0xFFFF) timeout --;
}
}
/**
*@Name:HostCtrlTransfer374
*@Describe: 执行控制传输
*@Output:Not
*@Input:
*@Date:2017-02-20
**/
/* 执行控制传输,ReqBuf指向8字节请求码,DatBuf为收发缓冲区 */
u8 HostCtrlTransfer374(u8 *ReqBuf,u8 *DatBuf,u8 *RetLen )
{// 如果需要接收和发送数据,那么DatBuf需指向有效缓冲区用于存放后续数据,实际成功收发的总长度保存在ReqLen指向的字节变量中
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超时
if( s == USB_INT_SUCCESS )// SETUP成功
{
tog = 1;// 默认DATA1,默认无数据故状态阶段为IN
if((*(ReqBuf+3))==0x22)
{
total = *( ReqBuf+6) - 0x40;
}
else
{
total = *( ReqBuf + 6 );
}
if(total && DatBuf)// 需要收数据
{
len = total;
if( *ReqBuf & 0x80 )// 收
{
while(len)
{
delay_us(100);
s = WaitHostTransact374( 0, DEF_USB_PID_IN, tog, 200 ); // IN数据
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;// 状态阶段为OUT
}
else
{// 发
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数据
if ( s != USB_INT_SUCCESS ) break;
DatBuf += count;
len -= count;
if(tog)
tog = 0;
else
tog = 1;
}
tog = 1; // 状态阶段为IN
}
total -= len; // 减去剩余长度得实际传输长度
}
if( s == USB_INT_SUCCESS ) // 数据阶段成功
{
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状态返回数据长度
{
if( CH374_READ_REGISTER(REG_USB_LENGTH) )
s = USB_INT_BUF_OVER; // 状态阶段错误
}
}
}
if( RetLen )
*RetLen = total;// 实际成功收发的总长度
return s;
}
/**
*@Name:SetUsbAddress
*@Describe:设置USB设备地址
*@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设备地址
s = HostCtrlTransfer374( BufSetAddr, NULL, NULL );// 执行控制传输
if (s == USB_INT_SUCCESS)
{
SetHostUsbAddr(addr);// 设置USB主机当前操作的USB设备地址
}
delay_us(3000);// 等待USB设备完成操作
return(s);
}
/**
*@Name:GetDeviceDescr
*@Describe:设置USB设备配置
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-20
**/
u8 SetUsbConfig(u8 cfg )
{
u8 BufSetCfg[ sizeof( SetupSetUsbConfig ) ] ;
memcpy ( BufSetCfg, SetupSetUsbConfig, sizeof( SetupSetUsbConfig ) );
((PUSB_SETUP_REQ)BufSetCfg )-> wValueL = cfg;// USB设备配置
return(HostCtrlTransfer374(BufSetCfg,NULL, NULL )); // 执行控制传输
}
/**
*@Name:GetDeviceDescr
*@Describe:获取设备描述符
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-20
**/
u8 GetDeviceDescr(u8 *buf )
{
u8 s,len;
s = HostCtrlTransfer374((u8 *)SetupGetDevDescr,buf,&len );// 执行控制传输
if ( s == USB_INT_SUCCESS )
{
UsbDevEndpSize = ((PUSB_DEV_DESCR)buf) -> bMaxPacketSize0; // 端点0最大包长度,这是简化处理,正常应该先获取前8字节后立即更新UsbDevEndpSize再继续
if( len < ((PUSB_SETUP_REQ)SetupGetDevDescr) -> wLengthL ) s = USB_INT_BUF_OVER; // 描述符长度错误
}
return(s);
}
/**
*@Name:GetConfigDescr
*@Describe:获取配置描述符
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-20
**/
u8 GetConfigDescr(u8 *buf)
{
u8 s,len,i,c,j;
u8 BufLogDescr[sizeof(SetupGetCfgDescr)] ;
s = HostCtrlTransfer374((u8*)SetupGetCfgDescr,buf,&len ); // 执行控制传输
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; // 返回长度错误
}
else
{
memcpy(BufLogDescr,SetupGetCfgDescr,sizeof( SetupGetCfgDescr));
((PUSB_SETUP_REQ)BufLogDescr ) -> wLengthL = ((PUSB_CFG_DESCR)buf) -> wTotalLengthL; // 完整配置描述符的总长度
s = HostCtrlTransfer374(BufLogDescr,buf,&len); // 执行控制传输
if(s == USB_INT_SUCCESS )
{
//简单分析配置描述符,获取端点地址,这里只处理一个端点的情况
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]; //获取报告描述符的长度
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的鼠标、键盘
{
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];//判断是否为中断端点
if(c & 0x80)
endp_in_addr = (c&0x0f);// IN端点的地址
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:设置IDLE
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-21
**/
u8 SetIdle(void)//设置IDLE
{
u8 s;
s = HostCtrlTransfer374(SetupSetidle,NULL,NULL);
return s;
}
/**
*@Name:GetHidDes
*@Describe:获取报表描述符
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@Date:2017-02-21
**/
u8 GetHidDes(u8 *p)//获取报表描述符
{
u8 s;
u8 buffer[8];
//leng=SetupGetHidDes[0x06]-0x40;//报表描述符的长度在发送数据长度的基础上减去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:返回是否获取设备描述符成功
*@Date:2017-02-21
**/
u8 SetReport(u8 *p)
{
u8 s,l=1;
s = HostCtrlTransfer374(SetupSetReport,p,&l);//实际的数据可以写别的数据,这个你可以用计算机抓下数据在发下去
return s;
}
/**
*@Name:SetReport
*@Describe:通过中断端点获取鼠标、键盘上传的数据
*@Output:Not
*@Input:返回是否获取设备描述符成功
*@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数据 01 09 00 1000
if(s != USB_INT_SUCCESS )
{
//delay_us(5000);
OSTimeDly(3); //延时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设备初始化,枚举
*@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];//由于报告描述符大小不定,缓冲区的大小最好定义大些
Init374Host();// 初始化USB主机
while(1)
{
SetHostLeisure();//设定USB主机空闲
while(1)
{
if (Query374Interrupt()) HostDetectInterrupt(); // 如果有USB主机中断则处理
if (Query374DeviceIn()) break; // 有USB设备
OSTimeDly(5); //100ms
}
OSTimeDly(14); //延时14*20ms = 280ms // 由于USB设备刚插入尚未稳定,故等待USB设备数百毫秒,消除插拔抖动
if(Query374Interrupt()) HostDetectInterrupt(); // 如果有USB主机中断则处理
HostSetReset();// USB总线复位
for(i=0;i<100;i++ )// 等待USB设备复位后重新连接
{
if(Query374DeviceIn()) break; // 有USB设备
delay_us(1000);
}
if(Query374Interrupt()) HostDetectInterrupt( ); // 如果有USB主机中断则处理
if(Query374DeviceIn())// 有USB设备
{
if(Query374DevFullSpeed())
{
HostSetFullSpeed();// 检测到全速USB设备
// printf("全速USB设备插入:\r\n");
printf("Full-Speed Device\r\n");
}
else
{
HostSetLowSpeed();// 检测到低速USB设备
//printf("低速USB设备插入:\r\n");
printf("Low-Speed Device\r\n");
}
}
else
{
continue;// 设备已经断开,继续等待
}
OSTimeDly(3); //延时3*20ms = 60ms
close_bit_flag=0;//设备是否拔出
//1、获取设备描述符
s = GetDeviceDescr(DeviceDescribe_buf); // 获取设备描述符
if(s != USB_INT_SUCCESS )
{
printf("获取设备描述符失败\r\n");
goto WaitDeviceOut;// 终止操作,等待USB设备拔出
}
printf("设备描述符:");
for(i=0;i <((PUSB_SETUP_REQ)SetupGetDevDescr ) -> wLengthL;i++ )
printf("%02X ",DeviceDescribe_buf[i]);//输出描述符
printf( "\r\n" );
//2、设置USB设备地址
s = SetUsbAddress(0x02);// 设置USB设备地址
if(s != USB_INT_SUCCESS )
{
printf("设置USB设备地址错误\r\n");
goto WaitDeviceOut;// 终止操作,等待USB设备拔出
}
printf("设置USB设备地址0X02成功\r\n");
//3、获取配置描述符
s = GetConfigDescr(DeviceDescribe_buf); // 获取配置描述符
//printf("config_status=%02x\r\n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
printf("获取配置描述符错误\r\n");
goto WaitDeviceOut;// 终止操作,等待USB设备拔出
}
//4、设置USB设备配置
// 分析配置描述符,获取端点数据/各端点地址/各端点大小等,更新变量endp_addr和endp_size等
s = SetUsbConfig( ( (PUSB_CFG_DESCR)DeviceDescribe_buf ) -> bConfigurationValue ); // 设置USB设备配置
if ( s != USB_INT_SUCCESS )
{
printf("获取配置描述符错误\r\n");
goto WaitDeviceOut;// 终止操作,等待USB设备拔出
}
printf("设置USB设备配置成功\r\n");
//-------------------------以下进行HID类的简单操作-----------------------------------------------------------
//5、设置IDLE
s = SetIdle();//设置IDLE,这个步骤是按照HID类的协议来做的
if(s != USB_INT_SUCCESS)
{
if((s&0x0f) == USB_INT_RET_STALL) goto next_operate1; //返回STALL可能本身不支持
}
printf("设置IDLE成功\r\n");
next_operate1:
//6、获取报表描述符
s=GetHidDes(DeviceDescribe_buf);// 获取报表描述符
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("获取报表描述符描述符错误\r\n");
goto WaitDeviceOut;//出错退出
}
DeviceDescribe_buf[0]=0x01;
//设置报表
s = SetReport(DeviceDescribe_buf);//设置报表
if(s==USB_INT_SUCCESS)
{
printf("Set_Report success\r\n");
}
else //设置报告出错
{
if((s&0x0f) == USB_INT_RET_STALL) goto next_operate2; //返回STALL可能本身不支持
}
next_operate2:
// 下面开始读取数据 ( 实际在读取数据的时候,要先发送中断端点的令牌来读取数据,接着才能获取到数据 )
ReadDataFlag = 0; //开始取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)// 这个是为了知道设备拔出产生的中断状态
{
close_bit_flag=1;
break;
}
OSTimeDly(5); //100ms
}
//-------------------------------------------------------------------------------------------------------
WaitDeviceOut: // 等待USB设备拔出
printf( "Wait Device Out\r\n" );
if(close_bit_flag==0)//设备拔出
{
while(1)
{
if(Query374Interrupt()) HostDetectInterrupt( );// 如果有USB主机中断则处理
if(Query374DeviceIn() == FALSE ) break; // 没有USB设备
OSTimeDly(5); //100ms
}
}
OSTimeDly(5); //延时5*20ms = 100ms
}
}
//--------------------------------------------------------------------------------------
串口输出信息:
Low-Speed Device
设备描述符:12 01 10 01 00 00 00 08 D5 05 89 06 03 01 00 01 00 01
设置USB设备地址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
设置USB设备配置成功
设置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