1
0
Fork 0
mirror of https://github.com/rfc2822/GfxTablet synced 2025-10-03 09:39:16 +02:00

win32 driver 1.4 for GfxTablet with protocol v2 support

This commit is contained in:
christoph 2018-11-22 08:47:02 +01:00
parent 128060d724
commit ca6c6be57b
12 changed files with 552 additions and 0 deletions

11
driver-win32/.gitignore vendored Normal file
View file

@ -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

View file

@ -0,0 +1,334 @@
#include "stdafx.h"
#include "driver-win32.h"
#include <WinSock2.h>
#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;
}

View file

@ -0,0 +1,3 @@
#pragma once
#include "resource.h"

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

View file

@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F1323D24-2E93-466B-83D9-01042B36DE6A}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>driverwin32</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>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)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="driver-win32.ico" />
<None Include="small.ico" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="driver-win32.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="driver-win32.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="driver-win32.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="small.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="driver-win32.ico">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="driver-win32.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="driver-win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="driver-win32.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

BIN
driver-win32/resource.h Normal file

Binary file not shown.

BIN
driver-win32/small.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

8
driver-win32/stdafx.cpp Normal file
View file

@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// driver-win32.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

35
driver-win32/stdafx.h Normal file
View file

@ -0,0 +1,35 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
#include <shellapi.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#include <wininet.h>
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
typedef char int8_t;
#include "../driver-uinput/protocol.h"

8
driver-win32/targetver.h Normal file
View file

@ -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 <SDKDDKVer.h>