最近因?yàn)橐鉀Q一個(gè)bug,需要在內(nèi)核的f_hid.c里面做一些適配,需要把這部分代碼研究透徹。
在這幾天之前我是根本不知道什么是In端點(diǎn),Out端點(diǎn),以及什么是endpoint 0的,而且最近的一段時(shí)間,我一直是在寫應(yīng)用方面的代碼,也是趁著這個(gè)機(jī)會(huì),好好拜讀這部分。
——
在HID 1.0之前,是沒(méi)有什么OUT 端點(diǎn)的,都是用端點(diǎn)0來(lái)進(jìn)行數(shù)據(jù)傳輸,不過(guò)端點(diǎn)0有一個(gè)問(wèn)題,他的最大傳輸包的大小有限制。
謝謝我飛哥給的截圖
之后,就有一個(gè)大佬在原來(lái)的內(nèi)核代碼上面做了一部分修改,在原來(lái)的enpoint 0 上加了一個(gè)OUT端點(diǎn),意思就是說(shuō),本來(lái)從深圳到廣州有綠皮火車,但是綠皮火車一次只能裝下20個(gè)人,有一個(gè)人就發(fā)明了高鐵,高鐵一次可以裝200個(gè)人。
這個(gè)提交的鏈接
https://github.com/torvalds/linux/commit/99c515005857ff7d6cd5c2ba272ccab5dc0ea648
這個(gè)修改的commit里面說(shuō)明了修改的原因,比如說(shuō)使用端點(diǎn)0不能同步到字符設(shè)備,而且端點(diǎn)0的使用可能會(huì)導(dǎo)致數(shù)據(jù)丟失,所以加了一個(gè)OUT interrupt endpoint接口。
重點(diǎn)來(lái)了
并且這個(gè)補(bǔ)丁還會(huì)繼續(xù)處理SET_REPORT 接口請(qǐng)求事件。
——
好了,上面是這個(gè)文件的第一次修改,我們的代碼里面也是用的原廠的SDK代碼修改,但是這個(gè)修改有一個(gè)問(wèn)題,實(shí)際上端點(diǎn)0的SET REPORT并沒(méi)有正確請(qǐng)求,這是一個(gè)問(wèn)題,但是這個(gè)問(wèn)題不是Linux 代碼的問(wèn)題,應(yīng)該是芯片原廠移植過(guò)來(lái)后出現(xiàn)的問(wèn)題。
之后,又有一個(gè)大佬重新對(duì)這個(gè)內(nèi)核代碼進(jìn)行了改造
提交的commit鏈接如下
https://github.com/torvalds/linux/commit/d7428bc26fc767942c38d74b80299bcd4f01e7cb
他的修改的主要是增加了配置選項(xiàng),就是可以軟件配置使用OUT endpoint還是端點(diǎn)0,這主要是不同的產(chǎn)品定義可能需求會(huì)不同。
這個(gè)改造的原因是什么呢?
有些主機(jī)設(shè)備,我們說(shuō)的主機(jī)指的是USB的HOST設(shè)備,它不支持OUT endpoint 。
還有一些蘋果產(chǎn)品,他們天然就不能使用OUT端點(diǎn)來(lái)傳輸。
其他巴拉巴拉的一些大家就自己看吧。
——
截圖給大家看看什么是端點(diǎn)0和OUT endpoint
——
寫了很多,還沒(méi)有說(shuō)到我要改造什么,其實(shí)就是對(duì)這部分機(jī)制熟悉了,要修改掉因?yàn)镾ET REPORT導(dǎo)致的一個(gè)bug。
這也是一些看代碼的思路吧,內(nèi)核是分成很多很多模塊的,大家想看哪些模塊,去看看commit,去看看代碼,其實(shí)挺有意思的。
不過(guò)里面的一些命名并不是很清晰明了,比如IN這個(gè)東西,太簡(jiǎn)潔了,不是做USB的人估計(jì)很難明白,這些還有,要是去調(diào)試HID描述符,就知道那是太要繞腦子了。
——問(wèn)題是什么?
還是從HID來(lái)說(shuō),上面留言說(shuō)的沒(méi)問(wèn)題,USB嘛,不就是一個(gè)發(fā)送,一個(gè)接口,設(shè)備到主機(jī)通過(guò)in端口,這個(gè)沒(méi)問(wèn)題。
在HID低版本的時(shí)候用的是endpoint 0端口,也不能說(shuō)是低版本,即使在高版本,也是可以用endpoint 0端口的「不同之處在于低版本只有endpoint 0」,我也拿了一些競(jìng)品的產(chǎn)品來(lái)看,他們也是可以通過(guò)endpoint 0來(lái)發(fā)送信息給設(shè)備端的。
問(wèn)題是,我們用的RK方案打開(kāi)了out端點(diǎn)后不可以。
其他產(chǎn)品在打開(kāi)out端口的時(shí)候,也是可以用endpoint 0 發(fā)送數(shù)據(jù)到設(shè)備的。
為什么我揪著這個(gè)endpoint 0發(fā)送呢?
是因?yàn)闇y(cè)試發(fā)現(xiàn)通過(guò)這個(gè)端口可以使用set report 函數(shù),用這個(gè)函數(shù)來(lái)發(fā)送消息不會(huì)出現(xiàn)偶發(fā)的超時(shí)問(wèn)題。
RK是怎么回復(fù)的呢?
他們說(shuō)他們提供的方案是用endpoint 0的,都不會(huì)有問(wèn)題。
而且看了內(nèi)核代碼,確實(shí)是配置想用哪個(gè)就用哪個(gè),用戶自己選擇,用了out ,endpoint 0 就用不了了。
人家代碼也是寫得很清楚了,就是更子的。
——那我們?yōu)槭裁床恢苯佑肦K的方案,直接用endpoint 0 就好了
直接用endpoint 0我在之前的文章也說(shuō)了,這樣就可以兼容MAC的電腦,也不會(huì)出現(xiàn)一些亂七八糟可能性的問(wèn)題。
但是問(wèn)題是,我們的應(yīng)用程序開(kāi)發(fā)的很多功能,都已經(jīng)實(shí)現(xiàn),都是用的out端點(diǎn),包的長(zhǎng)度也是1024, 這方案一搞下去,那所有人都要重寫代碼,重新測(cè)試了。
—— 后面怎么修改了?
因?yàn)?/strong>如果加上
設(shè)備是可以調(diào)用HOST的setreport接口的,我要做的,無(wú)非就是在這里判斷下數(shù)據(jù)指令,然后傳給應(yīng)用程序就好了。
問(wèn)題就出在這里,usb的一些結(jié)構(gòu)體,如果沒(méi)有好好寫,就可能影響到系統(tǒng)的東西。
OUT端點(diǎn)寫入數(shù)據(jù)的時(shí)候,是直接用到req結(jié)構(gòu)體的
這段代碼在out端點(diǎn)接收沒(méi)有問(wèn)題,但是放到setreport部分來(lái)處理就出現(xiàn)了問(wèn)題。
setreport的處理不一樣
他給HOST來(lái)的數(shù)據(jù)在內(nèi)核重新分配了空間。
然后就針對(duì)這些不同的邏輯修改修改。
細(xì)節(jié)就不說(shuō)了
內(nèi)核代碼不像應(yīng)用代碼,應(yīng)用的調(diào)試是比較方便的,內(nèi)核的調(diào)試涉及硬件設(shè)備就不同了,而且接口的處理也會(huì)不同,稍不注意引起的空指針問(wèn)題,整個(gè)系統(tǒng)就掛了,應(yīng)用還可以用守護(hù)進(jìn)程拉起來(lái),內(nèi)核就不行,只能重啟。
不過(guò)內(nèi)核都是C,看起來(lái)還是比較舒服的。
更多信息可以來(lái)這里獲取==>>電子技術(shù)應(yīng)用-AET<<
電子技術(shù)應(yīng)用專欄作家 嵌入式Linux
原文鏈接:https://mp.weixin.qq.com/s/humym3KbZsEzT2XSi-texw