我的芯片用的是CH549L,注冊(cè)成HID設(shè)備下的第0x0C項(xiàng)consumer類型應(yīng)用。目的是通過(guò)旋鈕調(diào)節(jié)電腦音量。
正常使用都沒有問(wèn)題。但是有一個(gè)BUG是,部分時(shí)候電腦關(guān)機(jī)以后重啟,這時(shí)候設(shè)備就不能工作了,必須要重新插拔一下HID設(shè)備才行。
通過(guò)大量測(cè)試后初步判斷,是因?yàn)殡娔X重啟時(shí),整個(gè)過(guò)程中電腦的USB口沒有斷電,以至于重新開機(jī)以后,HID設(shè)備并沒有重啟。電腦這邊枚舉的USB設(shè)備的數(shù)據(jù)已經(jīng)清空了,但是我這個(gè)HID設(shè)備卻還記著之前枚舉的信息,這時(shí)候電腦沒有檢測(cè)到重新插入的USB設(shè)備的信號(hào),就不會(huì)自動(dòng)的重新枚舉。導(dǎo)致舊的信息不能用了,以至于失效。
我嘗試了一個(gè)簡(jiǎn)單的辦法,就是人工判斷設(shè)備失效以后,按一下一下我的板上的一個(gè)按鈕,然后在程序里直接goto到程序的最開始,直接重新初始化,但是不能夠解決這個(gè)問(wèn)題。
所以我想問(wèn)問(wèn),有沒有什么能夠檢測(cè)到USB通信失效了的變量啊之類的?還有檢測(cè)到失效以后,又如何通過(guò)軟件重新讓電腦枚舉我的設(shè)備?
----------------------------
我的代碼主要修改自給的demo代碼里面的“CompositeKM.C”文件。上面附上我的描述符,USB中斷服務(wù)函數(shù)沒敢改。
/*設(shè)備描述符*/
UINT8C DevDesc[] = {
? ? 0x12, ?// bLength。描述符長(zhǎng)度(18字節(jié),十六進(jìn)制為0x12),就是標(biāo)志描述符數(shù)據(jù)結(jié)構(gòu)的長(zhǎng)度。
? ? 0x01, ?// bDescriptorType。描述符類型。0x01為設(shè)備描述符
? ? 0x00,0x02, ?// bcdUSB。設(shè)備使用的USB協(xié)議版本。表示形式0xJJMN版本JJ.M.N(JJ-主要版本號(hào),M-次要版本號(hào),N-次要版本)。
? ? ? ? ? ? ? ? // 例子:如果是USB2.0,寫成:0200H。如果是USB1.1,寫成。0110H 如果是USB3.11,寫成:0311H。
? ? ? ? ? ? ? ? // 注意是小端模式,所以低字節(jié)寫在前面
? ? 0x00, ?// bDeviceClass。類代碼。表示設(shè)備類型。為0時(shí)指示用接口描述符來(lái)標(biāo)識(shí)類別。詳見https://www.usb.org/defined-class-codes
? ? 0x00, ?// bDeviceSubClass。子類型。
? ? 0x00, ?// bDeviceProtocol。設(shè)備使用的協(xié)議。
? ? THIS_ENDP0_SIZE, ?// bMaxPackeSize0。端點(diǎn)一次最大傳多少個(gè)字節(jié)。
? ? 0x86,0x1a, ?// idVender。廠商ID。
? ? 0xe1,0xe6, ?// idProduct。產(chǎn)品ID。
? ? 0x00,0x01, ?// bcdDevice。產(chǎn)品版本號(hào)。
? ? 0x01, ?// iManufacturer。描述廠商的字符串的索引。
? ? 0x02, ?// iProduct。描述產(chǎn)品的字符串的索引。
? ? 0x00, ?// iSerialNumber。描述產(chǎn)品序列號(hào)字符串的索引.
? ? 0x01 ?// bNumConfigurations。指示設(shè)備有多少個(gè)配置
? ? };
/*字符串描述符*/
// 語(yǔ)言ID描述符
UINT8C ?MyLangDescr[] = {
? ? 0x04, ?// bLength。描述符長(zhǎng)度。
? ? 0x03, ?// bDescriptorType。描述符類型。語(yǔ)言ID描述符也是字符串描述符,類型為0x03。
? ? 0x09, 0x04 ?// wLANGID[0]。要支持的語(yǔ)言ID號(hào)。
? ? // wLANGID[n]。有可能會(huì)支持多種語(yǔ)言。但是這里沒寫了。
? ? };
// 廠家信息描述符
UINT8C ?MyManuInfo[] = {
? ? 0x0E, ?// bLength。描述符長(zhǎng)度。
? ? 0x03, ?// bDescriptorType。描述符類型。字符串描述符類型為0x03。
? ? 'C', 0, 'S', 0, 'Y', 0, '.', 0, 'U', 0, 'S', 0, 'B', 0 ?// bString。UNICODE編碼的字符串。
? ? };
// 產(chǎn)品信息描述符
UINT8C ?MyProdInfo[] = {
? ? 0x0C, ?// bLength。描述符長(zhǎng)度。
? ? 0x03, ?// bDescriptorType。描述符類型。字符串描述符類型為0x03。
? ? 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0 ?// bString。UNICODE編碼的字符串。
? ? };
/*HID類報(bào)表描述符*/
UINT8C ConsumerRepDesc[] =
{
? ? 0x05,0x0C, ?// Usage Page (Consumer)
? ? 0x09,0x01, ?// Usage(Consumer Control)
? ? 0xA1,0x01, ?// Collection (Application), ? ? ? ? ? ? ? ?Main Items —— Collection —— Application
? ? ? ? 0x15,0x00, ?// Logical Minimum (0), ? ? ? ? ? ? ? ? ? ? Global Items —— Logical Minimum —— 0
? ? ? ? 0x25,0x01, ?// Logical Maximum (1), ? ? ? ? ? ? ? ? ? ? Global Items —— Logical Maximum —— 1
? ? ? ? 0x75,0x01, ?// Report Size (1), ? ? ? ? ? ? ? ? ? ? ? ? Global Items —— Report Size —— 1
? ? ? ? 0x95,0x01, ?// Report Count (1), ? ? ? ? ? ? ? ? ? ? ? ?Global Items —— Report Count —— 1
? ? ? ? 0x09,0xCD, ?// Usage(Play/Pause),開始暫停
? ? ? ? 0x81,0x06, ?// Input (Data, Value, Relative),
? ? ? ? 0x09,0xB5, ?// Usage(Scan Next Track),下一曲
? ? ? ? 0x81,0x06, ?// Input (Data, Value, Relative),
? ? ? ? 0x09,0xB6, ?// Usage(Scan Previous Track),上一曲
? ? ? ? 0x81,0x06, ?// Input (Data, Value, Relative),
? ? ? ? 0x09,0xE2, ?// Usage(Mute),靜音
? ? ? ? 0x81,0x06, ?// Input (Data, Value, Relative),
? ? ? ? 0x09,0xE9, ?// Usage(Volume Increment),音量+
? ? ? ? 0x81,0x06, ?// Input (Data, Value, Relative),
? ? ? ? 0x09,0xEA, ?// Usage(Volume Decrement),音量-
? ? ? ? 0x81,0x06, ?// Input (Data, Value, Relative),
? ? ? ? 0x09,0xB3, ?// Usage(Fast Forward),快進(jìn)
? ? ? ? 0x81,0x02, ?// Input (Data, Value, Absolute),
? ? ? ? 0x09,0xB4, ?// Usage(Rewind),倒帶
? ? ? ? 0x81,0x02, ?// Input (Data, Value, Absolute),
? ? 0xC0 ?// End Collection, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Main Items —— End Collection
};
/*配置描述符集合(必須按照順序)*/
UINT8C CfgDesc[] =
{
? ? // 標(biāo)準(zhǔn)配置描述符
? ? 0x09, ?// bLength。配置本描述符的長(zhǎng)度。
? ? 0x02, ?// bDescriptorType。描述符類型。配置描述符為0x02。
? ? 0x3b,0x00, ?// wTotalLength。配置描述符集合總長(zhǎng)度。
? ? 0x01, ?// bNumInterfaces。當(dāng)前配置下面有多少個(gè)接口。
? ? 0x01, ?// bConfigurationValue。當(dāng)前配置的標(biāo)識(shí)。一個(gè)USB設(shè)備可能有多個(gè)配置,但是當(dāng)前只能選擇一種配置。
? ? 0x00, ?// iConfiguration。描述該配置的字符串的索引值。如果沒有字符串,那這個(gè)值就是0。
? ? 0xE0, ?// bmAttributes。在這個(gè)配置下,設(shè)備的一些特性。
? ? ? ? ? ? ? ? // D7是保留位,默認(rèn)為1;
? ? ? ? ? ? ? ? // D6表示供電方式,0是自供電,1是總線供電;
? ? ? ? ? ? ? ? // D5表示是否支持遠(yuǎn)程喚醒,為1表示設(shè)備支持遠(yuǎn)程喚醒;
? ? ? ? ? ? ? ? // D4~D0保留,默認(rèn)為0。
? ? 0x32, ?// bMaxPower。配置設(shè)備需要的電流。單位是2ma。如果一個(gè)設(shè)備耗電量100ma,那么本字節(jié)設(shè)置為0x32即可。
? ? // 接口描述符(Consumer)
? ? 0x09, ?// bLength。配置本描述符的長(zhǎng)度。
? ? 0x04, ?// bDescriptorType。描述符類型。接口描述符為0x04。
? ? 0x00, ?// bInterfaceNumber。接口編號(hào)。如果一個(gè)配置有多個(gè)接口的話,那么每個(gè)接口的編號(hào)都有一個(gè)獨(dú)立的編號(hào),編號(hào)從0開始遞增。
? ? 0x00, ?// bAlternateSetting。備用接口編號(hào)。一般很少用,設(shè)置為0。
? ? 0x01, ?// bNumEndpoints。該接口使用的端點(diǎn)個(gè)數(shù)。
? ? 0x03, ?// bInterfaceClass。接口類。當(dāng)設(shè)備描述符設(shè)備類型bDeviceClass為0時(shí),也就是指示用接口描述符來(lái)標(biāo)識(shí)類別。
? ? 0x01, ?// bInterfaceSubClass。接口子類。
? ? 0x01, ?// bInterfaceProtocol。接口協(xié)議。
? ? 0x00, ?// iInterface。此接口的字符串索引值。沒有的話一般為0.
? ?
? ? // HID類描述符
? ? 0x09, ?// bLength。配置本描述符的長(zhǎng)度。
? ? 0x21, ?// bDescriptorType。描述符類型。HID描述符為0x21。
? ? 0x11,0x01, ?// bcdHID。HID設(shè)備所遵循的HID版本號(hào),為4位16進(jìn)制的BCD碼。1.0即0x0100,1.1即0x0101,2.0即0x0200。
? ? 0x00, ?// bCountryCode。HID設(shè)備國(guó)家/地區(qū)代碼。
? ? 0x01, ?// bNumDescriptor。HID設(shè)備支持的下級(jí)描述符的數(shù)量。由于HID設(shè)備至少需要包括一個(gè)報(bào)告描述符,故其值至小為0x01,一般的HID設(shè)備也為1,也就是有一個(gè)報(bào)告描述符,物理描述符很少用到。
? ? 0x22, ?// bDescriptorTyep。下級(jí)描述符的類型。下級(jí)描述符第1個(gè)必須是報(bào)告描述符,所以這里存放報(bào)告描述符類型,報(bào)告描述符的類型為0x22。
? ? sizeof(ConsumerRepDesc)&0xFF,sizeof(ConsumerRepDesc)>>8, ?// wDescriptorLength。下級(jí)描述符的長(zhǎng)度
? ?
? ? // 端點(diǎn)描述符(Consumer)
? ? 0x07, ?// bLength。配置本描述符的長(zhǎng)度。
? ? 0x05, ?// bDescriptorType。描述符類型。端點(diǎn)描述符為0x05。
? ? 0x81, ?// bEndpointAddress。
? ? ? ? ? ? ? ? // Bit 3…0: 端點(diǎn)編號(hào);
? ? ? ? ? ? ? ? // Bit 6…4: 保留,默認(rèn)為0;
? ? ? ? ? ? ? ? // Bit 7:如果是控制端點(diǎn)可以忽略,因?yàn)榭刂贫它c(diǎn)有兩個(gè)方向,否則一般表示數(shù)據(jù)傳輸方向,0 = OUT endpoint ? 1 = IN endpoint。
? ? 0x03, ?// bmAttributes。Bits 1..0: 表示傳輸類型
? ? ? ? ? ? ? ? // 00 = Control-控制傳輸
? ? ? ? ? ? ? ? // 01 = Isochronous-同步傳輸
? ? ? ? ? ? ? ? // 10 = Bulk-批量傳輸
? ? ? ? ? ? ? ? // 11 = Interrupt-中斷傳輸
? ? ? ? ? ? ? ? // Bits 7..2: 還沒講
? ? ENDP1_IN_SIZE,0x00, ?// wMaxPackeSize(雙字節(jié))。表示當(dāng)前配置下此端點(diǎn)能夠接收或發(fā)送的最大數(shù)據(jù)包的大小。
? ? 0x0a ?// bInterval。查詢時(shí)間。就是主機(jī)多久和設(shè)備通訊一次。低速和全速稱為幀,一個(gè)值代表1ms。高速稱為微幀,一個(gè)值代表125us。
};