?? ch374_hid.c
字號:
/* 設定全速USB設備運行環境 */
void HostSetFullSpeed( void )
{
Write374Byte( REG_USB_SETUP, Read374Byte( REG_USB_SETUP ) & ~ BIT_SETP_USB_SPEED | BIT_SETP_AUTO_SOF ); // 全速且發SOF
mDelaymS( 1 );
}
/* 設定低速USB設備運行環境 */
void HostSetLowSpeed( void )
{
Write374Byte( REG_USB_SETUP, Read374Byte( REG_USB_SETUP ) | BIT_SETP_USB_SPEED | BIT_SETP_AUTO_SOF ); // 低速且發SOF
mDelaymS( 1 );
}
/* 初始化USB主機 */
void Init374Host( void )
{
Write374Byte( REG_USB_SETUP, 0x00 );
SetHostUsbAddr( 0x00 );
Write374Byte( REG_USB_H_CTRL, 0x00 );
Write374Byte( REG_INTER_FLAG, BIT_IF_USB_PAUSE | BIT_IF_INTER_FLAG ); // 清所有中斷標志
// Write374Byte( REG_INTER_EN, BIT_IE_TRANSFER ); // 允許傳輸完成中斷,因為本程序使用查詢方式檢測USB設備插拔,所以無需USB設備檢測中斷
Write374Byte( REG_INTER_EN, BIT_IE_TRANSFER | BIT_IE_DEV_DETECT ); // 允許傳輸完成中斷和USB設備檢測中斷
Write374Byte( REG_SYS_CTRL, BIT_CTRL_OE_POLAR ); // 對于CH374T或者UEN引腳懸空的CH374S必須置BIT_CTRL_OE_POLAR為1
HostSetBusFree( ); // USB總線空閑
}
/* 獲取設備描述符 */
UINT8 GetDeviceDescr( PUINT8 buf )
{
UINT8 s, len;
s = HostCtrlTransfer374( 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 );
}
/* 獲取配置描述符 */
UINT8 GetConfigDescr( PUINT8 buf )
{
UINT8 s, len,i,c,j;
UINT8 BufLogDescr[ sizeof( SetupGetCfgDescr ) ] ;
s = HostCtrlTransfer374( 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 )
{
//簡單分析配置描述符,獲取端點地址,這里只處理一個端點的情況
for ( i = 0; i < ( (PUSB_CFG_DESCR)buf ) -> wTotalLengthL; i ++ ) printf( "%02X ", (UINT16)( buf[i] ) ); //配置描述符
printf( "\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]; //獲取報告描述符的長度
}
printf("hid_des_leng=%02x\n",(unsigned short)hid_des_leng);
endp_out_addr=endp_in_addr=0;endp_num=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 // OUT端點
{
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\n",(unsigned short)endp_in_addr);
printf("endp_out_addr=%02x\n",(unsigned short)endp_out_addr);
}
}
}
return( s );
}
/* 設置USB設備地址 */
UINT8 SetUsbAddress( UINT8 addr )
{
UINT8 s;
UINT8 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設備地址
}
mDelaymS( 3 ); // 等待USB設備完成操作
return( s );
}
/* 設置USB設備配置 */
UINT8 SetUsbConfig( UINT8 cfg )
{
UINT8 BufSetCfg[ sizeof( SetupSetUsbConfig ) ] ;
memcpy ( BufSetCfg, SetupSetUsbConfig, sizeof( SetupSetUsbConfig ) );
( (PUSB_SETUP_REQ)BufSetCfg ) -> wValueL = cfg; // USB設備配置
return( HostCtrlTransfer374( BufSetCfg, NULL, NULL ) ); // 執行控制傳輸
}
/* 設置Idle */
UINT8 Set_Idle( )
{
UINT8 s;
s=HostCtrlTransfer374(SetupSetidle,NULL,NULL);
return s;
}
/* 獲取報表描述符 */
unsigned char Get_Hid_Des(unsigned char *p)//獲取報表描述符
{
unsigned char s;
// leng=SetupGetHidDes[0x06]-0x40;//報表描述符的長度在發送數據長度的基礎上減去0X40
unsigned char buffer[8];
memcpy ( buffer, SetupGetHidDes, 8 );
buffer[0x06] = hid_des_leng+0x40;
s=HostCtrlTransfer374(buffer,p,&buffer[0x06]);
return s;
}
/* 設置報表 */
UINT8 Set_Report(unsigned char *p)
{
UINT8 s,l=1;
s=HostCtrlTransfer374(SetupSetReport,p,&l); //實際的數據可以寫別的數據,這個你可以用計算機抓下數據在發下去
return s;
}
/* 為printf和getkey輸入輸出初始化串口 */
void mInitSTDIO( )
{
SCON = 0x50;
PCON = 0x80;
TMOD = 0x20;
TH1 = 0xf3; //24MHZ, 9600
TR1 = 1;
TI = 1;
}
int main( void )
{
UINT8 i, s,close_bit_flag=0;
UINT8 idata buf[80]; //由于報告描述符大小不定,緩沖區的大小最好定義大些
// P1&=0xF8; // 如果在U盤文件讀寫模塊上試用本程序必須加上本行
AUXR |= 0x02;
mDelaymS( 50 ); // 等待CH374復位完成
CH374_PORT_INIT( ); // CH374接口初始化
mInitSTDIO( ); // 為了讓計算機通過串口監控演示過程
for(i=0;i!=64;i++)
{
s=Read374Byte(i);
printf("%02x ",(unsigned short)s);
}
printf("\n");
printf( "Start CH374 Host\n" );
Init374Host( ); // 初始化USB主機
while ( 1 )
{
HostSetBusFree( ); // 設定USB主機空閑
while ( 1 )
{
if ( Query374Interrupt( ) ) HostDetectInterrupt( ); // 如果有USB主機中斷則處理
if ( Query374DeviceIn( ) ) break; // 有USB設備
}
mDelaymS( 250 ); // 由于USB設備剛插入尚未穩定,故等待USB設備數百毫秒,消除插拔抖動
if ( Query374Interrupt( ) ) HostDetectInterrupt( ); // 如果有USB主機中斷則處理
printf( "Reset Device\n" );
HostSetBusReset( ); // USB總線復位
for ( i = 0; i < 100; i ++ ) // 等待USB設備復位后重新連接
{
if ( Query374DeviceIn( ) ) break; // 有USB設備
mDelaymS( 1 );
}
if ( Query374Interrupt( ) ) HostDetectInterrupt( ); // 如果有USB主機中斷則處理
if ( Query374DeviceIn( ) ) // 有USB設備
{
if ( Query374DevFullSpeed( ) )
{
printf( "Start Full-Speed Device\n" );
HostSetFullSpeed( ); // 檢測到全速USB設備
}
else
{
printf( "Start Low-Speed Device\n" );
HostSetLowSpeed( ); // 檢測到低速USB設備
LOW_SPEED_BIT=1;
}
}
else
{
continue; // 設備已經斷開,繼續等待
}
mDelaymS( 50 );
close_bit_flag=0;
printf( "GetDeviceDescr: " );
s = GetDeviceDescr( buf ); // 獲取設備描述符
printf("device_status=%02x \n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
goto WaitDeviceOut; // 終止操作,等待USB設備拔出
}
for ( i = 0; i < ( (PUSB_SETUP_REQ)SetupGetDevDescr ) -> wLengthL; i ++ ) printf( "%02X ", (UINT16)( buf[i] ) );
printf( "\n" );
s = SetUsbAddress( 0x02 ); // 設置USB設備地址
printf("address_status=%02x\n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
goto WaitDeviceOut; // 終止操作,等待USB設備拔出
}
s = GetConfigDescr( buf ); // 獲取配置描述符
printf("config_status=%02x\n",(unsigned short)s);
if ( s != USB_INT_SUCCESS )
{
goto WaitDeviceOut; // 終止操作,等待USB設備拔出
}
// 分析配置描述符,獲取端點數據/各端點地址/各端點大小等,更新變量endp_addr和endp_size等
s = SetUsbConfig( ( (PUSB_CFG_DESCR)buf ) -> bConfigurationValue ); // 設置USB設備配置
if ( s != USB_INT_SUCCESS )
{
// printf( "ERROR = %02X\n", (UINT16)s );
goto WaitDeviceOut; // 終止操作,等待USB設備拔出
}
else printf( "SetUsbConfig_success\n" );
//-------------------------以下進行HID類的簡單操作-----------------------------------------------------------
printf("Set_Idle\n");
s=Set_Idle( ); //設置IDLE,這個步驟是按照HID類的協議來做的
if(s!=USB_INT_SUCCESS)
{
printf("Set_Idle_Err=%02x\n",(unsigned short)s);
if(s&0x0f==USB_INT_RET_STALL) goto next_operate1; //返回STALL可能本身不支持
}
else printf("Set_idle success\n");
next_operate1:
printf("Get_Hid_Des\n");
s=Get_Hid_Des(buf); // 獲取報表描述符描述符
if(s==USB_INT_SUCCESS)
{
printf("HID_Desc: ");
for(i=0;i!=hid_des_leng;i++) printf("%02x ",(unsigned short)buf[i]);
printf("\n");
}
else
{
goto WaitDeviceOut; //出錯退出
}
printf("Set_Report \n"); //對于鍵盤發Set_Report來點亮燈,對于鼠標則不需要這一步
buf[0]=0x01;
s=Set_Report(buf); //設置報表
if(s==USB_INT_SUCCESS)
{
printf("Set_Report success\n");
}
else
{
printf("Set_Report Err=%02x\n",(unsigned short)s); //設置報告出錯
if(s&0x0f==USB_INT_RET_STALL) goto next_operate2; //返回STALL可能本身不支持
}
next_operate2:
// 下面開始讀取數據 ( 實際在讀取數據的時候,要先發送中斷端點的令牌來讀取數據,接著才能獲取到數據 )
tog1=FALSE; //開始取DATA0
while(1)
{
s=Interrupt_Data_Trans(buf);
// printf("s:%x \n",(unsigned short)s);
if(s==USB_INT_SUCCESS)
{
for(i=0;i!=8;i++) printf("%02x ",(unsigned short)buf[i]);
printf("\n");
}
else if(s==USB_INT_DISCONNECT) // 這個是為了知道設備拔出產生的中斷狀態
{
close_bit_flag=1;
break;
}
}
WaitDeviceOut: // 等待USB設備拔出
printf( "Wait Device Out\n" );
if(close_bit_flag==0){
while ( 1 )
{
if ( Query374Interrupt( ) ) HostDetectInterrupt( ); // 如果有USB主機中斷則處理
if ( Query374DeviceIn( ) == FALSE ) break; // 沒有USB設備
}
}
mDelaymS( 100 ); // 等待設備完全斷開,消除插拔抖動
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -