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);

    其他的驱动程序处理都是常规处理,在这里就不多做介绍!

posted on 2013-02-02 18:34  WoLF89  阅读(1479)  评论(0编辑  收藏  举报

导航