问题
I've been following the WinUsb MSDN HowTo here and so far it's worked pretty well. I've made it to the point in the guide where I have to call the WinUsb_Initialize() function from the WinUsb DLL. And that's where I'm stuck. My code so far is this, and you will doubtlessly ascertain that I've ripped a great deal of it screaming from the WinAPI.py module of PyWinUSB. Insert gratuitous thanks and giving credit to the creator of PyWinUSB here.
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?>)
I've tried creating a simple handle and passing that byref(handle) as the second parameter to the function, but the handle value stays as None. I don't know how much has been done with Python and WinUSB.DLL but if anyone can point me in the correct direction I'd be sincerely grateful.
Thanks in advance.
回答1:
The documentation says it is a PWINUSB_INTERFACE_HANDLE, which is a PVOID, which is a c_void_p
in ctypes
, so this should work:
h = ctypes.c_void_p()
winUSB.WinUsb_Initialize(winUSBHandle, ctypes.byref(h))
Does the winUSBHandle
look valid (not 0 or -1 or 0xFFFFFFFF)?
Edit
If it is failing, make sure to use the ctypes
copy of GetLastError
or it may be incorrect. Make the library references with:
winUSB = ctypes.WinDLL('winusb',use_last_error=True)
and use:
ctypes.get_last_error()
来源:https://stackoverflow.com/questions/12926923/winusb-dll-and-python-specifically-winusb-initialize