USB轉COM驅動的編寫實現有很多中方法,最近在網路上看到一個最常用的方式,即是虛擬一個COM口,在COM初試的時候進行開啟一個USB裝置.
當USB串COM口驅動處理Write和Read 等IRQ的時候,其實是去讀寫USB 裝置驅動,讀寫方式是直接採用ZwReadFile和ZwWriteFile函數.但是真正的實現也不是這麼簡單,真實的實現是開闢一個線程和一段較大的緩衝區,線程用於適時讀取USB裝置的資料並儲存在緩衝區當中.當上層應用程式向這個虛擬COM口發送READ IRP(IRP_MJ_READ)的時候,則直接從這段緩衝區中讀取資料返回即可.當然還不要忘記處理逾時的問題處理.
因此USB轉COM驅動在INF檔案載入的時候實際上需要載入兩個驅動程式,一個是USB驅動,對應與USB裝置的VID和PID,另外一個就是COM虛擬驅動程式,需要對應設定COM口號.如下將對關鍵代碼列出;
status = IoCreateDevice(DriverObject,<br /> sizeof(VCP4USB_DEVICE_EXTENSION),<br /> &ntDeviceName,<br /> FILE_DEVICE_SERIAL_PORT,<br /> 0,<br /> TRUE, // exclusive<br /> &fdo);
status = IoGetDeviceInterfaces(pGuid, NULL, 0, &pSymLink);<br /> DPrint(DBG_OTHER, ("IoGetDeviceInterface return %d/n", status));</p><p> if ((status == STATUS_INVALID_DEVICE_REQUEST) || (*pSymLink == NULL))<br /> return STATUS_UNSUCCESSFUL;</p><p> pCur = pSymLink;<br /> instanceCur = 0;<br /> status = STATUS_INVALID_INFO_CLASS;<br /> while (*pCur != NULL)<br /> {<br /> p = pCur;<br /> for (size = 0; *p != NULL; size ++)<br /> p ++;<br /> DPrint(DBG_OTHER, ("No.%d: size=%d/n", instanceCur, size));<br /> DPrint(DBG_OTHER, ("name:%ws/n", pCur));<br /> if (instance == instanceCur)<br /> {<br /> if (RtlCompareMemory(pCur, pPrefix, prefixLength) == prefixLength)<br /> {<br /> DPrint(DBG_OTHER, ("Find OK/n"));<br /> devName->MaximumLength = size * sizeof(WCHAR);<br /> devName->Buffer = (PWSTR)ExAllocatePool(NonPagedPool, (size + 1) * sizeof(WCHAR));<br /> if (devName->Buffer == NULL)<br /> {<br /> DPrint(DBG_OTHER, ("Allocate devName error./n"));<br /> status = STATUS_INSUFFICIENT_RESOURCES;<br /> break;<br /> }<br /> RtlCopyMemory(devName->Buffer, pCur, (size+1) * sizeof(WCHAR));<br /> RtlInitUnicodeString(devName, devName->Buffer);<br /> status = STATUS_SUCCESS;<br /> break; // find ok and break<br /> }<br /> }<br /> pCur += size + 1; // skip last NULL<br /> instanceCur ++;<br /> if (instanceCur >= 2) // for debug<br /> break;<br /> }</p><p> ExFreePool(pSymLink);<br /> return status;
curStatus = GetUsbDeviceName(&usbDeviceName, &GUID_CLASS_XXXX_BULK,<br /> &XXXX_SYMLINK_CMPSTR, XXXX_SYMLINK_STRLEN, 0);<br /> if (!hRead)<br /> rdStatus = createFile(&hRead, &usbDeviceName, L"//PIPE0", 6, GENERIC_READ);<br /> if (!hWrite)<br /> wtStatus = createFile(&hWrite, &usbDeviceName, L"//PIPE1", 6, GENERIC_WRITE);
其他的驅動程式處理都是常規處理,在這裡就不多做介紹!