沁恒CH583 USB 自定义HID调试记录
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                沁恒CH583 USB 自定义HID调试记录
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                使用USB HID主要是為了免驅,通過自定義USB HID可以利用USB口來做很多事,比如串口打印,串口升級都可以通過usb口來實現,這樣可以省去一個USB轉串口器件同時也不用裝驅動,如下實現可以通過usb hid進行自定義收發,類似串口自定義收發。
如下代碼基本都是基于沁恒EVT改造而來,
GitHub - iot-lorawan/ch58x_usbhid_custom: custom usb hid in ch58x
usb配置相關,該配置聲明了使用usb 自定義hid,
#include "CH58x_common.h" #define RepDataLoadLen 64#define DevEP0SIZE 0x40 // 設備描述符 /* Device Descriptor */ const UINT8 MyDevDescr[] = {0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, DevEP0SIZE,0x86, 0x1A, 0xE1, 0xE6,0x00, 0x01, 0x01, 0x02, 0x00, 0x01, };/* USB配置描述符(全速) */ UINT8 MyCfgDescr[ ] = {0x09,0x02,0x29,0x00,0x01,0x01,0x04,0xA0,0x23, //配置描述符0x09,0x04,0x00,0x00,0x02,0x03,0x00,0x00,0x05, //接口描述符0x09,0x21,0x00,0x01,0x00,0x01,0x22,0x22,0x00, //HID類描述符0x07,0x05,0x81,0x03,0x40,0x00,0x01, //端點描述符(全速間隔時間改成1ms)0x07,0x05,0x01,0x03,0x40,0x00,0x01, //端點描述符 };/* USB報告描述符 */ const UINT8 CompatibilityHIDRepDesc[ ] = {0x06, 0x00,0xff,0x09, 0x01,0xa1, 0x01, //集合開始0x09, 0x02, //Usage Page 用法0x15, 0x00, //Logical Minimun0x26, 0x00,0xff, //Logical Maximun0x75, 0x08, //Report Size0x95, RepDataLoadLen, //Report Counet0x81, 0x06, //Input0x09, 0x02, //Usage Page 用法0x15, 0x00, //Logical Minimun0x26, 0x00,0xff, //Logical Maximun0x75, 0x08, //Report Size0x95, RepDataLoadLen, //Report Counet0x91, 0x06, //Output0xC0 };/* Language Descriptor */ const UINT8 MyLangDescr[] = {0x04, 0x03, 0x09, 0x04 };/* Manufactor Descriptor */ const UINT8 MyManuInfo[] = {0x0E, 0x03, 'w', 0, 'c', 0, 'h', 0, '.', 0, 'c', 0, 'n', 0 };/* Product Information */ const UINT8 MyProdInfo[] = {0x0C, 0x03, 'C', 0, 'H', 0, '1', 0, '0', 0, 'x', 0 };/* USB序列號字符串描述符 */ const UINT8 MySerNumInfo[ ] = {/* 0123456789 */22,03,48,0,49,0,50,0,51,0,52,0,53,0,54,0,55,0,56,0,57,0 };/* USB設備限定描述符 */ const UINT8 MyUSBQUADesc[ ] = {0x0A, 0x06, 0x00, 0x02, 0xFF, 0x00, 0xFF, 0x40, 0x01, 0x00, };/**********************************************************/ uint8_t DevConfig, Ready; uint8_t SetupReqCode; uint16_t SetupReqLen; const uint8_t *pDescr; uint8_t Report_Value = 0x00; uint8_t Idle_Value = 0x00; uint8_t USB_SleepStatus = 0x00; /* USB睡眠狀態 *//*鼠標鍵盤數據*/ uint8_t HIDMouse[4] = {0x0, 0x0, 0x0, 0x0}; uint8_t HIDKey[8] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; /******** 用戶自定義分配端點RAM ****************************************/ __attribute__((aligned(4))) uint8_t EP0_Databuf[64 + 64 + 64]; //ep0(64)+ep4_out(64)+ep4_in(64) __attribute__((aligned(4))) uint8_t EP1_Databuf[64 + 64]; //ep1_out(64)+ep1_in(64) __attribute__((aligned(4))) uint8_t EP2_Databuf[64 + 64]; //ep2_out(64)+ep2_in(64) __attribute__((aligned(4))) uint8_t EP3_Databuf[64 + 64]; //ep3_out(64)+ep3_in(64)USB邏輯交互,放在usb中斷函數里執行
void USB_DevTransProcess(void) {uint8_t len, chtype;uint8_t intflag, errflag = 0;intflag = R8_USB_INT_FG;if(intflag & RB_UIF_TRANSFER){if((R8_USB_INT_ST & MASK_UIS_TOKEN) != MASK_UIS_TOKEN) // 非空閑{switch(R8_USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP))// 分析操作令牌和端點號{case UIS_TOKEN_IN:{switch(SetupReqCode){case USB_GET_DESCRIPTOR:len = SetupReqLen >= DevEP0SIZE ? DevEP0SIZE : SetupReqLen; // 本次傳輸長度memcpy(pEP0_DataBuf, pDescr, len); /* 加載上傳數據 */SetupReqLen -= len;pDescr += len;R8_UEP0_T_LEN = len;R8_UEP0_CTRL ^= RB_UEP_T_TOG; // 翻轉break;case USB_SET_ADDRESS:R8_USB_DEV_AD = (R8_USB_DEV_AD & RB_UDA_GP_BIT) | SetupReqLen;R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;break;case USB_SET_FEATURE:break;default:R8_UEP0_T_LEN = 0; // 狀態階段完成中斷或者是強制上傳0長度數據包結束控制傳輸R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;break;}}break;case UIS_TOKEN_OUT:{len = R8_USB_RX_LEN;if(SetupReqCode == 0x09){if(pEP0_DataBuf[0])PRINT("Light on Num Lock LED!\n");else if(pEP0_DataBuf[0] == 0)PRINT("Light off Num Lock LED!\n");}}break;case UIS_TOKEN_OUT | 1:{if(R8_USB_INT_ST & RB_UIS_TOG_OK){ // 不同步的數據包將丟棄R8_UEP1_CTRL ^= RB_UEP_R_TOG;len = R8_USB_RX_LEN;DevEP1_OUT_Deal(len);}}break;case UIS_TOKEN_IN | 1:R8_UEP1_CTRL ^= RB_UEP_T_TOG;R8_UEP1_CTRL = (R8_UEP1_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;break;case UIS_TOKEN_OUT | 2:{if(R8_USB_INT_ST & RB_UIS_TOG_OK){ // 不同步的數據包將丟棄R8_UEP2_CTRL ^= RB_UEP_R_TOG;len = R8_USB_RX_LEN;DevEP2_OUT_Deal(len);}}break;case UIS_TOKEN_IN | 2:R8_UEP2_CTRL ^= RB_UEP_T_TOG;R8_UEP2_CTRL = (R8_UEP2_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;break;case UIS_TOKEN_OUT | 3:{if(R8_USB_INT_ST & RB_UIS_TOG_OK){ // 不同步的數據包將丟棄R8_UEP3_CTRL ^= RB_UEP_R_TOG;len = R8_USB_RX_LEN;DevEP3_OUT_Deal(len);}}break;case UIS_TOKEN_IN | 3:R8_UEP3_CTRL ^= RB_UEP_T_TOG;R8_UEP3_CTRL = (R8_UEP3_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;break;case UIS_TOKEN_OUT | 4:{if(R8_USB_INT_ST & RB_UIS_TOG_OK){R8_UEP4_CTRL ^= RB_UEP_R_TOG;len = R8_USB_RX_LEN;DevEP4_OUT_Deal(len);}}break;case UIS_TOKEN_IN | 4:R8_UEP4_CTRL ^= RB_UEP_T_TOG;R8_UEP4_CTRL = (R8_UEP4_CTRL & ~MASK_UEP_T_RES) | UEP_T_RES_NAK;break;default:break;}R8_USB_INT_FG = RB_UIF_TRANSFER;}if(R8_USB_INT_ST & RB_UIS_SETUP_ACT) // Setup包處理{R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_NAK;SetupReqLen = pSetupReqPak->wLength;SetupReqCode = pSetupReqPak->bRequest;chtype = pSetupReqPak->bRequestType;len = 0;errflag = 0;if((pSetupReqPak->bRequestType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD){/* 非標準請求 *//* 其它請求,如類請求,產商請求等 */if(pSetupReqPak->bRequestType & 0x40){/* 廠商請求 */}else if(pSetupReqPak->bRequestType & 0x20){switch(SetupReqCode){case DEF_USB_SET_IDLE: /* 0x0A: SET_IDLE */Idle_Value = EP0_Databuf[3];break; //這個一定要有case DEF_USB_SET_REPORT: /* 0x09: SET_REPORT */break;case DEF_USB_SET_PROTOCOL: /* 0x0B: SET_PROTOCOL */Report_Value = EP0_Databuf[2];break;case DEF_USB_GET_IDLE: /* 0x02: GET_IDLE */EP0_Databuf[0] = Idle_Value;len = 1;break;case DEF_USB_GET_PROTOCOL: /* 0x03: GET_PROTOCOL */EP0_Databuf[0] = Report_Value;len = 1;break;default:errflag = 0xFF;}}}else /* 標準請求 */{switch(SetupReqCode){case USB_GET_DESCRIPTOR:{switch(((pSetupReqPak->wValue) >> 8)){case USB_DESCR_TYP_DEVICE:/* 獲取設備描述符 */pDescr = MyDevDescr;len = MyDevDescr[0];break;case USB_DESCR_TYP_CONFIG:/* 獲取配置描述符 */pDescr = MyCfgDescr;len = sizeof( MyCfgDescr );break;case USB_DESCR_TYP_STRING:/* 獲取字符串描述符 */switch( (pSetupReqPak->wValue)&0xff ){case 0:/* 語言字符串描述符 */pDescr = MyLangDescr;len = MyLangDescr[0];break;case 1:/* USB產商字符串描述符 */pDescr = MyManuInfo;len = MyManuInfo[0];break;case 2:/* USB產品字符串描述符 */pDescr = MyProdInfo;len = MyProdInfo[0];break;case 3:/* USB序列號字符串描述符 */pDescr = MySerNumInfo;len = sizeof( MySerNumInfo );break;default:errflag = 0xFF;break;}break;case USB_DESCR_TYP_REPORT:/* USB設備報告描述符 */pDescr = CompatibilityHIDRepDesc;len = sizeof( CompatibilityHIDRepDesc );break;case USB_DESCR_TYP_QUALIF:/* 設備限定描述符 */pDescr = ( PUINT8 )&MyUSBQUADesc[ 0 ];len = sizeof( MyUSBQUADesc );break;case USB_DESCR_TYP_SPEED:/* 其他速度配置描述符 */errflag = 0xFF;break;default :errflag = 0xff;break;}if(SetupReqLen > len)SetupReqLen = len; //實際需上傳總長度len = (SetupReqLen >= DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;memcpy(pEP0_DataBuf, pDescr, len);pDescr += len;}break;case USB_SET_ADDRESS:SetupReqLen = (pSetupReqPak->wValue) & 0xff;break;case USB_GET_CONFIGURATION:pEP0_DataBuf[0] = DevConfig;if(SetupReqLen > 1)SetupReqLen = 1;break;case USB_SET_CONFIGURATION:DevConfig = (pSetupReqPak->wValue) & 0xff;break;case USB_CLEAR_FEATURE:{if((pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) // 端點{switch((pSetupReqPak->wIndex) & 0xff){case 0x83:R8_UEP3_CTRL = (R8_UEP3_CTRL & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK;break;case 0x03:R8_UEP3_CTRL = (R8_UEP3_CTRL & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK;break;case 0x82:R8_UEP2_CTRL = (R8_UEP2_CTRL & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK;break;case 0x02:R8_UEP2_CTRL = (R8_UEP2_CTRL & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK;break;case 0x81:R8_UEP1_CTRL = (R8_UEP1_CTRL & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_NAK;break;case 0x01:R8_UEP1_CTRL = (R8_UEP1_CTRL & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_ACK;break;default:errflag = 0xFF; // 不支持的端點break;}}else if((pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE){if(pSetupReqPak->wValue == 1){USB_SleepStatus &= ~0x01;}}else{errflag = 0xFF;}}break;case USB_SET_FEATURE:if((pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP){/* 端點 */switch(pSetupReqPak->wIndex){case 0x83:R8_UEP3_CTRL = (R8_UEP3_CTRL & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_STALL;break;case 0x03:R8_UEP3_CTRL = (R8_UEP3_CTRL & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_STALL;break;case 0x82:R8_UEP2_CTRL = (R8_UEP2_CTRL & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_STALL;break;case 0x02:R8_UEP2_CTRL = (R8_UEP2_CTRL & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_STALL;break;case 0x81:R8_UEP1_CTRL = (R8_UEP1_CTRL & ~(RB_UEP_T_TOG | MASK_UEP_T_RES)) | UEP_T_RES_STALL;break;case 0x01:R8_UEP1_CTRL = (R8_UEP1_CTRL & ~(RB_UEP_R_TOG | MASK_UEP_R_RES)) | UEP_R_RES_STALL;break;default:/* 不支持的端點 */errflag = 0xFF; // 不支持的端點break;}}else if((pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE){if(pSetupReqPak->wValue == 1){/* 設置睡眠 */USB_SleepStatus |= 0x01;}}else{errflag = 0xFF;}break;case USB_GET_INTERFACE:pEP0_DataBuf[0] = 0x00;if(SetupReqLen > 1)SetupReqLen = 1;break;case USB_SET_INTERFACE:break;case USB_GET_STATUS:if((pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP){/* 端點 */pEP0_DataBuf[0] = 0x00;switch(pSetupReqPak->wIndex){case 0x83:if((R8_UEP3_CTRL & (RB_UEP_T_TOG | MASK_UEP_T_RES)) == UEP_T_RES_STALL){pEP0_DataBuf[0] = 0x01;}break;case 0x03:if((R8_UEP3_CTRL & (RB_UEP_R_TOG | MASK_UEP_R_RES)) == UEP_R_RES_STALL){pEP0_DataBuf[0] = 0x01;}break;case 0x82:if((R8_UEP2_CTRL & (RB_UEP_T_TOG | MASK_UEP_T_RES)) == UEP_T_RES_STALL){pEP0_DataBuf[0] = 0x01;}break;case 0x02:if((R8_UEP2_CTRL & (RB_UEP_R_TOG | MASK_UEP_R_RES)) == UEP_R_RES_STALL){pEP0_DataBuf[0] = 0x01;}break;case 0x81:if((R8_UEP1_CTRL & (RB_UEP_T_TOG | MASK_UEP_T_RES)) == UEP_T_RES_STALL){pEP0_DataBuf[0] = 0x01;}break;case 0x01:if((R8_UEP1_CTRL & (RB_UEP_R_TOG | MASK_UEP_R_RES)) == UEP_R_RES_STALL){pEP0_DataBuf[0] = 0x01;}break;}}else if((pSetupReqPak->bRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE){pEP0_DataBuf[0] = 0x00;if(USB_SleepStatus){pEP0_DataBuf[0] = 0x02;}else{pEP0_DataBuf[0] = 0x00;}}pEP0_DataBuf[1] = 0;if(SetupReqLen >= 2){SetupReqLen = 2;}break;default:errflag = 0xff;break;}}if(errflag == 0xff) // 錯誤或不支持{// SetupReqCode = 0xFF;R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL; // STALL}else{if(chtype & 0x80) // 上傳{len = (SetupReqLen > DevEP0SIZE) ? DevEP0SIZE : SetupReqLen;SetupReqLen -= len;}elselen = 0; // 下傳R8_UEP0_T_LEN = len;R8_UEP0_CTRL = RB_UEP_R_TOG | RB_UEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; // 默認數據包是DATA1}R8_USB_INT_FG = RB_UIF_TRANSFER;}}else if(intflag & RB_UIF_BUS_RST){R8_USB_DEV_AD = 0;R8_UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;R8_UEP1_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;R8_UEP2_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;R8_UEP3_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK;R8_USB_INT_FG = RB_UIF_BUS_RST;}else if(intflag & RB_UIF_SUSPEND){if(R8_USB_MIS_ST & RB_UMS_SUSPEND){;} // 掛起else{;} // 喚醒R8_USB_INT_FG = RB_UIF_SUSPEND;}else{R8_USB_INT_FG = intflag;} }__INTERRUPT __HIGH_CODE void USB_IRQHandler(void) /* USB中斷服務程序,使用寄存器組1 */ {USB_DevTransProcess(); }USB端點收發部分接口,IN OUT都是從host端即電腦端而言
/********************************************************************** @fn DevEP1_OUT_Deal** @brief 端點1數據處理** @return none*/ void DevEP1_OUT_Deal(uint8_t l) { /* 用戶可自定義 */uint8_t i;for(i = 0; i < l; i++){pEP1_IN_DataBuf[i] = pEP1_OUT_DataBuf[i];}DevEP1_IN_Deal(l);PRINT("DevEP1_OUT_Deal:%d\r\n",l); }/********************************************************************** @fn DevEP2_OUT_Deal** @brief 端點2數據處理** @return none*/ void DevEP2_OUT_Deal(uint8_t l) { /* 用戶可自定義 */uint8_t i;PRINT("DevEP2_OUT_Deal:%d\r\n",l);for(i = 0; i < l; i++){pEP2_IN_DataBuf[i] = pEP2_OUT_DataBuf[i];}DevEP2_IN_Deal(l); }/********************************************************************** @fn DevEP3_OUT_Deal** @brief 端點3數據處理** @return none*/ void DevEP3_OUT_Deal(uint8_t l) { /* 用戶可自定義 */uint8_t i;PRINT("DevEP3_OUT_Deal:%d\r\n",l);for(i = 0; i < l; i++){pEP3_IN_DataBuf[i] = pEP3_OUT_DataBuf[i];}DevEP3_IN_Deal(l); }/********************************************************************** @fn DevEP4_OUT_Deal** @brief 端點4數據處理** @return none*/ void DevEP4_OUT_Deal(uint8_t l) { /* 用戶可自定義 */uint8_t i;PRINT("DevEP4_OUT_Deal:%d\r\n",l);for(i = 0; i < l; i++){pEP4_IN_DataBuf[i] = pEP4_OUT_DataBuf[i];}DevEP4_IN_Deal(l); }主函數:
int main() {SetSysClock(CLK_SOURCE_PLL_60MHz);DebugInit();PRINT("start\n");pEP0_RAM_Addr = EP0_Databuf;pEP1_RAM_Addr = EP1_Databuf;pEP2_RAM_Addr = EP2_Databuf;pEP3_RAM_Addr = EP3_Databuf;USB_DeviceInit();PFIC_EnableIRQ(USB_IRQn);while(1){mDelaymS(100);#if 0uint8_t i;for(i = 0; i < 64; i++){pEP1_IN_DataBuf[i] = 0x30+i;}DevEP1_IN_Deal(64);#endif} }使用usb hid收發助手調試
總結
以上是生活随笔為你收集整理的沁恒CH583 USB 自定义HID调试记录的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: linux yum安装xz,CentOS
- 下一篇: laravel 隐藏入口文件
