文獻(xiàn)標(biāo)識(shí)碼: A
DOI:10.16157/j.issn.0258-7998.2017.02.029
中文引用格式: 王嘉駿,楊錄,韓志毅,等. 車架號(hào)碼區(qū)域隱藏焊縫檢測(cè)系統(tǒng)的定位裝置[J].電子技術(shù)應(yīng)用,2017,43(2):120-123.
英文引用格式: Wang Jiajun,Yang Lu,Han Zhiyi,et al. The positioning device for the detection system of the frame number area hidden weld[J].Application of Electronic Technique,2017,43(2):120-123.
0 引言
車架號(hào)碼是由阿拉伯?dāng)?shù)字和字母組成的17位編碼,對(duì)車輛具有唯一識(shí)別性,因此被稱為“汽車身份證”[1]。被盜車輛的車架號(hào)碼區(qū)域通常會(huì)被整體摳掉,并重新焊接刻有偽造車架號(hào)碼的鋼板,再通過打膩?zhàn)雍蛧娖岬姆椒?a class="innerlink" href="http://ihrv.cn/tags/隱藏焊縫" title="隱藏焊縫" target="_blank">隱藏焊縫,從而逃避交警的追查[2]。針對(duì)這種情況,現(xiàn)常使用超聲無損檢測(cè)技術(shù),通過分析超聲回波來判定車架的完整性。但是,這種方法僅可作為一種甄別手段,對(duì)于刑事訴訟仍缺少有力的證據(jù)。所以,本文將通用鼠標(biāo)改造成一位置傳感器,在檢測(cè)過程中對(duì)隱藏焊縫進(jìn)行定位,再結(jié)合超聲回波信號(hào),生成對(duì)檢測(cè)區(qū)域內(nèi)部結(jié)構(gòu)的俯視灰度圖,進(jìn)一步判斷車架的完整性并提供有力證據(jù)。
在對(duì)車架區(qū)域檢測(cè)掃描的過程中,為了獲得檢測(cè)區(qū)域內(nèi)部結(jié)構(gòu)的俯視圖,須實(shí)時(shí)獲得超聲探頭的二維坐標(biāo)。本文通過將編寫的下層過濾驅(qū)動(dòng)程序安裝到USB(通用串行總線)鼠標(biāo),使其成為一個(gè)虛擬的位置傳感器來實(shí)現(xiàn)定位。最終,檢測(cè)系統(tǒng)將采集到的超聲回波信號(hào)和相應(yīng)的探頭位置信息匹配,實(shí)現(xiàn)實(shí)時(shí)計(jì)算檢測(cè)過程中超聲探頭的運(yùn)動(dòng)軌跡和生成檢測(cè)區(qū)域內(nèi)部結(jié)構(gòu)的俯視圖,并使得檢測(cè)設(shè)備具有便攜和靈活的特點(diǎn)。
1 USB鼠標(biāo)驅(qū)動(dòng)模型
1.1 Windows驅(qū)動(dòng)模型概述
Windows驅(qū)動(dòng)程序在Windows主機(jī)應(yīng)用程序和物理設(shè)備之間采用了靈活的分層驅(qū)動(dòng)方式。分層式的結(jié)構(gòu)具有很好的可移植性和兼容性,開發(fā)者可利用已有的系統(tǒng)驅(qū)動(dòng)程序來開發(fā)滿足客戶需要的驅(qū)動(dòng)程序。
在標(biāo)準(zhǔn)的Windows系統(tǒng)驅(qū)動(dòng)程序分層結(jié)構(gòu)的模型中,功能驅(qū)動(dòng)程序和總線驅(qū)動(dòng)程序是兩個(gè)最為重要的驅(qū)動(dòng)程序。其中,總線驅(qū)動(dòng)程序負(fù)責(zé)主機(jī)和硬件設(shè)備的連接,由操作系統(tǒng)提供,用戶無須干預(yù)。功能驅(qū)動(dòng)程序是用戶根據(jù)需要自己開發(fā),一個(gè)完整的功能驅(qū)動(dòng)程序包含多個(gè)例程,當(dāng)Windows系統(tǒng)接收到一個(gè)IRP(I/O請(qǐng)求包)時(shí),系統(tǒng)就會(huì)調(diào)用相應(yīng)的驅(qū)動(dòng)程序例程來執(zhí)行操作。
有些設(shè)備還需要安裝過濾驅(qū)動(dòng)程序,過濾驅(qū)動(dòng)程序根據(jù)功能的不同分成上層過濾驅(qū)動(dòng)程序和下層過濾驅(qū)動(dòng)程序兩種。其中上層過濾驅(qū)動(dòng)程序作用于功能驅(qū)動(dòng)程序之上,為指定設(shè)備提供附加的功能支持。下層過濾驅(qū)動(dòng)程序作用于功能驅(qū)動(dòng)程序之下,且數(shù)據(jù)須經(jīng)過下層過濾驅(qū)動(dòng)程序處理后再向下傳輸[3]。
這樣下層過濾驅(qū)動(dòng)程序可以對(duì)數(shù)據(jù)進(jìn)行捕捉、修改或者攔截的操作,進(jìn)而重新定義硬件行為。本文就是使用這類過濾驅(qū)動(dòng)程序來開發(fā)位置傳感器。
1.2 HID USB鼠標(biāo)的驅(qū)動(dòng)程序設(shè)備棧模型
圖1是USB鼠標(biāo)在Windows系統(tǒng)環(huán)境中的訪問流程。在圖中,一個(gè)HID類應(yīng)用程序可以調(diào)用含有系統(tǒng)HID類驅(qū)動(dòng)程序hidclass.sys的HID類設(shè)備棧。HID類驅(qū)動(dòng)程序又調(diào)用HID小驅(qū)動(dòng)程序和硬件設(shè)備進(jìn)行USB通信,在訪問過程中需要經(jīng)過下層過濾驅(qū)動(dòng)程序hidparse.sys進(jìn)行語法分析。
當(dāng)USB鼠標(biāo)插入到計(jì)算機(jī)后會(huì)先經(jīng)過USB棧被識(shí)別為USB設(shè)備,因?yàn)樗彩荋ID類設(shè)備,所以系統(tǒng)會(huì)同時(shí)裝入HID類的驅(qū)動(dòng)棧;當(dāng)HID類驅(qū)動(dòng)程序通過HID小驅(qū)動(dòng)程序hidparse.sys讀取到USB鼠標(biāo)的報(bào)告描述符時(shí),系統(tǒng)依據(jù)對(duì)報(bào)告描述符中usage項(xiàng)的判斷,識(shí)別當(dāng)前設(shè)備為鼠標(biāo)。因此鼠標(biāo)驅(qū)動(dòng)程序也會(huì)在HID類驅(qū)動(dòng)棧之上的位置裝入系統(tǒng),這樣完整的驅(qū)動(dòng)程序棧裝入完畢。此時(shí),USB鼠標(biāo)就可以正常的工作了。隨后Windows系統(tǒng)利用Win32函數(shù)以光標(biāo)的形式將USB鼠標(biāo)的位移信息表現(xiàn)出來,這就完成了對(duì)USB鼠標(biāo)的操作。
2 USB光電鼠標(biāo)映射為虛擬的位置傳感器的開發(fā)思路
2.1 USB 鼠標(biāo)過濾驅(qū)動(dòng)程序的開發(fā)思路
本文的目的是利用USB光電鼠標(biāo)獲得精確的位置信息,但光電鼠標(biāo)作為操作系統(tǒng)的獨(dú)占設(shè)備,只允許Windows系統(tǒng)對(duì)其訪問,所以需要攔截并改變它的報(bào)告描述符使它成為自定義的新設(shè)備。HID類驅(qū)動(dòng)程序與USB棧對(duì)話會(huì)調(diào)用小驅(qū)動(dòng)程序,小驅(qū)動(dòng)程序又通過產(chǎn)生內(nèi)部IOCTL(I/O控制碼)來使能USB類驅(qū)動(dòng)程序,進(jìn)而可獲得設(shè)備的報(bào)告描述符。當(dāng)設(shè)備是鼠標(biāo)時(shí),報(bào)告描述符中的usage項(xiàng)的值是2,如果將它改為0,操作系統(tǒng)就不會(huì)再將它識(shí)別為鼠標(biāo),也就不會(huì)再有裝入鼠標(biāo)驅(qū)動(dòng)棧的操作。所此, 本文的工作就是編譯一個(gè)下層過濾驅(qū)動(dòng)程序usbfilt.sys來攔截USB鼠標(biāo)的報(bào)告描述符并修改其中usage項(xiàng)的返回值,使系統(tǒng)不會(huì)將它識(shí)別為鼠標(biāo), 這樣用戶態(tài)程序就有權(quán)利對(duì)新定義的設(shè)備進(jìn)行控制和訪問。
2.2 I/O請(qǐng)求包和IRP處理
I/O請(qǐng)求包是Windows系統(tǒng)所使用的與內(nèi)核模式驅(qū)動(dòng)程序通信的一種數(shù)據(jù)結(jié)構(gòu),其中帶有一組I/O管理器例程且可對(duì)I/O請(qǐng)求包進(jìn)行操作。I/O管理器依據(jù)請(qǐng)求內(nèi)容的不同來選擇相應(yīng)的設(shè)備對(duì)象和驅(qū)動(dòng)程序?qū)ο?,同時(shí)生成相應(yīng)的IRP發(fā)送到對(duì)應(yīng)的驅(qū)動(dòng)程序中來執(zhí)行特定的操作,驅(qū)動(dòng)與驅(qū)動(dòng)之間通過IRP進(jìn)行通信。
IRP是從非分頁內(nèi)存中定義分配的大小可變的結(jié)構(gòu),它由IRP首部和可變數(shù)目的輔助請(qǐng)求棧單元組成。IRP首部由當(dāng)前擁有IRP的驅(qū)動(dòng)指針、指向IRP輸入輸出緩沖區(qū)的指針等組成。之后是一個(gè)IO_STACK_LOCATION結(jié)構(gòu)的棧單元,棧單元中保存著一個(gè)I/O請(qǐng)求的參數(shù)以及代碼、完成函數(shù)指針請(qǐng)求、當(dāng)前對(duì)應(yīng)的設(shè)備指針等。當(dāng)多個(gè)驅(qū)動(dòng)程序處理一個(gè)IRP時(shí),就會(huì)生成多個(gè)IRP棧單元。不同驅(qū)動(dòng)程序需從其所指向的IRP棧單元中讀取到相應(yīng)的IRP參數(shù)。如果需要把IRP沿當(dāng)前被訪問設(shè)備的驅(qū)動(dòng)程序棧繼續(xù)傳遞下去,下一個(gè)棧單元的參數(shù)必須被正確設(shè)置。向下傳遞的IRP所對(duì)應(yīng)的參數(shù)必須不同于正在處理的IRP。
當(dāng)一個(gè)I/O請(qǐng)求包生成一個(gè)對(duì)應(yīng)的IRP時(shí),IRP首部和第一個(gè)IRP棧單元將首先被I/O管理器設(shè)置。IRP中含有很多問題需要驅(qū)動(dòng)程序進(jìn)行處理,所以當(dāng)一個(gè)IRP生成時(shí),就會(huì)被傳遞到當(dāng)前訪問設(shè)備的驅(qū)動(dòng)程序棧的棧頂,隨即會(huì)被從上而下進(jìn)行相應(yīng)的處理,如圖2所示。
IRP的處理是從最頂層驅(qū)動(dòng)程序1開始,通過調(diào)用函數(shù)IoGetCurrentIrpStackLocation來使I/O管理器棧單元指針指向當(dāng)前棧單元。如果IRP需要繼續(xù)向下傳遞到驅(qū)動(dòng)程序2,這時(shí)驅(qū)動(dòng)程序2的棧單元需驅(qū)動(dòng)程序1設(shè)置它的參數(shù),并通過函數(shù)IoCallDriver來被調(diào)用,同時(shí)新生成的棧單元地址會(huì)映射到I/O管理器棧單元的指針, 然后過濾到的符合條件的IRP 將會(huì)被驅(qū)動(dòng)程序2 處理,之后以同樣的方式向下傳遞直到所用的驅(qū)動(dòng)程序處理完畢。當(dāng)IRP包含的問題處理完畢,最后的驅(qū)動(dòng)程序4 通過調(diào)用函數(shù)IoCompleteRequest 來標(biāo)識(shí)當(dāng)前IRP為已經(jīng)完成處理, 隨后沿著設(shè)備棧將IRP向上傳遞, 最終到達(dá)棧頂彈出,回到用戶。
3 過濾驅(qū)動(dòng)程序的開發(fā)
3.1 過濾驅(qū)動(dòng)程序主框架
DriverStudio是NuMega公司提供的驅(qū)動(dòng)程序開發(fā)工具。在DriverWorks中提供一個(gè)過濾驅(qū)動(dòng)程序的模板例程usbfilt[4]。在這個(gè)過濾驅(qū)動(dòng)程序中,直接把IRP傳送下去。本設(shè)計(jì)重點(diǎn)在于下面這個(gè)例程:
NTSTATUS UsbFilterDevice::InternalDeviceControl
(KIrp I)
{
T << "UsbFilterDevice::InternalDeviceControl\n";
if (I.IoctlCode() !=
IOCTL_INTERNAL_USB_SUBMIT_URB)
return DefaultPnp(I);
PURB p = I.Urb(CURRENT);
if(p->UrbHeader.Function!=URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE)
return DefaultPnp(I);
return PassThrough(I,
LinkTo(DeviceControlComplete), this);
}
需要重新定義的IRP會(huì)被上面的例程過濾到,并經(jīng)過下面的完成例程處理,從而構(gòu)成過濾驅(qū)動(dòng)程序的主框架。
NTSTATUS UsbFilterDevice::DeviceControlComplete(KIrp I)
{
T <<"UsbFilterDevice::DeviceControlComplete\n";
PURB p=I.Urb(CURRENT);
if(p)
{
char* DeseriptorBuffer=
(char*)p->
UrbControlDescriptorRequest.TransferBuffer;
DeseriptorBuffer+=3;
if((*DeseriptorBuffer&0xff)==2)
{
*DeseriptorBuffer=0;
}
}
return I.Status();
}
在這個(gè)完成例程中定義了一個(gè)指向URB(USB請(qǐng)求塊)緩沖區(qū)的指針DeseriptorBuffer,其中保存著設(shè)計(jì)所需要的報(bào)告描述符。在這個(gè)數(shù)組的第3個(gè)字節(jié)中保存著usage的值,然后需要對(duì)此值進(jìn)行判斷,如果是“2”就可以判定當(dāng)前讀取到的設(shè)備報(bào)告描述符是鼠標(biāo)的,之后需要將此值改為“0”,這樣就把讀到的報(bào)告描述符改成了自定義設(shè)備的報(bào)告。重啟設(shè)備后,當(dāng)系統(tǒng)再次讀到這個(gè)報(bào)告時(shí)就不會(huì)把USB鼠標(biāo)當(dāng)成標(biāo)準(zhǔn)設(shè)備而被系統(tǒng)獨(dú)占了。相反,USB鼠標(biāo)會(huì)作為自定義設(shè)備來使用。驅(qū)動(dòng)程序經(jīng)過DriverStudio在VC++6.0的編譯運(yùn)行后,生成了設(shè)計(jì)所需要的過濾驅(qū)動(dòng)程序usbfilt.sys。
3.2 過濾驅(qū)動(dòng)程序的安裝
為了通過VC++6.0將過濾驅(qū)動(dòng)程序準(zhǔn)確地安裝到某個(gè)設(shè)備上,應(yīng)該通過GUID(全域唯一標(biāo)識(shí)碼)查找指定設(shè)備類下的硬件ID來決定是否需要安裝過濾驅(qū)動(dòng)。另外,由于該過濾驅(qū)動(dòng)修改了報(bào)告描述符,導(dǎo)致最終的設(shè)備由原來的鼠標(biāo)變成了HID兼容設(shè)備。所以需要先將原來的驅(qū)動(dòng)卸載掉,然后才能安裝過濾驅(qū)動(dòng);否則系統(tǒng)將還使用以前的驅(qū)動(dòng),也就不會(huì)出現(xiàn)新的硬件。安裝過濾驅(qū)動(dòng)的關(guān)鍵是以下幾方面:(1)復(fù)制過濾驅(qū)動(dòng)文件usbfilt.sys到當(dāng)前系統(tǒng)的Windows\System32\Drivers目錄下;(2)卸載舊的驅(qū)動(dòng)程序,通過查找所有鼠標(biāo)設(shè)備,查看是否有指定硬件ID的設(shè)備,如果有,則卸載它;(3)添加服務(wù),調(diào)用OpenSCManager()函數(shù)打開SCManager數(shù)據(jù)庫,然后調(diào)用CreatService()函數(shù)增加usbfilt服務(wù);(4)更新設(shè)備過濾驅(qū)動(dòng)程序名稱列表;(5)重新啟動(dòng)設(shè)備,使主機(jī)識(shí)別新硬件。
3.3 獲取信息的用戶態(tài)應(yīng)用程序開發(fā)
通過安裝過濾驅(qū)動(dòng)把一個(gè)標(biāo)準(zhǔn)的Windows系統(tǒng)USB鼠標(biāo)改造成虛擬位置傳感設(shè)備后,Windows系統(tǒng)就失去了對(duì)它獨(dú)占訪問的權(quán)利。利用VC++編寫用戶態(tài)應(yīng)用程序?qū)ζ溥M(jìn)行訪問, 讀出它的位置信息為系統(tǒng)所用。
光電鼠標(biāo)芯片是一種內(nèi)部集成有圖像采集系統(tǒng)(IAS)和數(shù)字處理器(DSP)的數(shù)字圖像處理系統(tǒng),通過圖像處理實(shí)現(xiàn)二維平面的定位。圖像采集系統(tǒng)通過芯片底部的感光眼不斷對(duì)物體拍照,然后將圖像信息發(fā)送到數(shù)字處理器,數(shù)字處理器首先提取每張圖像信息中的特征像素,然后對(duì)相鄰的兩幅圖像信息中同一特征像素的位置變化進(jìn)行識(shí)別,進(jìn)而間接計(jì)算得到兩幅圖像在拍攝時(shí)間間隔內(nèi)USB鼠標(biāo)的移動(dòng)方向和位移大小,并把這些數(shù)值量化封裝后,發(fā)送到鼠標(biāo)芯片的固件中,進(jìn)一步封裝得到固定格式的報(bào)告描述符,最終通過USB接口送入計(jì)算機(jī)。
本文采用的鼠標(biāo)芯片的輸入報(bào)告描述符有5個(gè)字節(jié)。其中在第1、第2和第3個(gè)字節(jié)中儲(chǔ)存著X、Y方向的坐標(biāo)值以及左右鍵的狀態(tài),這3 個(gè)字節(jié)的具體結(jié)構(gòu)如圖3所示。需要注意的是:一方面在輸入報(bào)告描述符中第2和第3字節(jié)是移動(dòng)的相對(duì)坐標(biāo)值,需在后續(xù)的程序中通過累加算法把它轉(zhuǎn)換為鼠標(biāo)移動(dòng)的絕對(duì)坐標(biāo);另一方面,此設(shè)備被激勵(lì)后使用的是右手坐標(biāo)系。
要實(shí)時(shí)獲得位置傳感器的位置信息,需要循環(huán)讀取位移信息。為了避免讀操作時(shí)發(fā)生訪問沖突失去響應(yīng),單獨(dú)創(chuàng)建一個(gè)線程來高速讀取輸入報(bào)告。通過調(diào)用Windows提供的API函數(shù)庫來識(shí)別并讀取USB設(shè)備的數(shù)據(jù),并定義一個(gè)緩沖數(shù)組存取輸入報(bào)告描述符中的坐標(biāo)值, 最后根據(jù)對(duì)鼠標(biāo)設(shè)定的分辨率將得到的絕對(duì)坐標(biāo)值轉(zhuǎn)換為實(shí)際的位移大小。
4 實(shí)驗(yàn)結(jié)果及分析
將過濾驅(qū)動(dòng)程序usbfilt.sys準(zhǔn)確地安裝到目標(biāo)鼠標(biāo)上。此時(shí),重新啟動(dòng)設(shè)備,使主機(jī)識(shí)別新硬件。圖4所示為在VC環(huán)境下編譯的簡易上位機(jī),上位機(jī)可識(shí)別改造好的新設(shè)備,并顯示必要的設(shè)備信息。
在車架的完整性檢測(cè)工程中,超聲探頭和位置傳感器在車架區(qū)域同步掃描。通過定義灰度值將超聲回波信號(hào)可視化顯示,即可生成一檢測(cè)區(qū)域內(nèi)部結(jié)構(gòu)的俯視圖。經(jīng)實(shí)驗(yàn)檢測(cè),傳感器定位精度可達(dá)到0.03 mm,完全滿足本檢測(cè)系統(tǒng)對(duì)于位置信息的精度要求。
5 結(jié)論
本文通過編寫HID類下層過濾驅(qū)動(dòng)程序?qū)SB光電鼠標(biāo)映射為一個(gè)位置傳感器,實(shí)現(xiàn)了車架完整性檢測(cè)過程中快速、準(zhǔn)確定位隱藏焊縫,并進(jìn)一步結(jié)合超聲回波信號(hào),生成對(duì)檢測(cè)區(qū)域內(nèi)部結(jié)構(gòu)的俯視灰度圖。為公安機(jī)關(guān)處理走私、盜竊車輛案件的刑事訴訟工作提供了有力證據(jù),同時(shí)這種方法充分體現(xiàn)便攜式檢測(cè)設(shè)備輕便靈活的特點(diǎn),具有很好實(shí)用價(jià)值。
參考文獻(xiàn)
[1] 于吉?jiǎng)?,楊錄,張艷花.便攜式隱藏焊縫超聲檢測(cè)系統(tǒng)設(shè)計(jì)[J].儀表技術(shù)與傳感器,2015(12):85-87,96.
[2] 武佳慧,楊錄,張艷花.車架VIN碼區(qū)域超聲檢測(cè)方法研究[J].電子技術(shù)應(yīng)用,2014(8):80-82,86.
[3] 宮閩軍.碳纖維復(fù)合材料孔隙率超聲檢測(cè)系統(tǒng)定位裝置及可視化研究[D].杭州:浙江大學(xué),2005.
[4] 李凌.碳纖維復(fù)合材料數(shù)字化超聲檢測(cè)系統(tǒng)關(guān)鍵技術(shù)研究[D].杭州:浙江大學(xué),2007.
作者信息:
王嘉駿1,楊 錄1,韓志毅2,趙 辛2
(1.中北大學(xué) 信息與通信工程學(xué)院 電子測(cè)試技術(shù)國家重點(diǎn)實(shí)驗(yàn)室,山西 太原030051;
2.太原市公安局,山西 太原030051)