From ccfd1b4a82fe3cdcb9fdbaded1c589dfdaeefd6f Mon Sep 17 00:00:00 2001 From: radiomanV Date: Sat, 12 May 2018 23:07:40 +0300 Subject: [PATCH] TL866II Wine implementation --- wine/{ => TL866}/Makefile | 0 wine/{ => TL866}/readme | 0 wine/{ => TL866}/setupapi.dll | Bin wine/{ => TL866}/usb.c | 0 wine/TL866II/Makefile | 111 ++++++++ wine/TL866II/readme | 22 ++ wine/TL866II/setupapi.dll | Bin 0 -> 89012 bytes wine/TL866II/usb.c | 505 ++++++++++++++++++++++++++++++++++ 8 files changed, 638 insertions(+) rename wine/{ => TL866}/Makefile (100%) rename wine/{ => TL866}/readme (100%) rename wine/{ => TL866}/setupapi.dll (100%) rename wine/{ => TL866}/usb.c (100%) create mode 100644 wine/TL866II/Makefile create mode 100644 wine/TL866II/readme create mode 100755 wine/TL866II/setupapi.dll create mode 100644 wine/TL866II/usb.c diff --git a/wine/Makefile b/wine/TL866/Makefile similarity index 100% rename from wine/Makefile rename to wine/TL866/Makefile diff --git a/wine/readme b/wine/TL866/readme similarity index 100% rename from wine/readme rename to wine/TL866/readme diff --git a/wine/setupapi.dll b/wine/TL866/setupapi.dll similarity index 100% rename from wine/setupapi.dll rename to wine/TL866/setupapi.dll diff --git a/wine/usb.c b/wine/TL866/usb.c similarity index 100% rename from wine/usb.c rename to wine/TL866/usb.c diff --git a/wine/TL866II/Makefile b/wine/TL866II/Makefile new file mode 100644 index 0000000..1758e2c --- /dev/null +++ b/wine/TL866II/Makefile @@ -0,0 +1,111 @@ +### Generated by Winemaker 0.8.4 +### +### Invocation command line was +### /usr/bin/winemaker -lusb-1.0 -ludev --dll --nosource-fix --nobackup --nomsvcrt --nodlls ./ + + +SRCDIR = . +SUBDIRS = +DLLS = usb.dll +LIBS = +EXES = + + + +### Common settings + +CEXTRA =-m32 -mincoming-stack-boundary=2 +CXXEXTRA = +RCEXTRA = +DEFINES = +INCLUDE_PATH = +DLL_PATH = +DLL_IMPORTS = +LIBRARY_PATH = +LIBRARIES = -lusb-1.0 -ludev + + +### usb.dll sources and settings + +usb_dll_MODULE = usb.dll +usb_dll_C_SRCS = usb.c +usb_dll_CXX_SRCS = +usb_dll_RC_SRCS = +usb_dll_LDFLAGS = -shared -m32 +usb_dll_ARFLAGS = +usb_dll_DLL_PATH = +usb_dll_DLLS = +usb_dll_LIBRARY_PATH = +usb_dll_LIBRARIES = + +usb_dll_OBJS = $(usb_dll_C_SRCS:.c=.o) \ + $(usb_dll_CXX_SRCS:.cpp=.o) \ + $(usb_dll_RC_SRCS:.rc=.res) + + + +### Global source lists + +C_SRCS = $(usb_dll_C_SRCS) +CXX_SRCS = $(usb_dll_CXX_SRCS) +RC_SRCS = $(usb_dll_RC_SRCS) + + +### Tools + +CC = winegcc +CXX = wineg++ +RC = wrc +AR = ar + + +### Generic targets + +all: $(SUBDIRS) $(DLLS:%=%.so) $(LIBS) $(EXES) + +### Build rules + +.PHONY: all clean dummy + +$(SUBDIRS): dummy + @cd $@ && $(MAKE) + +# Implicit rules + +.SUFFIXES: .cpp .cxx .rc .res +DEFINCL = $(INCLUDE_PATH) $(DEFINES) $(OPTIONS) + +.c.o: + $(CC) -c $(CFLAGS) $(CEXTRA) $(DEFINCL) -o $@ $< + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(CXXEXTRA) $(DEFINCL) -o $@ $< + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(CXXEXTRA) $(DEFINCL) -o $@ $< + +.rc.res: + $(RC) $(RCFLAGS) $(RCEXTRA) $(DEFINCL) -fo$@ $< + +# Rules for cleaning + +CLEAN_FILES = y.tab.c y.tab.h lex.yy.c core *.orig *.rej \ + \\\#*\\\# *~ *% .\\\#* + +clean:: $(SUBDIRS:%=%/__clean__) $(EXTRASUBDIRS:%=%/__clean__) + $(RM) $(CLEAN_FILES) $(RC_SRCS:.rc=.res) $(C_SRCS:.c=.o) $(CXX_SRCS:.cpp=.o) + $(RM) $(DLLS:%=%.so) $(LIBS) $(EXES) $(EXES:%=%.so) + +$(SUBDIRS:%=%/__clean__): dummy + cd `dirname $@` && $(MAKE) clean + +$(EXTRASUBDIRS:%=%/__clean__): dummy + -cd `dirname $@` && $(RM) $(CLEAN_FILES) + +### Target specific build rules +DEFLIB = $(LIBRARY_PATH) $(LIBRARIES) $(DLL_PATH) $(DLL_IMPORTS:%=-l%) + +$(usb_dll_MODULE).so: $(usb_dll_OBJS) + $(CC) $(usb_dll_LDFLAGS) -o $@ $(usb_dll_OBJS) $(usb_dll_LIBRARY_PATH) $(usb_dll_DLL_PATH) $(DEFLIB) $(usb_dll_DLLS:%=-l%) $(usb_dll_LIBRARIES:%=-l%) + + diff --git a/wine/TL866II/readme b/wine/TL866II/readme new file mode 100644 index 0000000..8c4cfb1 --- /dev/null +++ b/wine/TL866II/readme @@ -0,0 +1,22 @@ +Simple low level winelib usb wrapper for Xgpro V7.xx +This version will autodetect the Xgpro.exe version. + +Add the following rule to the udev subsystem: +open terminal and as root type: +#echo 'SUBSYSTEMS=="usb", ATTRS{idVendor}=="a466", ATTRS{idProduct}=="0a53", GROUP="plugdev", MODE="0666"' > /etc/udev/rules.d/51-minipro.rules +#udevadm trigger + + +How to install: +1. Install wine +2. Copy the provided setupapi.dll file in the minipro folder +3. Run the Minipro.exe + + +How to compile: +1. Install wine, wine-devel, libusb-devel, libudev-devel packages +2. Run make +3. Rename usb.dll.so as setupapi.dll and copy this file in the minipro folder +4. Run the Minipro.exe + + diff --git a/wine/TL866II/setupapi.dll b/wine/TL866II/setupapi.dll new file mode 100755 index 0000000000000000000000000000000000000000..5fd1864c4ede722fef934ff30defb529401ee8e3 GIT binary patch literal 89012 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 literal 0 HcmV?d00001 diff --git a/wine/TL866II/usb.c b/wine/TL866II/usb.c new file mode 100644 index 0000000..4f50bf8 --- /dev/null +++ b/wine/TL866II/usb.c @@ -0,0 +1,505 @@ +#define __WINESRC__ +#define __CYGWIN__ +#define _GNU_SOURCE + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define TL866_VID 0xA466 +#define TL866_PID 0x0A53 + + +typedef struct { +HANDLE InterfaceHandle; +UCHAR PipeID; +PUCHAR Buffer; +ULONG BufferLength; +PULONG LengthTransferred; +LPOVERLAPPED Overlapped; +}Args; + +//replacement functions for minipro. Function prototypes and calling convention must be the same as in Xgpro.exe, otherwise the application will crash. +int open_devices(int *error); +void close_devices(); +HANDLE __stdcall RegisterDeviceNotifications(HANDLE hRecipient, LPVOID NotificationFilter, DWORD Flags); +BOOL __stdcall WinUsb_SetPipePolicy(HANDLE InterfaceHandle, UCHAR PipeID, ULONG PolicyType, ULONG ValueLength, PVOID Value); +BOOL __stdcall WinUsb_Transfer(HANDLE InterfaceHandle, UCHAR PipeID, PUCHAR Buffer, ULONG BufferLength, PULONG LengthTransferred, LPOVERLAPPED Overlapped); + +//helper functions +BOOL patch_minipro(); +BOOL patch_function(char *library, char *func, void *funcaddress); +void async_transfer(Args *args); +void notifier_function(); +int get_device_count(); + + +//Global variables +libusb_device_handle *device_handle[4]; +libusb_context *ctx; +libusb_device **devs; + +HANDLE h_thread; + +HWND hWnd; +BOOL cancel; +HANDLE *usb_handle; +HANDLE *winusb_handle; +int *devices_count; + +//These are functions signature extracted from Xgpro.exe and should be compatible from V7.0 and above. +const unsigned char open_devices_pattern[] = { 0x53,0x57,0x6A,0x00,0x68,0x80,0x00,0x00,0x40,0x6A,0x03,0x6A,0x00,0x6A,0x03,0x68 }; + + + +BOOL patch_function(char *library, char *func, void *funcaddress) +{ + DWORD dwOldProtection; + DWORD func_addr = 0; + + void *BaseAddress = GetModuleHandleA(NULL); + PIMAGE_NT_HEADERS NtHeader = (PIMAGE_NT_HEADERS)((PBYTE)BaseAddress + ((PIMAGE_DOS_HEADER)BaseAddress)->e_lfanew); + PIMAGE_IMPORT_DESCRIPTOR ImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)((PBYTE)BaseAddress + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); + + //Search for library in the IAT + while (ImpDesc->Characteristics && ImpDesc->Name) { + if (strcasecmp(BaseAddress + ImpDesc->Name, library) == 0) { + break;//Found it! + } + ImpDesc++; + } + + + //check if the library was found in the IAT + if(!ImpDesc->Characteristics) + { + printf("%s was not found in the IAT.\n", library); + return FALSE;//nope, exit with error. + } + + //Get the address of function in library + DWORD_PTR ProcAddress = (DWORD_PTR)GetProcAddress(GetModuleHandleA(library), func); + + //Find the address in the thunk table + PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)(BaseAddress + ImpDesc->FirstThunk); + while (thunk->u1.Function) + { + if ((DWORD_PTR)thunk->u1.Function == ProcAddress) + { + //if found, patch it to point to our custom function + MEMORY_BASIC_INFORMATION info; + VirtualQuery(&thunk->u1.Function, &info, sizeof(MEMORY_BASIC_INFORMATION)); + VirtualProtect(info.BaseAddress, info.RegionSize, PAGE_READWRITE, &dwOldProtection); + func_addr = thunk->u1.Function; + thunk->u1.Function = (DWORD_PTR)funcaddress; + VirtualProtect(info.BaseAddress, info.RegionSize, info.Protect, &dwOldProtection); + + } + + thunk++; + } + + //check if the patch was ok. + if (!func_addr) + { + printf("%s was not found in %s.\n", func, library); + return FALSE;//nope, exit with error. + } + + + return TRUE; +} + + +//Patcher function. Called from DllMain. Return TRUE if patch was ok and continue with program loading or FALSE to exit with error. +BOOL patch_minipro() +{ + + //Get the BaseAddress, NT Header and Image Import Descriptor + void *BaseAddress = GetModuleHandleA(NULL); + PIMAGE_NT_HEADERS NtHeader = (PIMAGE_NT_HEADERS)((PBYTE)BaseAddress + ((PIMAGE_DOS_HEADER)BaseAddress)->e_lfanew); + + //Patch the Linux incompatible functions functions + if(!patch_function("user32.dll", "RegisterDeviceNotificationA", &RegisterDeviceNotifications)) + return FALSE; + + if(!patch_function("winusb.dll", "WinUsb_SetPipePolicy", &WinUsb_SetPipePolicy)) + return FALSE; + + if(!patch_function("winusb.dll", "WinUsb_WritePipe", &WinUsb_Transfer)) + return FALSE; + + if(!patch_function("winusb.dll", "WinUsb_ReadPipe", &WinUsb_Transfer)) + return FALSE; + + + //Searching for functions signature in code section. + void *p_opendevices = memmem(BaseAddress + NtHeader->OptionalHeader.BaseOfCode, NtHeader->OptionalHeader.SizeOfCode, &open_devices_pattern, sizeof(open_devices_pattern)) - 0x1D; + void *p_closedevices = (void*)(*(int*)((unsigned char*)p_opendevices + 5)) + (DWORD)((unsigned char*)p_opendevices + 9); + void *p_winusbhandle = (void*)(*(int*)((unsigned char*)p_closedevices + 0x12)); + void *p_usbhandle = (void*)(*(int*)((unsigned char*)p_closedevices + 0x2)); + void *p_devicescount= (void*)(*(int*)((unsigned char*)p_opendevices + 0xAF)); + + //check if all pointers are o.k. + if (!p_opendevices) + { + printf("Functions signature not found! Unknown MiniPro version.\n"); + return FALSE;//nope, exit with error. + } + + + //Print debug info. + unsigned char *version = memmem(BaseAddress, NtHeader->OptionalHeader.SizeOfImage, "Xgpro v", 7); + if (version) printf("Found %s\n", version); + printf("Base Address = 0x%08X\n", (DWORD)BaseAddress); + printf("Code section = 0x%08X,0x%08X\n", (DWORD)BaseAddress + NtHeader->OptionalHeader.BaseOfCode, (DWORD)NtHeader->OptionalHeader.SizeOfCode); + printf("Open Devices found at 0x%08X\n", (DWORD)p_opendevices); + printf("Close Devices found at 0x%08X\n", (DWORD)p_closedevices); + printf("Usb Handle found at 0x%08X\n", (DWORD)p_usbhandle); + printf("WinUsb Handle found at 0x%08X\n", (DWORD)p_winusbhandle); + printf("Devices count found at 0x%08X\n", (DWORD)p_devicescount); + + + //Patch all low level functions in MiniPro.exe to point to our custom functions. + BYTE t[] = { 0x68, 0, 0, 0, 0, 0xc3 };// push xxxx, ret; an absolute Jump replacement. + DWORD *p_func = (DWORD*)&t[1]; + DWORD dwOldProtection; + + //Initialize the usb handle address. + usb_handle = p_usbhandle; + winusb_handle = p_winusbhandle; + devices_count = p_devicescount; + VirtualProtect(BaseAddress + NtHeader->OptionalHeader.BaseOfCode, NtHeader->OptionalHeader.SizeOfCode, PAGE_READWRITE, &dwOldProtection);//unprotect the code memory section + + //patch Open_Devices function + *p_func = (DWORD)&open_devices; + memcpy(p_opendevices, t, 6); + + //patch close_devices function + *p_func = (DWORD)&close_devices; + memcpy(p_closedevices, t, 6); + + VirtualProtect(BaseAddress + NtHeader->OptionalHeader.BaseOfCode, NtHeader->OptionalHeader.SizeOfCode, dwOldProtection, &dwOldProtection);//restore the old protection + return TRUE; +} + + + +//Minipro replacement functions +int open_devices(int *error) +{ + printf("Open devices.\n"); + close_devices(); + device_handle[0] = NULL; + device_handle[1] = NULL; + device_handle[2] = NULL; + device_handle[3] = NULL; + devs = NULL; + + libusb_init(&ctx);//initialize a new session + libusb_set_debug(ctx, 3);//set verbosity level + + + usb_handle[0] = INVALID_HANDLE_VALUE; + usb_handle[1] = INVALID_HANDLE_VALUE; + usb_handle[2] = INVALID_HANDLE_VALUE; + usb_handle[3] = INVALID_HANDLE_VALUE; + + winusb_handle[0] = INVALID_HANDLE_VALUE; + winusb_handle[1] = INVALID_HANDLE_VALUE; + winusb_handle[2] = INVALID_HANDLE_VALUE; + winusb_handle[3] = INVALID_HANDLE_VALUE; + + *devices_count = 0; + + int devices_found = 0, i, ret; + struct libusb_device_descriptor desc; + int count = libusb_get_device_list(ctx, &devs); + + if (count < 0) { + return 0; + } + + + for (i = 0; i < count; i++) { + ret = libusb_get_device_descriptor(devs[i], &desc); + if (ret != LIBUSB_SUCCESS) + { + return 0; + } + + if (TL866_PID == desc.idProduct && TL866_VID == desc.idVendor) + { + if (libusb_open(devs[i], &device_handle[devices_found]) == LIBUSB_SUCCESS && + libusb_claim_interface(device_handle[devices_found], 0) == LIBUSB_SUCCESS) + { + usb_handle[devices_found] = (HANDLE)devices_found; + winusb_handle[devices_found] = (HANDLE)devices_found; + devices_found++; + *devices_count = devices_found; + if (devices_found == 4) + return 0; + } + } + + } + return 0; +} + + + +void close_devices() +{ + printf("Close devices.\n"); + if (devs != NULL) + { + + int i;; + for (i = 0; i < 4; i++) + { + if (device_handle[i] != NULL) + { + //libusb_release_interface(device_handle[i], 0); + libusb_close(device_handle[i]); + device_handle[i] = NULL; + } + } + libusb_free_device_list(devs, 1); + libusb_exit(ctx);//close session + devs = NULL;; + } +} + + + +HANDLE __stdcall RegisterDeviceNotifications(HANDLE hRecipient, LPVOID NotificationFilter, DWORD Flags) +{ + + printf("RegisterDeviceNotifications hWnd=%X4\n", (unsigned int)hRecipient); + hWnd = hRecipient; + h_thread = CreateThread(NULL, 0, (void*)notifier_function, NULL, 0, NULL); + if(! h_thread) + printf("Thread notifier failed.\n"); + + return 0; +} + + + +//winusb implemented functions. +BOOL __stdcall WinUsb_SetPipePolicy(HANDLE InterfaceHandle, UCHAR PipeID, ULONG PolicyType, ULONG ValueLength, PVOID Value) +{ + return TRUE; +} + + +//Asynchronous transfer for WinUsb_ReadPipe/WinUsb_WritePipe. +void async_transfer(Args *args) +{ + libusb_bulk_transfer(device_handle[(int)args->InterfaceHandle], args->PipeID, args->Buffer, args->BufferLength, args->LengthTransferred, 10000); + SetEvent(args->Overlapped->hEvent);//signal the event to release the waiting object. + free(args);//Free the malloced args. +} + + +//WinUsb_ReadPipe/winUsb_WritePipe LibUsb implementation. +BOOL __stdcall WinUsb_Transfer(HANDLE InterfaceHandle, UCHAR PipeID, PUCHAR Buffer, ULONG BufferLength, PULONG LengthTransferred, LPOVERLAPPED Overlapped) +{ + if (InterfaceHandle == INVALID_HANDLE_VALUE) + return FALSE; + if (device_handle[(int)InterfaceHandle] == NULL) + return FALSE; + int ret; + if(Overlapped != NULL)//If an asynchronous transfer is needed then pack all the arguments to an Arg structure and pass them to a new thread and return immediately. + { + ResetEvent(Overlapped->hEvent); + Args *args = malloc(sizeof(*args)); + args->InterfaceHandle = InterfaceHandle; + args->PipeID = PipeID; + args->Buffer = Buffer; + args->BufferLength = BufferLength; + args->LengthTransferred = LengthTransferred; + args->Overlapped = Overlapped; + CreateThread(NULL, 0, (void*)async_transfer, args, 0, NULL); + return TRUE; + } + else//Just an synchronous transfer is needed; just call the libusb_bulk_transfer. + { + ret = libusb_bulk_transfer(device_handle[(int)InterfaceHandle], PipeID, Buffer, BufferLength, LengthTransferred, 10000); + } + + return (ret == LIBUSB_SUCCESS); +} + + + + +void notifier_function() +{ + + struct udev *udev; + struct udev_monitor *mon; + struct udev_device *dev; + + const GUID guid = {0xE7E8BA13,0x2A81,0x446E,{0xA1,0x1E,0x72,0x39,0x8F,0xBD,0xA8,0x2F}}; + + DEV_BROADCAST_DEVICEINTERFACE_W DevBi; + DevBi.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE_W); + DevBi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + DevBi.dbcc_classguid = guid; + + udev = udev_new(); + if (!udev) { + printf("Can't create udev\n"); + return; + } + + + mon = udev_monitor_new_from_netlink(udev, "udev"); + if (!mon) + { + printf("NetLink not available!\n"); + return; + } + int count = get_device_count(); + if (count == -1) + { + printf("udev error.\n"); + return; + } + + udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", NULL); + udev_monitor_enable_receiving(mon); + int fd = udev_monitor_get_fd(mon); + + cancel = FALSE; + while (!cancel) { + fd_set fds; + struct timeval tv; + int ret; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = 0; + tv.tv_usec = 0; + + ret = select(fd + 1, &fds, NULL, NULL, &tv); + if (ret > 0 && FD_ISSET(fd, &fds)) { + + dev = udev_monitor_receive_device(mon); + if (dev && !strcasecmp(udev_device_get_devtype(dev), "usb_device")) { + int count_new; + if (!strcasecmp(udev_device_get_action(dev), "add")) + { + count_new = get_device_count(); + if (count != count_new) + { + count = count_new; + //printf("device added.\n"); + close_devices(); + usleep(100000); + SendMessageA(hWnd, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)&DevBi); + usleep(100000); + RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE); + } + + } + else if (!strcasecmp(udev_device_get_action(dev), "remove")) + { + count_new = get_device_count(); + if (count != count_new) + { + count = count_new; + //printf("device removed.\n"); + close_devices(); + usleep(100000); + SendMessageA(hWnd, WM_DEVICECHANGE, DBT_DEVICEREMOVECOMPLETE, (LPARAM)&DevBi); + usleep(100000); + RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE); + } + } + udev_device_unref(dev); + } + } + usleep(10000); + } + udev_monitor_unref(mon); +} + + +int get_device_count() +{ + struct udev *udev = udev_new(); + if (!udev) + { + return -1; + } + + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + + enumerate = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(enumerate, "usb"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + int count = 0; + udev_list_entry_foreach(dev_list_entry, devices) + { + dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(dev_list_entry)); + if (!dev) + return -1; + + const char * vid = udev_device_get_sysattr_value(dev, "idVendor"); + const char * pid = udev_device_get_sysattr_value(dev, "idProduct");; + if (vid && pid && strtoul(vid, NULL, 16) == TL866_VID && strtoul(pid, NULL, 16) == TL866_PID) + count++; + udev_device_unref(dev); + } + udev_enumerate_unref(enumerate); + udev_unref(udev); + return count; +} + + +/*/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + + switch (fdwReason) + { + case DLL_WINE_PREATTACH: + return TRUE; + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + printf("Dll Loaded.\n"); + if (!patch_minipro()) + { + printf("Dll Unloaded.\n"); + return FALSE; + } + break; + case DLL_PROCESS_DETACH: + cancel = TRUE; + WaitForSingleObject(h_thread, 5000); + printf("Dll Unloaded.\n"); + break; + } + + return TRUE; +} + + +