From ca6c6be57b99dd473509db0eeb4df82ba4851b6b Mon Sep 17 00:00:00 2001 From: christoph Date: Thu, 22 Nov 2018 08:47:02 +0100 Subject: [PATCH] win32 driver 1.4 for GfxTablet with protocol v2 support --- driver-win32/.gitignore | 11 + driver-win32/driver-win32.cpp | 334 ++++++++++++++++++++++ driver-win32/driver-win32.h | 3 + driver-win32/driver-win32.ico | Bin 0 -> 8478 bytes driver-win32/driver-win32.rc | Bin 0 -> 5104 bytes driver-win32/driver-win32.vcxproj | 101 +++++++ driver-win32/driver-win32.vcxproj.filters | 52 ++++ driver-win32/resource.h | Bin 0 -> 1802 bytes driver-win32/small.ico | Bin 0 -> 23558 bytes driver-win32/stdafx.cpp | 8 + driver-win32/stdafx.h | 35 +++ driver-win32/targetver.h | 8 + 12 files changed, 552 insertions(+) create mode 100644 driver-win32/.gitignore create mode 100644 driver-win32/driver-win32.cpp create mode 100644 driver-win32/driver-win32.h create mode 100644 driver-win32/driver-win32.ico create mode 100644 driver-win32/driver-win32.rc create mode 100644 driver-win32/driver-win32.vcxproj create mode 100644 driver-win32/driver-win32.vcxproj.filters create mode 100644 driver-win32/resource.h create mode 100644 driver-win32/small.ico create mode 100644 driver-win32/stdafx.cpp create mode 100644 driver-win32/stdafx.h create mode 100644 driver-win32/targetver.h diff --git a/driver-win32/.gitignore b/driver-win32/.gitignore new file mode 100644 index 0000000..3562c17 --- /dev/null +++ b/driver-win32/.gitignore @@ -0,0 +1,11 @@ +/Debug/ +/Release/ +/ipch/ +/driver-win32.aps +/driver-win32.sdf +/driver-win32.suo +/*.vcxproj.user +/driver-win32.sln +Browse.VC.* +*.ipch +*.suo diff --git a/driver-win32/driver-win32.cpp b/driver-win32/driver-win32.cpp new file mode 100644 index 0000000..8ec10d2 --- /dev/null +++ b/driver-win32/driver-win32.cpp @@ -0,0 +1,334 @@ +#include "stdafx.h" +#include "driver-win32.h" +#include + +#pragma comment(lib, "Ws2_32.lib") + +#define MAX_LOADSTRING 100 +//#define SIMULATE_HOVER_TROUGH_LIGHT_TOUCH 1 + +// Global Variables: +HINSTANCE hInst; // current instance +TCHAR szTitle[MAX_LOADSTRING]; // The title bar text +TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name + +// Forward declarations of functions included in this code module: +ATOM MyRegisterClass(HINSTANCE hInstance); +BOOL InitInstance(HINSTANCE, int); +LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); + +int RunDriver(); + +int APIENTRY _tWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPTSTR lpCmdLine, + int nCmdShow) +{ + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + // TODO: Place code here. + MSG msg; + HACCEL hAccelTable; + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_DRIVERWIN32, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DRIVERWIN32)); + + // + PostMessage(NULL, WM_USER+1,0,0); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return (int) msg.wParam; +} + +ATOM MyRegisterClass(HINSTANCE hInstance) +{ + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = WndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = hInstance; + wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DRIVERWIN32)); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DRIVERWIN32); + wcex.lpszClassName = szWindowClass; + wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); + + return RegisterClassEx(&wcex); +} + +#define WM_USER_SHELLICON (WM_USER+1) + +NOTIFYICONDATA nidApp; + +void CreateTrayIcon(HWND hWnd) +{ + nidApp.cbSize = sizeof(NOTIFYICONDATA); + nidApp.hWnd = (HWND) hWnd; + nidApp.uID = IDI_DRIVERWIN32; + nidApp.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; + nidApp.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_DRIVERWIN32) ); + nidApp.uCallbackMessage = WM_USER_SHELLICON; + _tcscpy( nidApp.szTip, _T("GfxTablet windows driver") ); + + Shell_NotifyIcon(NIM_ADD, &nidApp); +} + +void RemoveTrayIcon(HWND hWnd) +{ + Shell_NotifyIcon(NIM_DELETE, &nidApp); +} + +DWORD dwDriverThreadId = 0; +DWORD WINAPI DriverThreadStart(LPVOID lpThreadParameter) +{ + return RunDriver(); +} + +HWND hWnd = NULL; + +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + hInst = hInstance; // Store instance handle in our global variable + + hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + + if (!hWnd) + { + return FALSE; + } + + CreateTrayIcon(hWnd); + + CreateThread(NULL, 500000, DriverThreadStart, NULL, 0, &dwDriverThreadId); + + return TRUE; +} + +void ShowTrayIconContextMenu(HWND hWnd) +{ + POINT lpClickPoint; + UINT uFlag = MF_BYPOSITION|MF_STRING; + GetCursorPos(&lpClickPoint); + HMENU hPopMenu = CreatePopupMenu(); + InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,IDM_EXIT,_T("Exit")); + TrackPopupMenu(hPopMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_BOTTOMALIGN, + lpClickPoint.x, lpClickPoint.y,0,hWnd,NULL); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + PAINTSTRUCT ps; + HDC hdc; + + switch (message) + { + case WM_USER_SHELLICON: + switch(LOWORD(lParam)) + { + case WM_RBUTTONDOWN: + ShowTrayIconContextMenu(hWnd); + } + break; + + case WM_COMMAND: + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + // Parse the menu selections: + switch (wmId) + { + case IDM_EXIT: + DestroyWindow(hWnd); + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + break; + case WM_DESTROY: + RemoveTrayIcon(hWnd); + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +int udp_socket; + +void die(TCHAR* fmt, ...) +{ + va_list args; + va_start(args,fmt); + TCHAR msgbuf[4096]; + _vsntprintf_s(msgbuf, _countof(msgbuf), fmt, args); + MessageBox(NULL, msgbuf, _T("GfxTablet Win32 driver error"), MB_ICONERROR|MB_OK); + + RemoveTrayIcon(hWnd); + ExitProcess(EXIT_FAILURE); +} + +int prepare_socket() +{ + int s; + struct sockaddr_in addr; + + WSADATA wsadata; + WSAStartup(WINSOCK_VERSION, &wsadata); + + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + die(_T("error: prepare_socket()")); + + ZeroMemory(&addr, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = htons(GFXTABLET_PORT); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) + { + DWORD dwErr = WSAGetLastError(); + if (dwErr == WSAEADDRINUSE) + die(_T("error: prepare_socket(). Port already in use") ); + else + die(_T("error: prepare_socket(). Error = 0x%08x"), dwErr ); + } + + return s; +} + +void quit(int signal) +{ + closesocket(udp_socket); +} + +int RunDriver(void) +{ + int device; + struct event_packet ev_pkt; + + udp_socket = prepare_socket(); + + printf("GfxTablet driver (protocol version %u) is ready and listening on 0.0.0.0:%u (UDP)\n" + "Hint: Make sure that this port is not blocked by your firewall.\n", PROTOCOL_VERSION, GFXTABLET_PORT); + + signal(SIGINT, quit); + signal(SIGTERM, quit); + + BOOL isDown = false; + + while (recv(udp_socket, (char*)&ev_pkt, sizeof(ev_pkt), 0) >= 9) { // every packet has at least 9 bytes + printf("."); fflush(0); + + if (memcmp(ev_pkt.signature, "GfxTablet", 9) != 0) { + fprintf(stderr, "\nGot unknown packet on port %i, ignoring\n", GFXTABLET_PORT); + continue; + } + ev_pkt.version = ntohs(ev_pkt.version); + if (ev_pkt.version != PROTOCOL_VERSION) { + fprintf(stderr, "\nGfxTablet app speaks protocol version %i but driver speaks version %i, please update\n", + ev_pkt.version, PROTOCOL_VERSION); + break; + } + + ev_pkt.x = ntohs(ev_pkt.x); + ev_pkt.y = ntohs(ev_pkt.y); + ev_pkt.pressure = ntohs(ev_pkt.pressure); + printf("x: %hi, y: %hi, pressure: %hi\n", ev_pkt.x, ev_pkt.y, ev_pkt.pressure); + + //windows uses 0-65535, while GfxTablet uses 0-32767 + int absoluteX = ((int)ev_pkt.x)*2; + int absoluteY = ((int)ev_pkt.y)*2; + + INPUT inputs[1]; + ZeroMemory(&inputs[0],sizeof(inputs)); + inputs[0].type = INPUT_MOUSE; + inputs[0].mi.dx = absoluteX; + inputs[0].mi.dy = absoluteY; + inputs[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE; + + //no support for pressure on windows :-(( + //This is only possible with an HID miniport driver. + //GIMP uses DirectInput - probably the HID miniport driver would be visible trough HID + //If not a DirectInput driver would be necessary too + //send_event(device, EV_ABS, ABS_PRESSURE, ev_pkt.pressure); + +#if SIMULATE_HOVER_TROUGH_LIGHT_TOUCH + //hack: ignores EVENT_TYPE_BUTTON (android touch events), but generates them + //when pressure is over a specific limit, so it is possible to move the finger + //around the tablet without drawing + if(ev_pkt.type==EVENT_TYPE_BUTTON && ev_pkt.down) + { + ev_pkt.type=EVENT_TYPE_MOTION; + } + else if(ev_pkt.type==EVENT_TYPE_MOTION && ev_pkt.pressure>18000) + { + if (!isDown) + ev_pkt.type=EVENT_TYPE_BUTTON; + } +#endif + + switch (ev_pkt.type) { + case EVENT_TYPE_MOTION: + inputs[0].mi.dwFlags |= MOUSEEVENTF_MOVE; + SendInput(1, &inputs[0], sizeof(inputs[0])); + break; + case EVENT_TYPE_BUTTON: + if (ev_pkt.button == 0) + { + inputs[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE; + SendInput(1, &inputs[0], sizeof(inputs[0])); + } + + if (ev_pkt.down) + { + inputs[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN; + isDown = true; + } + else + { + inputs[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP; + isDown = false; + } + SendInput(1, &inputs[0], sizeof(inputs[0])); + break; + + } + } + closesocket(udp_socket); + + + printf("GfxTablet driver shut down gracefully\n"); + return 0; +} diff --git a/driver-win32/driver-win32.h b/driver-win32/driver-win32.h new file mode 100644 index 0000000..d00d47e --- /dev/null +++ b/driver-win32/driver-win32.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/driver-win32/driver-win32.ico b/driver-win32/driver-win32.ico new file mode 100644 index 0000000000000000000000000000000000000000..4262841bd018f8cb3dde4a94f2c327e02a9efcf6 GIT binary patch literal 8478 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 OywA})@q1)f*82;z*I4)f literal 0 HcmV?d00001 diff --git a/driver-win32/driver-win32.vcxproj b/driver-win32/driver-win32.vcxproj new file mode 100644 index 0000000..7e081fe --- /dev/null +++ b/driver-win32/driver-win32.vcxproj @@ -0,0 +1,101 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {F1323D24-2E93-466B-83D9-01042B36DE6A} + Win32Proj + driverwin32 + 10.0.17763.0 + + + + Application + true + Unicode + v141 + + + Application + false + true + Unicode + v141 + + + + + + + + + + + + + true + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + + + + + + + + + + + + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/driver-win32/driver-win32.vcxproj.filters b/driver-win32/driver-win32.vcxproj.filters new file mode 100644 index 0000000..5b2c262 --- /dev/null +++ b/driver-win32/driver-win32.vcxproj.filters @@ -0,0 +1,52 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/driver-win32/resource.h b/driver-win32/resource.h new file mode 100644 index 0000000000000000000000000000000000000000..57895e461fe5840200024a59590550b9cc451643 GIT binary patch literal 1802 zcmbW2(Qev65Jm5Er2d1YJXR@%v`YKv+N44S7hyx2C)5CrsG>wNA!$|h*VCTa4N?ee zmsBfjXNUFK>)Dy%&wWcR{bFSLtf^9UHRQ>hl_^n=Rj%KR7dl{XOOXazYNkrpTJe;+ z!8gIT(puki$tuxHMx+ZZbj4HQzhR!^TjH6qYt3rGy2Nvd_3F_HV_1Ioxqh-|4q>TV ze3g!L=NQN8@JVFM8=*f%%@oaN*a=^m;oX0996dx$UA#t6C&Xx^FIbsO zmBq2ASba|W7(A=3*X*m)n?s1XhaqzTsesfCa(2JN$j7zhfg^uF*BI*V+f5!LziA|Q z_0_3uqJ(}k^4nT+&&4wo=MZb#XXKMca!zL0P4)jH8t-b!mT@ULv6~y)`a&zy{Jxev zf^3Q{*G@ShX0?BAbkwXlCo5u?bIG&faiq3Wys5+pbqoD)ox!TSr2f}bxpj(L*CW<= zSFB1pNX2Z`ddGaNbA892v3KQ|zUTN_S+d{rB6JSvOa+;2)n?txVlu({L`2eu2-+K0 z4eyND8?)Q`LZ2Qng?UCytw#FTp&IqoX;tdG=75`cPP}}qp7xZ-RI8){zNyPmGR8`< zr+lAf>lpiK?zHJB;k*fvtrHGhCRwj<;zq8golr;n>-K%NK($4&nQr-R<6n{9#Khl^ Y-EcG4;?rhq$o5Y(=YOGmIB9$R7bXGS761SM literal 0 HcmV?d00001 diff --git a/driver-win32/small.ico b/driver-win32/small.ico new file mode 100644 index 0000000000000000000000000000000000000000..d551aa3aaf80adf9b7760e2eb8de95a5c3e53df6 GIT binary patch literal 23558 zcmeI430zgx+QuJHKtxbe5gbu*030B5$VyGcDGSFOalkY&2LuvC5pp(7&2XNl96=@z zNXGH2`|DO#nx)3nwUq43A>_N=+wHsYe$U#6ePmShD&p^B>2uySylbs@uYIPy&-w#c zpc-6UYC)x+ErDgUwQ8BlZ7hIURRB*7exZ#T}AXG2* z=^weGTI5~Inq#r?3QZRh5>Vvy7AqDy*^i;1p6BY7;LQSXZ{;g>M z?fm5AM!1uJ~14CP5-;mbWJGeF0 z_iurN!(6GBI54yo4h(CB{j~e(6Em$hj*V=Fqpvo{5$e#07L+U2`wvFkn8s8S#Efo= z^|!}o{tozLT1|Z7UlaSMxZ(5FgK^Rilm(Khv|vko7i5X}36?lI))Ggklas69 zVxSe$=33+10BfA^v%)uXY;b;dHGCaV4e6oPadwt1PEE7L#SjO4G`kKy33kG#^P1yK zcx(J^Ra<Ti+?95-JJvGIWK0JnTs;vs^DcXy)=jK$w z=lme~e0CM~SM61i7E+Zy6!Vv8(?YCpX|5H%3$bS21{dbq;8I96Tne>C8jm-9o*mM| z?2r~#1K&~U^BwT@ygK+I#1UDG8sIO%&iE*}A+E1$jbGNa!S(fRas9ovxba>)TBY{5 zxxo`Rq9|oIDtY0?rjE#1t!!u9+}s5>w|2#i&D55z%y+}h?JrQ>af9~O4zA^n9=Nr$ z7jEt9gPXg&@$23JxV49(y|Q~4emOiI-)H_6dH=qKoBYhlq5e+&PW_AegZf|U-_)N} z9@RJC3MS7vp?yXL1qC4>AOQaU{+Kjr5++WZhzS!Wz}MFoW5Wxo&I+1!G$zZHn#$;`!98-<yjHIyy#~ zd!^|5sm6LSF)_!K%8;V#rWzZU(N_%@(#Q5Ewg{KRHI95 zY?=LIo2D9@#Ky*zb^O>SmHu~IE44l?Dgh-;K81z)WLJ`;4wqn z_ZrZ%LmzL?wy3kD_lL%jZ@l`n*YIJJ=8o?=KVm^dc=tK8XTNSrUK1xwofb5!|4WPJ z4;&O=5uecStt8`&$o&U)@7lX>*XEsj-g|fBj_upFZrx%^n^vq{{r0M5OP8-%`Odni z4ek1_pUw~WS3(xf3w~KkBmDdVRSL~dfr0)bOf7sI@n%@?lm1=c0pd4Z&T02Hm@RH2 z)we;5{I7(S*0d0%twR;wLsA|##n-X4buN70s`TsBg@MbpxknH6!QPjfV-K~P+VA6v z_lLE?{$Xwi?eB?&gE}IlpC>|?5A<%2&;edpIl33d4IhkA?7Qcs#@NdnYWsbf({dao zjuAS*69M!eGt37G)4CyX#*2ub-V>ij1>vuo!mzs+z)KgL@b7{zHqOE48v-$!zJ3#Y zv6uJbc6$T6dQ*KU=65px!K_Y5n$a2Cr*_9zn`Ys&O+gqt+y{pT0q+l>1_JwOKM87w zj|1D|zXCjwI@=4Ewok|DRTFSw+Z#B)bq3CDnTav%mol33yacQq;D9qB?)YqOTV(8< zhO{02IO`82u>Hs|UYpK$#ksIn_%f8&v3sW=YtK}ip9y^Z1~r3H`B~I#;2iDQ=@jeE zsP;Kl_%^%|E=9QF`(^IPTIr6TH*`S`ui5^ww+}9?dJfr}dg8{OA;>xEhiiu?LYUzwb+T)8Ci=PAZtkjWKvm68X{|HBivlm3|Y&X;^sP6+GhB5eJk92w>5I2 z+$j(Ix}hC1827D>9dK(?2jp()h@8zG@!QT$$l2N%x3+e|?QJ|JOre?J8PhnJ%Ni~CLrzWB&44|iS%zyB8@if zn`DaR3m@|O^QyPhwX#dzrgIKY+OQIBHLeiIw|EP z&VT0+jvL~&)rdRJe}-vnAIJ6*Q-ZDH1N-*w-gRv2&ZLw99b3D3xO=#{xw*T!wQ+Oz@bGBcd0?|n&$#sN_2S8-lrFX#RqEa{~iIg60Iwp0)kazxeJo zgX#N&>G3k(9Zpk`k46?8yGp_NR9<~gx%0b2>EBc6h6N*s;*a0{2Wy6O#7ZA8q(u55 zXmAg#9`ZC+QBk9x#nSQpa4CKpR!sCp#>stnXRBl-)qQFW^fsryy=(Z?FI2AS<5;lV$HB*W zpm$$$hhFu3THa~z+qYL;AE$u>2QZl)2G;Ru)3f^vUAny3rOUHDp6~jct50i}CXE|6 zZPK7&qvp+?vT*b1+^M5y`wmZgdAPT0`%H^xiXL6DvWOu*60xx;u6V#Q2{0r8adCy( zEn;IuV&g28p4jI>W#CW53OF&!CsAr~RottogHM>&s@S>DKq|7h|3SD9 zqF9XiYwfgmNUJRFhY%(1o6xLY)@?;QKJMM%9Zv1};>0~2!r#}0zp0zW`xNH9UeDj( zg}=XRQtjm}{_d~Eq+;bB6m$ICmr^L!lH$^jp`^CQQOEr>=J>f^rrg)^KRssd^D)QI zeLuo|80KTp^Sb>{=X%)v)pLRSmCW&T|B@EJinpT1Tyzb%m&zPJ_g4w`z?hFg`Rd1_ z>Wj7&9jm;{DmLy1Gsn+8Vp@!PtSTNouWWh8cdz+W{M_4Sj-PwjDs;R>k4LR3_uiS~ z=YBll{weJklr8FC(aI`*?jJPA&pn00ytW2@1pNNmFr)z)}MRaMZIsT^P*Jr zd{v~ficiI=V%Fb3xlf-prc}}2|5bcSDrP-?@&@_Qn~c8Rs-)*Df-M*%`H0H+%lZ72 zvi{EGQOr#h;dxS84CWx2AwMJBn{b$~fyU%&3N}@!=X}9qDHtRuG5tUm68j-~fkG1sqOUyGmYlwPgb z2OYaS`ssnHnDzL{f$7y1HvU2ZvOsRl96y=1qRkb)O#V)fzZuy)A>;K#iJYK%{YIx)`7mahDM1B1t%cm9kaZNYkD4X_DC9qd+$8->B5TQhB} zPLpFP(T5^y$$V8IA1dTRh5V#84>?gGBg(O=3b|S#mnh^Cg)FI%vsB;THmdl^aSGW> zA@3;U9fcgEkcSj)tKX)y|CMyJ9 zWMGAisgNZVGNwZIRLI7bES?uKuA0cIN->306SAtME58p}SdPK5N}H!(y?QQ$SPR)# zEw=cH;9p8myVEOE~ZJrY}3iIg?0rP&%LTBp=}8h@I%TXv<9-xUO`%}-uWt5a*E=2Z6^)Nip$4?6}mrb=W3r9pMm{N(?%I<=0f{ZX!iK0oKQ1d^EdG#^%`N>O4Lp#&)lc_BC`N?cbBh&ou z$Ha>#mE4>Z3XbJ2L!+Nt++W%XmzCnEDKwe#1XEVN#&9kX7z*Ba>aDt~p(O7d58 ztNMbLMIj4qo}V1Gs?t)?V|bWl{j*<9L>}8bKN)V*HyMT)&Xn7jpKpqbGz6zmVk@{(S%;moMb= zg`B=PIy$QPUCF}>xq2agFXZoq+`W*w*DN`FAuBIr%G&-D!IW`F9}` zFJ#_@jJ%MQmz-@~sV+i3UdYL7B1xFE+kg*rC_sn}}eaYVo*?J*YFZ>$;!oOJ{ z{QCgB-)1FF4i?imzkPZz{4Rvr{h7I>sgUu{%LsSK%b0JUml0-1RnN;GSP!(-+jpO%JopO`B((dnpK-(&yRaUJ6F; zchnE_k$Wv1f4{oG;*T$8Vx5|ss!Wf01@yO_$nuNBLZ4Gvb)Vu6x9f7RD3t3{RPFna z@~=**zWfUs8kYPPZCSL4e)B1xT|TXnSM+U>y|{O?8%m4vtzIr_BVKg5vCP}`*3dR} z&a!{N#n>%>kU18z!$Q_q$meQ#RW3=oZ=knFmg=8&V&`qOUg~p1N&lWwnpHmPb9YW3 zw+z)kIP(xwOMAJX5{|A*v__uZdtvV;w2rOkgeCCc1i z#a5Q%Amc3IgIa3+fBIm(x&OWTs_~Un|HxNN{coH$#m{POUDev^Dy>e{FMhe1Y5iiu zZ +#include + +// C RunTime Header Files +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef unsigned short uint16_t; +typedef unsigned char uint8_t; +typedef char int8_t; + +#include "../driver-uinput/protocol.h" diff --git a/driver-win32/targetver.h b/driver-win32/targetver.h new file mode 100644 index 0000000..87c0086 --- /dev/null +++ b/driver-win32/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include