1

我一直在这里关注 WinUsb MSDN HowTo ,到目前为止它运行良好。我已经在指南中指出我必须从 WinUsb DLL 调用 WinUsb_Initialize() 函数。这就是我卡住的地方。到目前为止,我的代码是这样的,你无疑会确定我已经从 PyWinUSB 的 WinAPI.py 模块中撕下了很多东西。在此处插入无偿感谢并感谢 PyWinUSB 的创建者。

import ctypes
import platform
from ctypes import byref, POINTER, Structure, sizeof, c_ulong
from ctypes.wintypes import DWORD, WORD, BYTE, HANDLE, LPCWSTR, ULONG, WCHAR, \
BOOL
TCHAR = WCHAR

winUSB          = ctypes.windll.winusb
winHID          = ctypes.windll.hid
kernel32        = ctypes.windll.kernel32
setupAPI        = ctypes.windll.setupapi

GENERIC_READ    = (-2147483648)
GENERIC_WRITE   = (1073741824)
FILE_SHARE_READ = 1
FILE_SHARE_WRITE = 2
OPEN_EXISTING   = 3
FILE_FLAG_OVERLAPPED    = 1073741824

if platform.architecture()[0].startswith('64'):
    WIN_PACK = 8
else:
    WIN_PACK = 1

class GUID(ctypes.Structure):
    """GUID Windows OS Structure"""
    _pack_ = 1
    _fields_ = [("data1", DWORD),
                ("data2", WORD),
                ("data3", WORD),
                ("data4", BYTE * 8)]

    def __init__(self, data1 = None, data2 = None, data3 = None, data4 = None):
        if data1 is not None:
            self.data1 = data1
        if data2 is not None:
            self.data2 = data2
        if data3 is not None:
            self.data3 = data3
        if data4 is not None:
            self.data4 = data4

class SP_DEVICE_INTERFACE_DATA(Structure):
    """
    typedef struct _SP_DEVICE_INTERFACE_DATA {
        DWORD       cbSize;
        GUID        InterfaceClassGuid;
        DWORD       Flags;
        ULONG_PTR   Reserved;
        } SP_DEVICE_INTERFACE_DATA,  *PSP_DEVICE_INTERFACE_DATA
    """
    _pack_ = WIN_PACK
    _fields_ = [("cb_size",                 DWORD),
                ("interface_class_guid",    GUID),
                ("flags",                   DWORD),
                ("reserved",                POINTER(ULONG))]

    def __init__(self):
        self.cb_size = sizeof(SP_DEVICE_INTERFACE_DATA)


class SP_DEVICE_INTERFACE_DETAIL_DATA(Structure):
    """
    typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA {
        DWORD cbSize;
        TCHAR DevicePath[ANYSIZE_ARRAY];
    } SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA;
    """

    _pack_ = WIN_PACK
    _fields_ = [("cb_size", DWORD),
                ("device_path", TCHAR * 1)] #device_path[1]

    def __init__(self):
        self.cb_size = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)

    def get_string(self):
        """Retreive stored string"""
        return ctypes.wstring_at(byref(self, sizeof(DWORD)))


class SP_DEVINFO_DATA(Structure):
    """
    typedef struct _SP_DEVINFO_DATA {
      DWORD     cbSize;
      GUID      ClassGuid;
      DWORD     DevInst;
      ULONG_PTR Reserved;
    } SP_DEVINFO_DATA, *PSP_DEVINFO_DATA;
    """
    _pack_ = WIN_PACK
    _fields_ = [("cb_size",     DWORD),
                ("class_guid",  GUID),
                ("dev_inst",    DWORD),
                ("reserved",    POINTER(ULONG))]

    def __init__(self):
        self.cb_size = sizeof(SP_DEVINFO_DATA)

class DIGCF:
    """
    Flags controlling what is included in the device information set
    built by SetupDiGetClassDevs
    """
    DEFAULT         = 0x00000001
    PRESENT         = 0x00000002
    ALLCLASSES      = 0x00000004
    PROFILE         = 0x00000008
    DEVICEINTERFACE = 0x00000010

def GetHidGuid():
    "Get system-defined GUID for HIDClass devices"
    hid_guid = GUID()
    winHID.HidD_GetHidGuid(byref(hid_guid))
    return hid_guid

