Windows XP下USB转串口驱动编码实现分析
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口号.如下将对关键代码列出;
- 创建COM口设备对象
1 status = IoCreateDevice(DriverObject, 2 sizeof(VCP4USB_DEVICE_EXTENSION), 3 &ntDeviceName, 4 FILE_DEVICE_SERIAL_PORT, 5 0, 6 TRUE, // exclusive 7 &fdo);
-
获取USB设备名称用于打开设备
1 status = IoGetDeviceInterfaces(pGuid, NULL, 0, &pSymLink); 2 DPrint(DBG_OTHER, ("IoGetDeviceInterface return %d/n", status)); 3 4 if ((status == STATUS_INVALID_DEVICE_REQUEST) || (*pSymLink == NULL)) 5 return STATUS_UNSUCCESSFUL; 6 7 pCur = pSymLink; 8 instanceCur = 0; 9 status = STATUS_INVALID_INFO_CLASS; 10 while (*pCur != NULL) 11 { 12 p = pCur; 13 for (size = 0; *p != NULL; size ++) 14 p ++; 15 DPrint(DBG_OTHER, ("No.%d: size=%d/n", instanceCur, size)); 16 DPrint(DBG_OTHER, ("name:%ws/n", pCur)); 17 if (instance == instanceCur) 18 { 19 if (RtlCompareMemory(pCur, pPrefix, prefixLength) == prefixLength) 20 { 21 DPrint(DBG_OTHER, ("Find OK/n")); 22 devName->MaximumLength = size * sizeof(WCHAR); 23 devName->Buffer = (PWSTR)ExAllocatePool(NonPagedPool, (size + 1) * sizeof(WCHAR)); 24 if (devName->Buffer == NULL) 25 { 26 DPrint(DBG_OTHER, ("Allocate devName error./n")); 27 status = STATUS_INSUFFICIENT_RESOURCES; 28 break; 29 } 30 RtlCopyMemory(devName->Buffer, pCur, (size+1) * sizeof(WCHAR)); 31 RtlInitUnicodeString(devName, devName->Buffer); 32 status = STATUS_SUCCESS; 33 break; // find ok and break 34 } 35 } 36 pCur += size + 1; // skip last NULL 37 instanceCur ++; 38 if (instanceCur >= 2) // for debug 39 break; 40 } 41 42 ExFreePool(pSymLink); 43 return status;
-
打开USB设备端口
1 curStatus = GetUsbDeviceName(&usbDeviceName, &GUID_CLASS_XXXX_BULK, 2 &XXXX_SYMLINK_CMPSTR, XXXX_SYMLINK_STRLEN, 0); 3 if (!hRead) 4 rdStatus = createFile(&hRead, &usbDeviceName, L"//PIPE0", 6, GENERIC_READ); 5 if (!hWrite) 6 wtStatus = createFile(&hWrite, &usbDeviceName, L"//PIPE1", 6, GENERIC_WRITE);
其他的驱动程序处理都是常规处理,在这里就不多做介绍!