mirror of
https://github.com/Qyriad/fusee-launcher.git
synced 2024-11-21 22:39:18 +01:00
Add Windows support with libusbK
This commit is contained in:
parent
8eaa3d4960
commit
62ff4dba45
@ -12,7 +12,7 @@
|
|||||||
# don't like it? suck it up, or find your own damned exploit ^-^
|
# don't like it? suck it up, or find your own damned exploit ^-^
|
||||||
#
|
#
|
||||||
# special thanks to:
|
# special thanks to:
|
||||||
# SciresM, motezazer -- guidance and support
|
# ScirèsM, motezazer -- guidance and support
|
||||||
# hedgeberg, andeor -- dumping the Jetson bootROM
|
# hedgeberg, andeor -- dumping the Jetson bootROM
|
||||||
# TuxSH -- for IDB notes that were nice to peek at
|
# TuxSH -- for IDB notes that were nice to peek at
|
||||||
#
|
#
|
||||||
@ -60,6 +60,9 @@ class HaxBackend:
|
|||||||
|
|
||||||
# USB constants used
|
# USB constants used
|
||||||
STANDARD_REQUEST_DEVICE_TO_HOST_TO_ENDPOINT = 0x82
|
STANDARD_REQUEST_DEVICE_TO_HOST_TO_ENDPOINT = 0x82
|
||||||
|
STANDARD_REQUEST_DEVICE_TO_HOST = 0x80
|
||||||
|
GET_DESCRIPTOR = 0x6
|
||||||
|
GET_CONFIGURATION = 0x8
|
||||||
|
|
||||||
# Interface requests
|
# Interface requests
|
||||||
GET_STATUS = 0x0
|
GET_STATUS = 0x0
|
||||||
@ -67,9 +70,8 @@ class HaxBackend:
|
|||||||
# List of OSs this class supports.
|
# List of OSs this class supports.
|
||||||
SUPPORTED_SYSTEMS = []
|
SUPPORTED_SYSTEMS = []
|
||||||
|
|
||||||
def __init__(self, usb_device, skip_checks=False):
|
def __init__(self, skip_checks=False):
|
||||||
""" Sets up the backend for the given device. """
|
""" Sets up the backend for the given device. """
|
||||||
self.dev = usb_device
|
|
||||||
self.skip_checks = skip_checks
|
self.skip_checks = skip_checks
|
||||||
|
|
||||||
|
|
||||||
@ -101,18 +103,37 @@ class HaxBackend:
|
|||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_appropriate_backend(cls, usb_device, system_override=None, skip_checks=False):
|
def create_appropriate_backend(cls, system_override=None, skip_checks=False):
|
||||||
""" Creates a backend object appropriate for the current OS. """
|
""" Creates a backend object appropriate for the current OS. """
|
||||||
|
|
||||||
# Search for a supportive backend, and try to create one.
|
# Search for a supportive backend, and try to create one.
|
||||||
for subclass in cls.__subclasses__():
|
for subclass in cls.__subclasses__():
|
||||||
if subclass.supported(system_override):
|
if subclass.supported(system_override):
|
||||||
return subclass(usb_device, skip_checks=skip_checks)
|
return subclass(skip_checks=skip_checks)
|
||||||
|
|
||||||
# ... if we couldn't, bail out.
|
# ... if we couldn't, bail out.
|
||||||
raise IOError("No backend to trigger the vulnerability-- it's likely we don't support your OS!")
|
raise IOError("No backend to trigger the vulnerability-- it's likely we don't support your OS!")
|
||||||
|
|
||||||
|
|
||||||
|
def read(self, length):
|
||||||
|
""" Reads data from the RCM protocol endpoint. """
|
||||||
|
return bytes(self.dev.read(0x81, length, 1000))
|
||||||
|
|
||||||
|
|
||||||
|
def write_single_buffer(self, data):
|
||||||
|
"""
|
||||||
|
Writes a single RCM buffer, which should be 0x1000 long.
|
||||||
|
The last packet may be shorter, and should trigger a ZLP (e.g. not divisible by 512).
|
||||||
|
If it's not, send a ZLP.
|
||||||
|
"""
|
||||||
|
return self.dev.write(0x01, data, 1000)
|
||||||
|
|
||||||
|
|
||||||
|
def find_device(self, vid=None, pid=None):
|
||||||
|
""" Set and return the device to be used """
|
||||||
|
self.dev = usb.core.find(idVendor=vid, idProduct=pid)
|
||||||
|
return self.dev
|
||||||
|
|
||||||
|
|
||||||
class MacOSBackend(HaxBackend):
|
class MacOSBackend(HaxBackend):
|
||||||
"""
|
"""
|
||||||
@ -274,11 +295,144 @@ class LinuxBackend(HaxBackend):
|
|||||||
raw = f.read()
|
raw = f.read()
|
||||||
return int(raw)
|
return int(raw)
|
||||||
|
|
||||||
|
class WindowsBackend(HaxBackend):
|
||||||
|
"""
|
||||||
|
Use libusbK for most of it, and use the handle libusbK gets for us to call kernel32's DeviceIoControl
|
||||||
|
"""
|
||||||
|
|
||||||
|
BACKEND_NAME = "Windows"
|
||||||
|
SUPPORTED_SYSTEMS = ["Windows"]
|
||||||
|
|
||||||
|
# Windows and libusbK specific constants
|
||||||
|
WINDOWS_FILE_DEVICE_UNKNOWN = 0x00000022
|
||||||
|
LIBUSBK_FUNCTION_CODE_GET_STATUS = 0x807
|
||||||
|
WINDOWS_METHOD_BUFFERED = 0
|
||||||
|
WINDOWS_FILE_ANY_ACCESS = 0
|
||||||
|
|
||||||
|
RAW_REQUEST_STRUCT_SIZE = 24 # 24 is how big the struct is, just trust me
|
||||||
|
TO_ENDPOINT = 2
|
||||||
|
|
||||||
|
# Yoinked (with love) from Windows' CTL_CODE macro
|
||||||
|
def win_ctrl_code(self, DeviceType, Function, Method, Access):
|
||||||
|
""" Return a control code for use with DeviceIoControl() """
|
||||||
|
return ((DeviceType) << 16 | ((Access) << 14) | ((Function)) << 2 | (Method))
|
||||||
|
|
||||||
|
def __init__(self, skip_checks):
|
||||||
|
import libusbK
|
||||||
|
self.libk = libusbK
|
||||||
|
# Grab libusbK
|
||||||
|
self.lib = ctypes.cdll.libusbK
|
||||||
|
|
||||||
|
|
||||||
# FIXME: Implement a Windows backend that talks to a patched version of libusbK
|
def find_device(self, Vid, Pid):
|
||||||
# so we can inject WdfUsbTargetDeviceSendControlTransferSynchronously to
|
"""
|
||||||
# trigger the exploit.
|
Windows version of this function
|
||||||
|
Its return isn't actually significant, but it needs to be not None
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Get a list of devices to use later
|
||||||
|
device_list = self.libk.KLST_HANDLE()
|
||||||
|
device_info = ctypes.pointer(self.libk.KLST_DEV_INFO())
|
||||||
|
ret = self.lib.LstK_Init(ctypes.byref(device_list), 0)
|
||||||
|
|
||||||
|
if ret == 0:
|
||||||
|
raise ctypes.WinError()
|
||||||
|
|
||||||
|
# Get info for a device with that vendor ID and product ID
|
||||||
|
device_info = ctypes.pointer(self.libk.KLST_DEV_INFO())
|
||||||
|
ret = self.lib.LstK_FindByVidPid(device_list, Vid, Pid, ctypes.byref(device_info))
|
||||||
|
self.lib.LstK_Free(ctypes.byref(device_list))
|
||||||
|
if device_info is None or ret == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Populate function pointers for use with the driver our device uses (which should be libusbK)
|
||||||
|
self.dev = self.libk.KUSB_DRIVER_API()
|
||||||
|
ret = self.lib.LibK_LoadDriverAPI(ctypes.byref(self.dev), device_info.contents.DriverID)
|
||||||
|
if ret == 0:
|
||||||
|
raise ctypes.WinError()
|
||||||
|
|
||||||
|
# Initialize the driver for use with our device
|
||||||
|
self.handle = self.libk.KUSB_HANDLE(None)
|
||||||
|
ret = self.dev.Init(ctypes.byref(self.handle), device_info)
|
||||||
|
if ret == 0:
|
||||||
|
raise self.libk.WinError()
|
||||||
|
|
||||||
|
return self.dev
|
||||||
|
|
||||||
|
|
||||||
|
def read(self, length):
|
||||||
|
""" Read using libusbK """
|
||||||
|
# Create the buffer to store what we read
|
||||||
|
buffer = ctypes.create_string_buffer(length)
|
||||||
|
|
||||||
|
len_transferred = ctypes.c_uint(0)
|
||||||
|
|
||||||
|
# Call libusbK's ReadPipe using our specially-crafted function pointer and the opaque device handle
|
||||||
|
ret = self.dev.ReadPipe(self.handle, ctypes.c_ubyte(0x81), ctypes.addressof(buffer), ctypes.c_uint(length), ctypes.byref(len_transferred), None)
|
||||||
|
|
||||||
|
if ret == 0:
|
||||||
|
raise ctypes.WinError()
|
||||||
|
|
||||||
|
return buffer.raw
|
||||||
|
|
||||||
|
def write_single_buffer(self, data):
|
||||||
|
""" Write using libusbK """
|
||||||
|
# Copy construct to a bytearray so we Know™ what type it is
|
||||||
|
buffer = bytearray(data)
|
||||||
|
|
||||||
|
# Convert wrap the data for use with ctypes
|
||||||
|
cbuffer = (ctypes.c_ubyte * len(buffer))(*buffer)
|
||||||
|
|
||||||
|
len_transferred = ctypes.c_uint(0)
|
||||||
|
|
||||||
|
# Call libusbK's WritePipe using our specially-crafted function pointer and the opaque device handle
|
||||||
|
ret = self.dev.WritePipe(self.handle, ctypes.c_ubyte(0x01), cbuffer, len(data), ctypes.byref(len_transferred), None)
|
||||||
|
if ret == 0:
|
||||||
|
raise ctypes.WinError()
|
||||||
|
|
||||||
|
def ioctl(self, driver_handle: ctypes.c_void_p, ioctl_code: ctypes.c_ulong, input_bytes: ctypes.c_void_p, input_bytes_count: ctypes.c_size_t, output_bytes: ctypes.c_void_p, output_bytes_count: ctypes.c_size_t):
|
||||||
|
""" Wrapper for DeviceIoControl """
|
||||||
|
overlapped = self.libk.OVERLAPPED()
|
||||||
|
ctypes.memset(ctypes.addressof(overlapped), 0, ctypes.sizeof(overlapped))
|
||||||
|
|
||||||
|
ret = ctypes.windll.kernel32.DeviceIoControl(driver_handle, ioctl_code, input_bytes, input_bytes_count, output_bytes, output_bytes_count, None, ctypes.byref(overlapped))
|
||||||
|
|
||||||
|
# We expect this to error, which matches the others ^_^
|
||||||
|
if ret == False:
|
||||||
|
raise ctypes.WinError()
|
||||||
|
|
||||||
|
def trigger_vulnerability(self, length):
|
||||||
|
"""
|
||||||
|
Go over libusbK's head and get the master handle it's been using internally
|
||||||
|
and perform a direct DeviceIoControl call to the kernel to skip the length check
|
||||||
|
"""
|
||||||
|
# self.handle is KUSB_HANDLE, cast to KUSB_HANDLE_INTERNAL to transparent-ize it
|
||||||
|
internal = ctypes.cast(self.handle, ctypes.POINTER(self.libk.KUSB_HANDLE_INTERNAL))
|
||||||
|
|
||||||
|
# Get the handle libusbK has been secretly using in its ioctl calls this whole time
|
||||||
|
master_handle = internal.contents.Device.contents.MasterDeviceHandle
|
||||||
|
|
||||||
|
if master_handle is None or master_handle == self.libk.INVALID_HANDLE_VALUE:
|
||||||
|
raise ValueError("Failed to initialize master handle")
|
||||||
|
|
||||||
|
# the raw request struct is pretty annoying, so I'm just going to allocate enough memory and set the few fields I need
|
||||||
|
raw_request = ctypes.create_string_buffer(self.RAW_REQUEST_STRUCT_SIZE)
|
||||||
|
|
||||||
|
# set timeout to 1000 ms, timeout offset is 0 (since it's the first member), and it's an unsigned int
|
||||||
|
timeout_p = ctypes.cast(raw_request, ctypes.POINTER(ctypes.c_uint))
|
||||||
|
timeout_p.contents = ctypes.c_ulong(1000) # milliseconds
|
||||||
|
|
||||||
|
status_p = ctypes.cast(ctypes.byref(raw_request, 4), ctypes.POINTER(self.libk.status_t))
|
||||||
|
status_p.contents.index = self.GET_STATUS
|
||||||
|
status_p.contents.recipient = self.TO_ENDPOINT
|
||||||
|
|
||||||
|
buffer = ctypes.create_string_buffer(length)
|
||||||
|
|
||||||
|
code = self.win_ctrl_code(self.WINDOWS_FILE_DEVICE_UNKNOWN, self.LIBUSBK_FUNCTION_CODE_GET_STATUS, self.WINDOWS_METHOD_BUFFERED, self.WINDOWS_FILE_ANY_ACCESS)
|
||||||
|
ret = self.ioctl(master_handle, ctypes.c_ulong(code), raw_request, ctypes.c_size_t(24), buffer, ctypes.c_size_t(length))
|
||||||
|
|
||||||
|
if ret == False:
|
||||||
|
raise ctypes.WinError()
|
||||||
|
|
||||||
|
|
||||||
class RCMHax:
|
class RCMHax:
|
||||||
@ -287,11 +441,6 @@ class RCMHax:
|
|||||||
DEFAULT_VID = 0x0955
|
DEFAULT_VID = 0x0955
|
||||||
DEFAULT_PID = 0x7321
|
DEFAULT_PID = 0x7321
|
||||||
|
|
||||||
# USB constants used
|
|
||||||
STANDARD_REQUEST_DEVICE_TO_HOST_TO_DEVICE = 0x80
|
|
||||||
GET_DESCRIPTOR = 0x6
|
|
||||||
GET_CONFIGURATION = 0x8
|
|
||||||
|
|
||||||
# Exploit specifics
|
# Exploit specifics
|
||||||
COPY_BUFFER_ADDRESSES = [0x40005000, 0x40009000] # The addresses of the DMA buffers we can trigger a copy _from_.
|
COPY_BUFFER_ADDRESSES = [0x40005000, 0x40009000] # The addresses of the DMA buffers we can trigger a copy _from_.
|
||||||
STACK_END = 0x40010000 # The address just after the end of the device's stack.
|
STACK_END = 0x40010000 # The address just after the end of the device's stack.
|
||||||
@ -302,12 +451,19 @@ class RCMHax:
|
|||||||
# The first write into the bootROM touches the lowbuffer.
|
# The first write into the bootROM touches the lowbuffer.
|
||||||
self.current_buffer = 0
|
self.current_buffer = 0
|
||||||
|
|
||||||
# Grab a connection to the USB device itself.
|
|
||||||
self.dev = self._find_device(vid, pid)
|
|
||||||
|
|
||||||
# Keep track of the total amount written.
|
# Keep track of the total amount written.
|
||||||
self.total_written = 0
|
self.total_written = 0
|
||||||
|
|
||||||
|
# Create a vulnerability backend for the given device.
|
||||||
|
try:
|
||||||
|
self.backend = HaxBackend.create_appropriate_backend(system_override=os_override, skip_checks=override_checks)
|
||||||
|
except IOError:
|
||||||
|
print("It doesn't look like we support your OS, currently. Sorry about that!\n")
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
# Grab a connection to the USB device itself.
|
||||||
|
self.dev = self._find_device(vid, pid)
|
||||||
|
|
||||||
# If we don't have a device...
|
# If we don't have a device...
|
||||||
if self.dev is None:
|
if self.dev is None:
|
||||||
|
|
||||||
@ -315,19 +471,12 @@ class RCMHax:
|
|||||||
if wait_for_device:
|
if wait_for_device:
|
||||||
print("Waiting for a TegraRCM device to come online...")
|
print("Waiting for a TegraRCM device to come online...")
|
||||||
while self.dev is None:
|
while self.dev is None:
|
||||||
self.dev = self._find_device()
|
self.dev = self._find_device(vid, pid)
|
||||||
|
|
||||||
# ... or bail out.
|
# ... or bail out.
|
||||||
else:
|
else:
|
||||||
raise IOError("No TegraRCM device found?")
|
raise IOError("No TegraRCM device found?")
|
||||||
|
|
||||||
# Create a vulnerability backend for the given device.
|
|
||||||
try:
|
|
||||||
self.backend = HaxBackend.create_appropriate_backend(self.dev, system_override=os_override, skip_checks=override_checks)
|
|
||||||
except IOError:
|
|
||||||
print("It doesn't look like we support your OS, currently. Sorry about that!\n")
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
# Print any use-related warnings.
|
# Print any use-related warnings.
|
||||||
self.backend.print_warnings()
|
self.backend.print_warnings()
|
||||||
|
|
||||||
@ -343,15 +492,11 @@ class RCMHax:
|
|||||||
pid = pid if pid else self.DEFAULT_PID
|
pid = pid if pid else self.DEFAULT_PID
|
||||||
|
|
||||||
# ... and use them to find a USB device.
|
# ... and use them to find a USB device.
|
||||||
return usb.core.find(idVendor=vid, idProduct=pid)
|
return self.backend.find_device(vid, pid)
|
||||||
|
|
||||||
|
|
||||||
def get_device_descriptor(self):
|
|
||||||
return self.dev.ctrl_transfer(self.STANDARD_REQUEST_DEVICE_TO_HOST, self.GET_DESCRIPTOR, 1 << 8, 0, 18)
|
|
||||||
|
|
||||||
def read(self, length):
|
def read(self, length):
|
||||||
""" Reads data from the RCM protocol endpoint. """
|
""" Reads data from the RCM protocol endpoint. """
|
||||||
return self.dev.read(0x81, length, 1000)
|
return self.backend.read(length)
|
||||||
|
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data):
|
||||||
@ -376,7 +521,7 @@ class RCMHax:
|
|||||||
If it's not, send a ZLP.
|
If it's not, send a ZLP.
|
||||||
"""
|
"""
|
||||||
self._toggle_buffer()
|
self._toggle_buffer()
|
||||||
return self.dev.write(0x01, data, 1000)
|
return self.backend.write_single_buffer(data)
|
||||||
|
|
||||||
|
|
||||||
def _toggle_buffer(self):
|
def _toggle_buffer(self):
|
||||||
@ -452,7 +597,7 @@ except IOError as e:
|
|||||||
|
|
||||||
# Print the device's ID. Note that reading the device's ID is necessary to get it into
|
# Print the device's ID. Note that reading the device's ID is necessary to get it into
|
||||||
try:
|
try:
|
||||||
device_id = switch.read_device_id().tostring()
|
device_id = switch.read_device_id()
|
||||||
print("Found a Tegra with Device ID: {}".format(device_id))
|
print("Found a Tegra with Device ID: {}".format(device_id))
|
||||||
except usb.core.USBError as e:
|
except usb.core.USBError as e:
|
||||||
# Raise the exception only if we're not being permissive about ID reads.
|
# Raise the exception only if we're not being permissive about ID reads.
|
||||||
|
190
libusbK.py
Normal file
190
libusbK.py
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
# This file is part of Fusée Launcher
|
||||||
|
# Copyright (C) 2018 Mikaela Szekely <qyriad@gmail.com>
|
||||||
|
# Copyright (C) 2018 Kate Temkin <k@ktemkin.com>
|
||||||
|
# Fusée Launcher is licensed under the terms of the GNU GPLv2
|
||||||
|
|
||||||
|
from ctypes import *
|
||||||
|
|
||||||
|
KLST_HANDLE = c_void_p
|
||||||
|
KUSB_HANDLE = c_void_p
|
||||||
|
INVALID_HANDLE_VALUE = -1
|
||||||
|
|
||||||
|
class DUMMYSTRUCTNAME(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Offset", c_ulong),
|
||||||
|
("OfsettHigh", c_ulong)
|
||||||
|
]
|
||||||
|
|
||||||
|
class DUMMYUNIONNAME(Union):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("DUMMYSTRUCTNAME", DUMMYSTRUCTNAME),
|
||||||
|
("Pointer", c_void_p)
|
||||||
|
]
|
||||||
|
|
||||||
|
class OVERLAPPED(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Internal", POINTER(c_ulong)),
|
||||||
|
("InternalHigh", POINTER(c_ulong)),
|
||||||
|
("DUMMYUNIONNAME", DUMMYUNIONNAME),
|
||||||
|
("hEvent", c_void_p)
|
||||||
|
]
|
||||||
|
|
||||||
|
class KLST_DEV_COMMON_INFO(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Vid", c_int),
|
||||||
|
("Pid", c_int),
|
||||||
|
("MI", c_int),
|
||||||
|
("InstanceID", c_char * 256)
|
||||||
|
]
|
||||||
|
|
||||||
|
class KLST_DEV_INFO(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Common", KLST_DEV_COMMON_INFO),
|
||||||
|
("DriverID", c_int),
|
||||||
|
("DeviceInterfaceGUID", c_char * 256),
|
||||||
|
("DeviceID", c_char * 256),
|
||||||
|
("ClassGUID", c_char * 256),
|
||||||
|
("Mfg", c_char * 256),
|
||||||
|
("DeviceDesc", c_char * 256),
|
||||||
|
("Service", c_char * 256),
|
||||||
|
("SymbolicLink", c_char * 256),
|
||||||
|
("DevicePath", c_char * 256),
|
||||||
|
("LUsb0FilterIndex", c_int),
|
||||||
|
("Connected", c_bool),
|
||||||
|
("KLST_SYNC_FLAG", c_int),
|
||||||
|
("BusNumber", c_int),
|
||||||
|
("DeviceAddress", c_int),
|
||||||
|
("SerialNumber", c_char * 256)
|
||||||
|
]
|
||||||
|
|
||||||
|
class KUSB_DRIVER_API_INFO(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("DriverID", c_int),
|
||||||
|
("FunctionCount", c_int)
|
||||||
|
]
|
||||||
|
|
||||||
|
class KUSB_DRIVER_API(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Info", KUSB_DRIVER_API_INFO),
|
||||||
|
("Init", WINFUNCTYPE(c_bool, KUSB_HANDLE, POINTER(KLST_DEV_INFO))),
|
||||||
|
("Free", c_void_p), # Unused, but pointer sized
|
||||||
|
("ClaimInterface", c_void_p), # Unused, but pointer sized
|
||||||
|
("ReleaseInterface", c_void_p), # Unused, but pointer sized
|
||||||
|
("SetAltInterface", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetAltInterface", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetDescriptor", c_void_p), # Unused, but pointer sized
|
||||||
|
("ControlTransfer", c_void_p), # Unused, but pointer sized
|
||||||
|
("SetPowerPolicy", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetPowerPolicy", c_void_p), # Unused, but pointer sized
|
||||||
|
("SetConfiguration", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetConfiguration", c_void_p), # Unused, but pointer sized
|
||||||
|
("ResetDevice", c_void_p), # Unused, but pointer sized
|
||||||
|
("Initialize", c_void_p), # Unused, but pointer sized
|
||||||
|
("SelectInterface", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetAssociatedInterface", c_void_p), # Unused, but pointer sized
|
||||||
|
("Clone", c_void_p), # Unused, but pointer sized
|
||||||
|
("QueryInterfaceSettings", c_void_p), # Unused, but pointer sized
|
||||||
|
("QueryDeviceInformation", c_void_p), # Unused, but pointer sized
|
||||||
|
("SetCurrentAlternateSetting", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetCurrentAlternateSetting", c_void_p), # Unused, but pointer sized
|
||||||
|
("QueryPipe", c_void_p), # Unused, but pointer sized
|
||||||
|
("SetPipePolicy", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetPipePolicy", c_void_p), # Unused, but pointer sized
|
||||||
|
|
||||||
|
# BOOL KUSB_API ReadPipe(_in_ KUSB_HANDLE InterfaceHandle, _in_ UCHAR PipeID, _out_ PUCHAR Buffer, _in_ UINT BufferLength, _outopt_ PUINT LengthTransferred, _intopt_ LPOVERLAPPED Overlapped)
|
||||||
|
("ReadPipe", WINFUNCTYPE(c_bool, KUSB_HANDLE, c_ubyte, c_void_p, c_uint, POINTER(c_uint), POINTER(OVERLAPPED))),
|
||||||
|
|
||||||
|
# BOOL KUSB_API WritePipe(_in_ KUSB_HANDLE InterfaceHandle, _in_ UCHAR PipeID, _in_ PUCHAR Buffer, _in_ UINT BufferLength, _outopt_ PUINT LengthTransferred, _inopt_ LPOVERLAPPED Overlapped)
|
||||||
|
("WritePipe", WINFUNCTYPE(c_bool, KUSB_HANDLE, c_ubyte, POINTER(c_ubyte), c_uint, POINTER(c_uint), POINTER(OVERLAPPED))),
|
||||||
|
|
||||||
|
("ResetPipe", c_void_p), # Unused, but pointer sized
|
||||||
|
("AbortPipe", c_void_p), # Unused, but pointer sized
|
||||||
|
("FlushPipe", c_void_p), # Unused, but pointer sized
|
||||||
|
("IsoReadPipe", c_void_p), # Unused, but pointer sized
|
||||||
|
("IsoWritePipe", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetCurrentFrameNumber", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetOverlappedResult", c_void_p), # Unused, but pointer sized
|
||||||
|
("GetProperty", c_void_p), # Unused, but pointer sized
|
||||||
|
|
||||||
|
# 34: Amount of functions in this struct
|
||||||
|
("z_F_i_x_e_d", c_ubyte * (512 - (sizeof(KUSB_DRIVER_API_INFO) - sizeof(POINTER(c_uint)) * 34)))
|
||||||
|
]
|
||||||
|
|
||||||
|
class Evt_t(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Cleanup", c_void_p)
|
||||||
|
]
|
||||||
|
|
||||||
|
class Count_t(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Use", c_ulong),
|
||||||
|
("Ref", c_ulong)
|
||||||
|
]
|
||||||
|
|
||||||
|
class User_t(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Valid", c_int), # BOOL
|
||||||
|
("CleanupCB", c_void_p), # Unused, but pointer sized
|
||||||
|
("Context", c_void_p) # Unused, but pointer sized
|
||||||
|
]
|
||||||
|
|
||||||
|
class KOBJ_BASE(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Disposing", c_ulong),
|
||||||
|
("Evt", Evt_t),
|
||||||
|
("Count", Count_t),
|
||||||
|
("User", User_t)
|
||||||
|
]
|
||||||
|
|
||||||
|
class KDEV_HANDLE_INTERNAL(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Base", KOBJ_BASE),
|
||||||
|
("MasterDeviceHandle", c_void_p),
|
||||||
|
("MasterInterfaceHandle", c_void_p),
|
||||||
|
("DevicePath", c_char_p),
|
||||||
|
("ConfigDescriptor", c_void_p), # Unused, pointer sized
|
||||||
|
("SharedInterfaces", c_void_p),
|
||||||
|
("DriverAPI", POINTER(KUSB_DRIVER_API)),
|
||||||
|
("UsbStack", c_void_p), # Unused, pointer sized
|
||||||
|
("Backend", c_void_p), # Unused, pointer sized
|
||||||
|
]
|
||||||
|
|
||||||
|
class Move_t(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("End", c_int),
|
||||||
|
("InterfaceEL", c_void_p), # Unused, pointer sized
|
||||||
|
("AltInterfaceEL", c_void_p), # Unused, pointer sized
|
||||||
|
("PipeEL", c_void_p), # Unused, pointer sized
|
||||||
|
]
|
||||||
|
|
||||||
|
class KUSB_HANDLE_INTERNAL(Structure):
|
||||||
|
""" What KUSB_HANDLE actually points to """
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("Base", KOBJ_BASE),
|
||||||
|
("Device", POINTER(KDEV_HANDLE_INTERNAL)),
|
||||||
|
("Selected_SharedInterface_Index", c_long),
|
||||||
|
("IsClone", c_int), # BOOL
|
||||||
|
("Move", Move_t)
|
||||||
|
]
|
||||||
|
|
||||||
|
class status_t(Structure):
|
||||||
|
_fields_ = \
|
||||||
|
[
|
||||||
|
("recipient", c_uint),
|
||||||
|
("index", c_uint),
|
||||||
|
("status", c_uint)
|
||||||
|
]
|
Loading…
Reference in New Issue
Block a user