SetupDiGetClassDevs             = setupAPI.SetupDiGetClassDevsW
SetupDiGetClassDevs.restype     = HANDLE
SetupDiGetClassDevs.argtypes    = [
    # __in_opt      const GUID *ClassGuid,
    # __in_opt      PCTSTR Enumerator,
    # __in_opt      HWND hwndParent,
    # __in          DWORD Flags,
    POINTER(GUID),
    LPCWSTR,
    HANDLE,
    DWORD]

SetupDiGetDeviceInterfaceDetail             = setupAPI.SetupDiGetDeviceInterfaceDetailW
SetupDiGetDeviceInterfaceDetail.restype     = BOOL
SetupDiGetDeviceInterfaceDetail.argtypes    = [
    # __in          HDEVINFO DeviceInfoSet,
    # __in          PSP_DEVICE_INTERFACE_DATA DeviceIn,
    # __out_opt     PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData,
    # __in          DWORD DeviceInterfaceDetailDataSize,
    # __out_opt     PDWORD RequiredSize
    # __out_opt     PSP_DEVINFO_DATA DeviceInfoData
    HANDLE,
    POINTER(SP_DEVICE_INTERFACE_DATA),
    POINTER(SP_DEVICE_INTERFACE_DETAIL_DATA),
    DWORD,
    POINTER(DWORD),
    POINTER(SP_DEVINFO_DATA)]                                   

devGuid     = GUID(0x2518E22E, 0x0F35, 0x11E2, (BYTE * 8)(0xB1, 0xD5, 0x6C, 0xF0,
                                                          0x49, 0x73, 0x78, 0x72))
classGuid   = GetHidGuid()
                #GUID(0x745A17A0, 0x74D3, 0x11D0, (BYTE * 8)(0xB6, 0xFE, 0x00, 0xA0,
                #                                            0xC9, 0x0F, 0x57, 0xDA))

derp        = SetupDiGetClassDevs(
                byref(classGuid), None, None,
                (DIGCF.PRESENT | DIGCF.DEVICEINTERFACE))

def stepDevices(herp, index = 0):
    devInterfaceData = SP_DEVICE_INTERFACE_DATA()
    if setupAPI.SetupDiEnumDeviceInterfaces(
        herp, None, byref(classGuid), index, byref(devInterfaceData)):
        yield devInterfaceData
        del devInterfaceData
    else:
        print(kernel32.GetLastError())

def enumDevices(herp):
    index               = 0    
    devInterfaceData    = SP_DEVICE_INTERFACE_DATA()
    while setupAPI.SetupDiEnumDeviceInterfaces(
        herp, None, byref(classGuid), index, byref(devInterfaceData)):        
        print(kernel32.GetLastError())
        yield devInterfaceData
        index += 1
    del devInterfaceData

def getDetail(herp, devData, devInfo = None):

    reqSize     = c_ulong(0)
    devDetail   = SP_DEVICE_INTERFACE_DETAIL_DATA()

    SetupDiGetDeviceInterfaceDetail(
        herp, byref(devData), None, 0, byref(reqSize), None)

    ctypes.resize(devDetail, reqSize.value)

    SetupDiGetDeviceInterfaceDetail(
        herp, byref(devData), byref(devDetail),
        reqSize, None, byref(devInfo))

    return devDetail.get_string()

dev = stepDevices(derp).next()
devInfo = SP_DEVINFO_DATA()
devString = getDetail(derp, dev, devInfo)

winUSBHandle = kernel32.CreateFileW(
    devString, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, None, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, None)

#winUSB.WinUsb_Initialize(winUSBHandle, <what goes here?>)

我尝试创建一个简单的句柄并将 byref(handle) 作为第二个参数传递给函数,但句柄值保持为 None。我不知道 Python 和 WinUSB.DLL 做了多少工作,但如果有人能指出我正确的方向,我将不胜感激。

提前致谢。

4

1 回答 1

0

文档说它是一个 PWINUSB_INTERFACE_HANDLE,它是一个 PVOID,它是一个c_void_pin ctypes,所以这应该可以工作:

h = ctypes.c_void_p()
winUSB.WinUsb_Initialize(winUSBHandle, ctypes.byref(h))

外观是否winUSBHandle有效(不是 0 或 -1 或 0xFFFFFFFF)?

编辑

如果失败,请确保使用ctypes副本,GetLastError否则可能不正确。使用以下方法进行库引用:

winUSB = ctypes.WinDLL('winusb',use_last_error=True)

并使用:

ctypes.get_last_error()
于 2012-10-17T15:46:53.777 回答