mcp-remotetouch 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -72
- package/build/index.js +55 -6
- package/build/index.js.map +1 -1
- package/build/python-daemon.d.ts +1 -1
- package/build/python-daemon.js +349 -83
- package/build/python-daemon.js.map +1 -1
- package/build/ssh-touch-session.js +11 -2
- package/build/ssh-touch-session.js.map +1 -1
- package/build/types.d.ts +8 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
An MCP server for remotely controlling a touchscreen on any Linux device over SSH.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Injects tap, swipe, long press, double tap, and keyboard events directly into the device. The daemon auto-detects the touchscreen and screen resolution. Keyboard input is injected via a virtual keyboard device created through `/dev/uinput`. **No installation required on the remote device** — the Python daemon is sent via stdin over SSH, using only Python's standard library.
|
|
6
6
|
|
|
7
7
|
## Architecture
|
|
8
8
|
|
|
@@ -14,14 +14,19 @@ Dev Machine Remote Linux Device
|
|
|
14
14
|
│ MCP Server (TS) │ ──────────────────> │ Python daemon │
|
|
15
15
|
│ stdio transport │ JSON-line proto │ (stdlib only) │
|
|
16
16
|
│ │ <────────────────── │ │
|
|
17
|
-
│ touch_tap │ │
|
|
18
|
-
│ touch_swipe │ │
|
|
19
|
-
│ touch_long_press │ │
|
|
20
|
-
│ touch_double_tap │ │
|
|
21
|
-
│
|
|
17
|
+
│ touch_tap │ │ Auto-detect │
|
|
18
|
+
│ touch_swipe │ │ touchscreen │
|
|
19
|
+
│ touch_long_press │ │ ↓ │
|
|
20
|
+
│ touch_double_tap │ │ /dev/input/eventN│
|
|
21
|
+
│ key_press │ │ ↓ │
|
|
22
|
+
│ key_type │ │ /dev/uinput (kbd)│
|
|
23
|
+
│ touch_disconnect │ │ ↓ │
|
|
24
|
+
│ │ │ Linux Input │
|
|
22
25
|
└──────────────────┘ └──────────────────┘
|
|
23
26
|
```
|
|
24
27
|
|
|
28
|
+
The daemon scans `/proc/bus/input/devices` to find the physical touchscreen (by checking `INPUT_PROP_DIRECT` and `ABS_MT_POSITION_X`), then injects events directly into it. This works reliably with containerized compositors (e.g., Torizon with Qt EGLFS) where virtual uinput devices may not be detected.
|
|
29
|
+
|
|
25
30
|
### HTTP server mode (`--server`)
|
|
26
31
|
|
|
27
32
|
```
|
|
@@ -45,7 +50,8 @@ AI Agent (remote) ──HTTP/SSE──> Express + StreamableHTTPServerTransport
|
|
|
45
50
|
|
|
46
51
|
- Any Linux device with a touchscreen (Raspberry Pi, SBC, embedded system, etc.)
|
|
47
52
|
- Python 3
|
|
48
|
-
-
|
|
53
|
+
- Read/write access to `/dev/input/eventN` (the touchscreen device)
|
|
54
|
+
- Write access to `/dev/uinput` (for keyboard input — optional, touch works without it)
|
|
49
55
|
|
|
50
56
|
Add the user to the `input` group on the remote device:
|
|
51
57
|
|
|
@@ -53,48 +59,48 @@ Add the user to the `input` group on the remote device:
|
|
|
53
59
|
sudo usermod -aG input $USER
|
|
54
60
|
```
|
|
55
61
|
|
|
56
|
-
Re-login for the change to take effect.
|
|
62
|
+
Re-login for the change to take effect. Alternatively, use the `useSudo` option.
|
|
57
63
|
|
|
58
64
|
## Installation
|
|
59
65
|
|
|
60
66
|
```bash
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
npm install -g mcp-remotetouch
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Or run directly with `npx`:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx mcp-remotetouch
|
|
65
74
|
```
|
|
66
75
|
|
|
67
|
-
##
|
|
76
|
+
## Usage
|
|
68
77
|
|
|
69
|
-
Add to Claude Desktop's `claude_desktop_config.json
|
|
78
|
+
Add to your MCP client configuration (e.g. Claude Desktop's `claude_desktop_config.json`):
|
|
70
79
|
|
|
71
80
|
```json
|
|
72
81
|
{
|
|
73
82
|
"mcpServers": {
|
|
74
83
|
"remotetouch": {
|
|
75
|
-
"command": "
|
|
76
|
-
"args": ["
|
|
77
|
-
"env": {
|
|
78
|
-
"REMOTETOUCH_SSH_HOST": "192.168.1.100",
|
|
79
|
-
"REMOTETOUCH_SSH_USER": "pi",
|
|
80
|
-
"REMOTETOUCH_SCREEN_WIDTH": "800",
|
|
81
|
-
"REMOTETOUCH_SCREEN_HEIGHT": "480"
|
|
82
|
-
}
|
|
84
|
+
"command": "npx",
|
|
85
|
+
"args": ["mcp-remotetouch"],
|
|
86
|
+
"env": {}
|
|
83
87
|
}
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
```
|
|
87
91
|
|
|
92
|
+
Screen resolution is auto-detected from the device. You can override it with `REMOTETOUCH_SCREEN_WIDTH` and `REMOTETOUCH_SCREEN_HEIGHT` if needed.
|
|
93
|
+
|
|
88
94
|
## Environment Variables
|
|
89
95
|
|
|
90
96
|
| Variable | Default | Description |
|
|
91
97
|
|---|---|---|
|
|
92
|
-
| `REMOTETOUCH_SSH_HOST` | (
|
|
98
|
+
| `REMOTETOUCH_SSH_HOST` | (none) | SSH host of the remote device |
|
|
93
99
|
| `REMOTETOUCH_SSH_USER` | `pi` | SSH username |
|
|
94
100
|
| `REMOTETOUCH_SSH_PORT` | `22` | SSH port |
|
|
95
101
|
| `REMOTETOUCH_SSH_KEY` | (none) | Path to SSH private key |
|
|
96
|
-
| `REMOTETOUCH_SCREEN_WIDTH` |
|
|
97
|
-
| `REMOTETOUCH_SCREEN_HEIGHT` |
|
|
102
|
+
| `REMOTETOUCH_SCREEN_WIDTH` | auto-detected | Screen width in pixels |
|
|
103
|
+
| `REMOTETOUCH_SCREEN_HEIGHT` | auto-detected | Screen height in pixels |
|
|
98
104
|
| `REMOTETOUCH_USE_SUDO` | `false` | Run daemon with sudo |
|
|
99
105
|
|
|
100
106
|
## Tools
|
|
@@ -109,8 +115,8 @@ Connect to a remote Linux device via SSH and start the touch daemon. Returns a s
|
|
|
109
115
|
| `user` | string? | SSH username |
|
|
110
116
|
| `port` | number? | SSH port |
|
|
111
117
|
| `sshKey` | string? | Path to SSH private key |
|
|
112
|
-
| `screenWidth` | number? | Screen width
|
|
113
|
-
| `screenHeight` | number? | Screen height
|
|
118
|
+
| `screenWidth` | number? | Screen width (auto-detected if omitted) |
|
|
119
|
+
| `screenHeight` | number? | Screen height (auto-detected if omitted) |
|
|
114
120
|
| `useSudo` | boolean? | Run with sudo |
|
|
115
121
|
|
|
116
122
|
### `touch_tap`
|
|
@@ -159,6 +165,25 @@ Double tap at the given coordinates.
|
|
|
159
165
|
| `x` | number | X coordinate |
|
|
160
166
|
| `y` | number | Y coordinate |
|
|
161
167
|
|
|
168
|
+
### `key_press`
|
|
169
|
+
|
|
170
|
+
Press a key with optional modifier keys. Requires `/dev/uinput` access on the remote device.
|
|
171
|
+
|
|
172
|
+
| Parameter | Type | Description |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `sessionId` | string | Session ID |
|
|
175
|
+
| `key` | string | Key name (e.g. `enter`, `a`, `tab`, `f1`, `up`, `space`) |
|
|
176
|
+
| `modifiers` | string[]? | Modifier keys to hold (e.g. `["ctrl"]`, `["ctrl", "shift"]`) |
|
|
177
|
+
|
|
178
|
+
### `key_type`
|
|
179
|
+
|
|
180
|
+
Type a string of text by simulating individual key presses. Requires `/dev/uinput` access on the remote device.
|
|
181
|
+
|
|
182
|
+
| Parameter | Type | Description |
|
|
183
|
+
|---|---|---|
|
|
184
|
+
| `sessionId` | string | Session ID |
|
|
185
|
+
| `text` | string | Text to type (e.g. `Hello, World!`) |
|
|
186
|
+
|
|
162
187
|
### `touch_disconnect`
|
|
163
188
|
|
|
164
189
|
Disconnect a session and clean up the remote daemon.
|
|
@@ -179,13 +204,10 @@ Instead of running as a stdio MCP server, you can run `mcp-remotetouch` as an HT
|
|
|
179
204
|
|
|
180
205
|
```bash
|
|
181
206
|
# Default: listen on 0.0.0.0:3000
|
|
182
|
-
|
|
207
|
+
npx mcp-remotetouch --server
|
|
183
208
|
|
|
184
209
|
# Custom port and host
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
# Or use the convenience script
|
|
188
|
-
npm run start:server
|
|
210
|
+
npx mcp-remotetouch --server --port 8080 --host 127.0.0.1
|
|
189
211
|
```
|
|
190
212
|
|
|
191
213
|
### CLI arguments
|
|
@@ -198,58 +220,45 @@ npm run start:server
|
|
|
198
220
|
|
|
199
221
|
Without `--server`, the process runs in stdio mode (the default, backward-compatible behavior).
|
|
200
222
|
|
|
201
|
-
|
|
223
|
+
## Workflow
|
|
202
224
|
|
|
203
|
-
|
|
225
|
+
A typical session from Claude Desktop:
|
|
204
226
|
|
|
205
|
-
```bash
|
|
206
|
-
# Initialize a session
|
|
207
|
-
curl -X POST http://localhost:3000/mcp \
|
|
208
|
-
-H "Content-Type: application/json" \
|
|
209
|
-
-H "Accept: application/json, text/event-stream" \
|
|
210
|
-
-d '{
|
|
211
|
-
"jsonrpc": "2.0",
|
|
212
|
-
"method": "initialize",
|
|
213
|
-
"params": {
|
|
214
|
-
"protocolVersion": "2025-03-26",
|
|
215
|
-
"capabilities": {},
|
|
216
|
-
"clientInfo": { "name": "test", "version": "1.0" }
|
|
217
|
-
},
|
|
218
|
-
"id": 1
|
|
219
|
-
}'
|
|
220
|
-
```
|
|
221
227
|
|
|
222
|
-
|
|
228
|
+
1. `touch_connect` — connect to the remote device
|
|
229
|
+
2. `touch_tap` / `touch_swipe` / `touch_long_press` / `touch_double_tap` — interact with the screen
|
|
230
|
+
3. `key_press` / `key_type` — send keyboard input
|
|
231
|
+
4. `touch_disconnect` — end the session
|
|
223
232
|
|
|
224
|
-
|
|
225
|
-
curl -X POST http://localhost:3000/mcp \
|
|
226
|
-
-H "Content-Type: application/json" \
|
|
227
|
-
-H "Accept: application/json, text/event-stream" \
|
|
228
|
-
-H "mcp-session-id: <session-id>" \
|
|
229
|
-
-d '{"jsonrpc":"2.0","method":"tools/list","id":2}'
|
|
230
|
-
```
|
|
233
|
+
## Troubleshooting
|
|
231
234
|
|
|
232
|
-
|
|
235
|
+
### Permission denied
|
|
233
236
|
|
|
234
|
-
|
|
237
|
+
The user on the remote device needs access to `/dev/input/eventN`. Either:
|
|
235
238
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
3. `touch_swipe` to scroll or swipe
|
|
239
|
-
4. `touch_disconnect` to end the session
|
|
239
|
+
- Add the user to the `input` group: `sudo usermod -aG input $USER` (re-login required)
|
|
240
|
+
- Or set `REMOTETOUCH_USE_SUDO=true`
|
|
240
241
|
|
|
241
|
-
|
|
242
|
+
### No physical touchscreen device found
|
|
242
243
|
|
|
243
|
-
|
|
244
|
+
The daemon could not find a touchscreen in `/proc/bus/input/devices`. Verify:
|
|
244
245
|
|
|
245
|
-
The
|
|
246
|
+
- The device has a touchscreen connected and its driver is loaded
|
|
247
|
+
- The device shows `INPUT_PROP_DIRECT` and has `ABS_MT_POSITION_X` capability
|
|
246
248
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
### Keyboard input not available
|
|
250
|
+
|
|
251
|
+
The `key_press` and `key_type` tools require write access to `/dev/uinput`. If keyboard is reported as unavailable:
|
|
252
|
+
|
|
253
|
+
- Add a udev rule to grant access:
|
|
254
|
+
```bash
|
|
255
|
+
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-uinput.rules
|
|
256
|
+
sudo udevadm control --reload-rules && sudo udevadm trigger
|
|
257
|
+
```
|
|
258
|
+
- Ensure the user is in the `input` group: `sudo usermod -aG input $USER` (re-login required)
|
|
259
|
+
- Or set `REMOTETOUCH_USE_SUDO=true`
|
|
251
260
|
|
|
252
|
-
|
|
261
|
+
Touch tools continue to work even if `/dev/uinput` is not accessible.
|
|
253
262
|
|
|
254
263
|
### SSH connection fails
|
|
255
264
|
|
package/build/index.js
CHANGED
|
@@ -8,13 +8,15 @@ import { SshTouchSessionManager } from "./ssh-touch-session.js";
|
|
|
8
8
|
import { randomUUID } from "node:crypto";
|
|
9
9
|
// Defaults from environment variables
|
|
10
10
|
function defaultConfig(overrides = {}) {
|
|
11
|
+
const envWidth = process.env.REMOTETOUCH_SCREEN_WIDTH;
|
|
12
|
+
const envHeight = process.env.REMOTETOUCH_SCREEN_HEIGHT;
|
|
11
13
|
return {
|
|
12
14
|
host: overrides.host ?? process.env.REMOTETOUCH_SSH_HOST ?? "",
|
|
13
15
|
user: overrides.user ?? process.env.REMOTETOUCH_SSH_USER ?? "pi",
|
|
14
16
|
port: overrides.port ?? Number(process.env.REMOTETOUCH_SSH_PORT ?? "22"),
|
|
15
17
|
sshKey: overrides.sshKey ?? process.env.REMOTETOUCH_SSH_KEY ?? undefined,
|
|
16
|
-
screenWidth: overrides.screenWidth ?? Number(
|
|
17
|
-
screenHeight: overrides.screenHeight ?? Number(
|
|
18
|
+
screenWidth: overrides.screenWidth ?? (envWidth ? Number(envWidth) : undefined),
|
|
19
|
+
screenHeight: overrides.screenHeight ?? (envHeight ? Number(envHeight) : undefined),
|
|
18
20
|
useSudo: overrides.useSudo ?? (process.env.REMOTETOUCH_USE_SUDO === "true"),
|
|
19
21
|
};
|
|
20
22
|
}
|
|
@@ -22,15 +24,15 @@ function defaultConfig(overrides = {}) {
|
|
|
22
24
|
function createServer(manager) {
|
|
23
25
|
const server = new McpServer({
|
|
24
26
|
name: "mcp-remotetouch",
|
|
25
|
-
version: "0.
|
|
27
|
+
version: "0.2.0",
|
|
26
28
|
});
|
|
27
29
|
server.tool("touch_connect", "Connect to a remote Linux device via SSH and start the touch daemon. Returns a session ID for subsequent touch commands.", {
|
|
28
30
|
host: z.string().optional().describe("SSH host (default: env REMOTETOUCH_SSH_HOST)"),
|
|
29
31
|
user: z.string().optional().describe("SSH user (default: env REMOTETOUCH_SSH_USER or 'pi')"),
|
|
30
32
|
port: z.number().optional().describe("SSH port (default: env REMOTETOUCH_SSH_PORT or 22)"),
|
|
31
33
|
sshKey: z.string().optional().describe("Path to SSH private key"),
|
|
32
|
-
screenWidth: z.number().optional().describe("Screen width in pixels (default:
|
|
33
|
-
screenHeight: z.number().optional().describe("Screen height in pixels (default:
|
|
34
|
+
screenWidth: z.number().optional().describe("Screen width in pixels (default: auto-detected from device, or env REMOTETOUCH_SCREEN_WIDTH)"),
|
|
35
|
+
screenHeight: z.number().optional().describe("Screen height in pixels (default: auto-detected from device, or env REMOTETOUCH_SCREEN_HEIGHT)"),
|
|
34
36
|
useSudo: z.boolean().optional().describe("Run daemon with sudo (default: env REMOTETOUCH_USE_SUDO or false)"),
|
|
35
37
|
}, async (params) => {
|
|
36
38
|
const config = defaultConfig({
|
|
@@ -50,8 +52,11 @@ function createServer(manager) {
|
|
|
50
52
|
}
|
|
51
53
|
try {
|
|
52
54
|
const sessionId = await manager.connect(config);
|
|
55
|
+
const session = manager.getSession(sessionId);
|
|
56
|
+
const w = session.config.screenWidth ?? "unknown";
|
|
57
|
+
const h = session.config.screenHeight ?? "unknown";
|
|
53
58
|
return {
|
|
54
|
-
content: [{ type: "text", text: `Connected. Session ID: ${sessionId}\nHost: ${config.user}@${config.host}:${config.port}\nScreen: ${
|
|
59
|
+
content: [{ type: "text", text: `Connected. Session ID: ${sessionId}\nHost: ${config.user}@${config.host}:${config.port}\nScreen: ${w}x${h}` }],
|
|
55
60
|
};
|
|
56
61
|
}
|
|
57
62
|
catch (err) {
|
|
@@ -161,6 +166,50 @@ function createServer(manager) {
|
|
|
161
166
|
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
162
167
|
}
|
|
163
168
|
});
|
|
169
|
+
server.tool("key_press", "Press a key with optional modifier keys on the remote device. Requires /dev/uinput access.", {
|
|
170
|
+
sessionId: z.string().describe("Session ID from touch_connect"),
|
|
171
|
+
key: z.string().describe("Key name (e.g. 'enter', 'a', 'tab', 'f1', 'up', 'space')"),
|
|
172
|
+
modifiers: z.array(z.string()).optional().describe("Modifier keys to hold (e.g. ['ctrl'], ['ctrl', 'shift'])"),
|
|
173
|
+
}, async (params) => {
|
|
174
|
+
const cmd = {
|
|
175
|
+
id: `keypress-${Date.now()}`,
|
|
176
|
+
type: "key_press",
|
|
177
|
+
key: params.key,
|
|
178
|
+
modifiers: params.modifiers,
|
|
179
|
+
};
|
|
180
|
+
try {
|
|
181
|
+
const resp = await manager.sendCommand(params.sessionId, cmd);
|
|
182
|
+
if (resp.status === "error") {
|
|
183
|
+
return { content: [{ type: "text", text: `Key press failed: ${resp.message}` }], isError: true };
|
|
184
|
+
}
|
|
185
|
+
const mods = params.modifiers?.length ? params.modifiers.join("+") + "+" : "";
|
|
186
|
+
return { content: [{ type: "text", text: `Pressed ${mods}${params.key}` }] };
|
|
187
|
+
}
|
|
188
|
+
catch (err) {
|
|
189
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
server.tool("key_type", "Type a string of text on the remote device by simulating individual key presses. Requires /dev/uinput access.", {
|
|
193
|
+
sessionId: z.string().describe("Session ID from touch_connect"),
|
|
194
|
+
text: z.string().describe("Text to type (e.g. 'Hello, World!')"),
|
|
195
|
+
}, async (params) => {
|
|
196
|
+
const cmd = {
|
|
197
|
+
id: `keytype-${Date.now()}`,
|
|
198
|
+
type: "key_type",
|
|
199
|
+
text: params.text,
|
|
200
|
+
};
|
|
201
|
+
try {
|
|
202
|
+
const resp = await manager.sendCommand(params.sessionId, cmd);
|
|
203
|
+
if (resp.status === "error") {
|
|
204
|
+
return { content: [{ type: "text", text: `Key type failed: ${resp.message}` }], isError: true };
|
|
205
|
+
}
|
|
206
|
+
const display = params.text.length > 50 ? params.text.substring(0, 50) + "..." : params.text;
|
|
207
|
+
return { content: [{ type: "text", text: `Typed: ${display}` }] };
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
return { content: [{ type: "text", text: `Error: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
211
|
+
}
|
|
212
|
+
});
|
|
164
213
|
server.tool("touch_disconnect", "Disconnect a touch session and clean up the remote daemon.", {
|
|
165
214
|
sessionId: z.string().describe("Session ID to disconnect"),
|
|
166
215
|
}, async (params) => {
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/build/python-daemon.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PYTHON_DAEMON_SCRIPT = "\nimport sys\nimport os\nimport json\nimport struct\nimport fcntl\nimport time\n\n# ioctl constants\nUI_SET_EVBIT = 0x40045564\nUI_SET_ABSBIT = 0x40045567\nUI_SET_PROPBIT = 0x4004556e\nUI_DEV_SETUP = 0x405c5503\nUI_DEV_CREATE = 0x5501\nUI_DEV_DESTROY = 0x5502\n\n# Event types\nEV_SYN = 0x00\nEV_ABS = 0x03\n\n# Sync codes\nSYN_REPORT = 0x00\n\n# ABS codes\nABS_MT_SLOT = 0x2f\nABS_MT_TRACKING_ID = 0x39\nABS_MT_POSITION_X = 0x35\nABS_MT_POSITION_Y = 0x36\n\n# Input properties\nINPUT_PROP_DIRECT = 0x01\n\n# uinput_abs_setup struct: __u16 code, struct input_absinfo { __s32 value, min, max, fuzz, flat, resolution }\n# = HiiiiiI -> but let's use the raw struct\n# Actually uinput_abs_setup = __u16 + padding + input_absinfo(6 x __s32)\n# struct uinput_abs_setup { __u16 code; __u16 pad; struct input_absinfo { __s32 value, minimum, maximum, fuzz, flat, resolution; }; };\nUI_ABS_SETUP = 0x405c5504\n\nUINPUT_MAX_NAME_SIZE = 80\n\ndef make_input_event(tv_sec, tv_usec, ev_type, code, value):\n # struct input_event uses struct timeval (long, long) + __u16 + __u16 + __s32\n # native long size handles 32/64 bit automatically\n return struct.pack('llHHi', tv_sec, tv_usec, ev_type, code, value)\n\ndef write_event(fd, ev_type, code, value):\n now = time.time()\n sec = int(now)\n usec = int((now - sec) * 1000000)\n os.write(fd, make_input_event(sec, usec, ev_type, code, value))\n\ndef syn_report(fd):\n write_event(fd, EV_SYN, SYN_REPORT, 0)\n\ndef touch_down(fd, slot, tracking_id, x, y):\n write_event(fd, EV_ABS, ABS_MT_SLOT, slot)\n write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, tracking_id)\n write_event(fd, EV_ABS, ABS_MT_POSITION_X, x)\n write_event(fd, EV_ABS, ABS_MT_POSITION_Y, y)\n syn_report(fd)\n\ndef touch_move(fd, slot, x, y):\n write_event(fd, EV_ABS, ABS_MT_SLOT, slot)\n write_event(fd, EV_ABS, ABS_MT_POSITION_X, x)\n write_event(fd, EV_ABS, ABS_MT_POSITION_Y, y)\n syn_report(fd)\n\ndef touch_up(fd, slot):\n write_event(fd, EV_ABS, ABS_MT_SLOT, slot)\n write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, -1)\n syn_report(fd)\n\ndef setup_uinput(screen_width, screen_height):\n fd = os.open('/dev/uinput', os.O_WRONLY | os.O_NONBLOCK)\n\n # Enable EV_ABS\n fcntl.ioctl(fd, UI_SET_EVBIT, EV_ABS)\n\n # Enable ABS axes\n fcntl.ioctl(fd, UI_SET_ABSBIT, ABS_MT_SLOT)\n fcntl.ioctl(fd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID)\n fcntl.ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_X)\n fcntl.ioctl(fd, UI_SET_ABSBIT, ABS_MT_POSITION_Y)\n\n # Set INPUT_PROP_DIRECT for touchscreen\n fcntl.ioctl(fd, UI_SET_PROPBIT, INPUT_PROP_DIRECT)\n\n # Setup ABS axes with uinput_abs_setup\n # struct uinput_abs_setup { __u16 code; __u16 pad; struct input_absinfo { __s32 value, minimum, maximum, fuzz, flat, resolution; }; };\n abs_setup_fmt = 'HH6i'\n\n # ABS_MT_SLOT: 0 to 9\n data = struct.pack(abs_setup_fmt, ABS_MT_SLOT, 0, 0, 0, 9, 0, 0, 0)\n fcntl.ioctl(fd, UI_ABS_SETUP, data)\n\n # ABS_MT_TRACKING_ID: 0 to 65535\n data = struct.pack(abs_setup_fmt, ABS_MT_TRACKING_ID, 0, 0, 0, 65535, 0, 0, 0)\n fcntl.ioctl(fd, UI_ABS_SETUP, data)\n\n # ABS_MT_POSITION_X: 0 to screen_width - 1\n data = struct.pack(abs_setup_fmt, ABS_MT_POSITION_X, 0, 0, 0, screen_width - 1, 0, 0, 0)\n fcntl.ioctl(fd, UI_ABS_SETUP, data)\n\n # ABS_MT_POSITION_Y: 0 to screen_height - 1\n data = struct.pack(abs_setup_fmt, ABS_MT_POSITION_Y, 0, 0, 0, screen_height - 1, 0, 0, 0)\n fcntl.ioctl(fd, UI_ABS_SETUP, data)\n\n # uinput_setup: char name[UINPUT_MAX_NAME_SIZE]; struct input_id { __u16 bustype, vendor, product, version; };\n # struct input_id: HHH H (bustype=0x03 USB, vendor=0x1234, product=0x5678, version=1)\n # struct uinput_setup: 80s HHHH I (ff_effects_max)\n name = b'mcp-remotetouch'\n setup_data = struct.pack('80sHHHHI', name.ljust(UINPUT_MAX_NAME_SIZE, b'\\x00'), 0x03, 0x1234, 0x5678, 1, 0)\n fcntl.ioctl(fd, UI_DEV_SETUP, setup_data)\n\n # Create the device\n fcntl.ioctl(fd, UI_DEV_CREATE)\n\n # Give udev time to create the device node\n time.sleep(0.2)\n\n return fd\n\ndef send_response(cmd_id, status, message=None):\n resp = {'id': cmd_id, 'status': status}\n if message is not None:\n resp['message'] = message\n sys.stdout.write(json.dumps(resp) + '\\n')\n sys.stdout.flush()\n\ntracking_id_counter = 0\n\ndef next_tracking_id():\n global tracking_id_counter\n tracking_id_counter = (tracking_id_counter + 1) % 65536\n return tracking_id_counter\n\ndef handle_tap(fd, cmd):\n x = int(cmd['x'])\n y = int(cmd['y'])\n duration_ms = cmd.get('duration_ms', 50)\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(duration_ms / 1000.0)\n touch_up(fd, 0)\n\ndef handle_swipe(fd, cmd):\n x1 = int(cmd['x'])\n y1 = int(cmd['y'])\n x2 = int(cmd['x2'])\n y2 = int(cmd['y2'])\n duration_ms = cmd.get('duration_ms', 300)\n steps = cmd.get('steps', max(int(duration_ms / 15), 2))\n tid = next_tracking_id()\n\n touch_down(fd, 0, tid, x1, y1)\n for i in range(1, steps + 1):\n t = i / steps\n cx = int(x1 + (x2 - x1) * t)\n cy = int(y1 + (y2 - y1) * t)\n time.sleep(duration_ms / 1000.0 / steps)\n touch_move(fd, 0, cx, cy)\n touch_up(fd, 0)\n\ndef handle_long_press(fd, cmd):\n x = int(cmd['x'])\n y = int(cmd['y'])\n duration_ms = cmd.get('duration_ms', 800)\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(duration_ms / 1000.0)\n touch_up(fd, 0)\n\ndef handle_double_tap(fd, cmd):\n x = int(cmd['x'])\n y = int(cmd['y'])\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(0.05)\n touch_up(fd, 0)\n time.sleep(0.1)\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(0.05)\n touch_up(fd, 0)\n\ndef main():\n fd = None\n try:\n for line in sys.stdin:\n line = line.strip()\n if not line:\n continue\n try:\n cmd = json.loads(line)\n except json.JSONDecodeError as e:\n sys.stderr.write('Invalid JSON: ' + str(e) + '\\n')\n continue\n\n cmd_id = cmd.get('id', '?')\n cmd_type = cmd.get('type', '')\n\n try:\n if cmd_type == 'init':\n screen_width = cmd.get('screen_width', 800)\n screen_height = cmd.get('screen_height', 480)\n fd = setup_uinput(screen_width, screen_height)\n send_response(cmd_id, 'ready', 'uinput device created')\n elif cmd_type == 'shutdown':\n send_response(cmd_id, 'ok', 'shutting down')\n break\n elif fd is None:\n send_response(cmd_id, 'error', 'device not initialized, send init first')\n elif cmd_type == 'tap':\n handle_tap(fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'swipe':\n handle_swipe(fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'long_press':\n handle_long_press(fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'double_tap':\n handle_double_tap(fd, cmd)\n send_response(cmd_id, 'ok')\n else:\n send_response(cmd_id, 'error', 'unknown command: ' + cmd_type)\n except PermissionError:\n send_response(cmd_id, 'error', 'Permission denied accessing /dev/uinput. Ensure user is in the input group: sudo usermod -aG input $USER')\n except Exception as e:\n send_response(cmd_id, 'error', str(e))\n finally:\n if fd is not None:\n try:\n fcntl.ioctl(fd, UI_DEV_DESTROY)\n os.close(fd)\n except Exception:\n pass\n\nif __name__ == '__main__':\n main()\n";
|
|
1
|
+
export declare const PYTHON_DAEMON_SCRIPT = "\nimport sys\nimport os\nimport json\nimport struct\nimport time\nimport glob\nimport re\n\n# Event types\nEV_SYN = 0x00\nEV_KEY = 0x01\nEV_ABS = 0x03\n\n# Sync codes\nSYN_REPORT = 0x00\n\n# Key codes\nBTN_TOUCH = 0x14a\n\n# ABS codes\nABS_X = 0x00\nABS_Y = 0x01\nABS_MT_SLOT = 0x2f\nABS_MT_TRACKING_ID = 0x39\nABS_MT_POSITION_X = 0x35\nABS_MT_POSITION_Y = 0x36\n\n# uinput constants\nUI_SET_EVBIT = 0x40045564\nUI_SET_KEYBIT = 0x40045565\nUI_DEV_CREATE = 0x5501\nUI_DEV_DESTROY = 0x5502\nEV_REP = 0x14\n\n# Key code mapping: key name -> Linux keycode\nKEY_MAP = {\n 'a': 30, 'b': 48, 'c': 46, 'd': 32, 'e': 18, 'f': 33, 'g': 34, 'h': 35,\n 'i': 23, 'j': 36, 'k': 37, 'l': 38, 'm': 50, 'n': 49, 'o': 24, 'p': 25,\n 'q': 16, 'r': 19, 's': 31, 't': 20, 'u': 22, 'v': 47, 'w': 17, 'x': 45,\n 'y': 21, 'z': 44,\n '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, '8': 9, '9': 10, '0': 11,\n 'enter': 28, 'tab': 15, 'space': 57, 'backspace': 14, 'escape': 1, 'delete': 111,\n 'up': 103, 'down': 108, 'left': 105, 'right': 106,\n 'home': 102, 'end': 107, 'pageup': 104, 'pagedown': 109, 'insert': 110,\n 'ctrl': 29, 'shift': 42, 'alt': 56, 'meta': 125,\n 'ctrl_r': 97, 'shift_r': 54, 'alt_r': 100,\n 'f1': 59, 'f2': 60, 'f3': 61, 'f4': 62, 'f5': 63, 'f6': 64,\n 'f7': 65, 'f8': 66, 'f9': 67, 'f10': 68, 'f11': 87, 'f12': 88,\n 'minus': 12, 'equal': 13, 'leftbrace': 26, 'rightbrace': 27,\n 'semicolon': 39, 'apostrophe': 40, 'grave': 41, 'backslash': 43,\n 'comma': 51, 'dot': 52, 'slash': 53, 'capslock': 58,\n}\n\n# Character to (key_name, needs_shift) mapping for key_type\nCHAR_MAP = {\n 'a': ('a', False), 'b': ('b', False), 'c': ('c', False), 'd': ('d', False),\n 'e': ('e', False), 'f': ('f', False), 'g': ('g', False), 'h': ('h', False),\n 'i': ('i', False), 'j': ('j', False), 'k': ('k', False), 'l': ('l', False),\n 'm': ('m', False), 'n': ('n', False), 'o': ('o', False), 'p': ('p', False),\n 'q': ('q', False), 'r': ('r', False), 's': ('s', False), 't': ('t', False),\n 'u': ('u', False), 'v': ('v', False), 'w': ('w', False), 'x': ('x', False),\n 'y': ('y', False), 'z': ('z', False),\n 'A': ('a', True), 'B': ('b', True), 'C': ('c', True), 'D': ('d', True),\n 'E': ('e', True), 'F': ('f', True), 'G': ('g', True), 'H': ('h', True),\n 'I': ('i', True), 'J': ('j', True), 'K': ('k', True), 'L': ('l', True),\n 'M': ('m', True), 'N': ('n', True), 'O': ('o', True), 'P': ('p', True),\n 'Q': ('q', True), 'R': ('r', True), 'S': ('s', True), 'T': ('t', True),\n 'U': ('u', True), 'V': ('v', True), 'W': ('w', True), 'X': ('x', True),\n 'Y': ('y', True), 'Z': ('z', True),\n '0': ('0', False), '1': ('1', False), '2': ('2', False), '3': ('3', False),\n '4': ('4', False), '5': ('5', False), '6': ('6', False), '7': ('7', False),\n '8': ('8', False), '9': ('9', False),\n ' ': ('space', False), '\\t': ('tab', False), '\\n': ('enter', False),\n '-': ('minus', False), '=': ('equal', False),\n '[': ('leftbrace', False), ']': ('rightbrace', False),\n ';': ('semicolon', False), \"'\": ('apostrophe', False),\n '`': ('grave', False), '\\\\': ('backslash', False),\n ',': ('comma', False), '.': ('dot', False), '/': ('slash', False),\n '!': ('1', True), '@': ('2', True), '#': ('3', True), '$': ('4', True),\n '%': ('5', True), '^': ('6', True), '&': ('7', True), '*': ('8', True),\n '(': ('9', True), ')': ('0', True),\n '_': ('minus', True), '+': ('equal', True),\n '{': ('leftbrace', True), '}': ('rightbrace', True),\n ':': ('semicolon', True), '\"': ('apostrophe', True),\n '~': ('grave', True), '|': ('backslash', True),\n '<': ('comma', True), '>': ('dot', True), '?': ('slash', True),\n}\n\ndef setup_uinput_keyboard():\n \"\"\"Create a virtual keyboard device via /dev/uinput.\"\"\"\n uinput_fd = os.open('/dev/uinput', os.O_WRONLY | os.O_NONBLOCK)\n # Enable EV_KEY and EV_REP event types\n fcntl.ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY)\n fcntl.ioctl(uinput_fd, UI_SET_EVBIT, EV_REP)\n # Enable all keycodes in KEY_MAP\n for keycode in KEY_MAP.values():\n fcntl.ioctl(uinput_fd, UI_SET_KEYBIT, keycode)\n # Write uinput_user_dev struct: 80-byte name + 1036 bytes of zeros = 1116 bytes\n name = b'mcp-remotetouch-kbd'\n dev_struct = name + b'\\x00' * (80 - len(name)) # name[80]\n dev_struct += struct.pack('HH', 0x03, 0x01) # id: bustype=BUS_VIRTUAL, vendor\n dev_struct += struct.pack('HH', 0x01, 0x01) # id: product, version\n dev_struct += b'\\x00' * (1116 - len(dev_struct)) # ff_effects_max + absmin/max/fuzz/flat\n os.write(uinput_fd, dev_struct)\n fcntl.ioctl(uinput_fd, UI_DEV_CREATE)\n time.sleep(0.2) # Wait for device to be registered\n return uinput_fd\n\ndef destroy_uinput_keyboard(uinput_fd):\n \"\"\"Destroy the virtual keyboard device.\"\"\"\n try:\n fcntl.ioctl(uinput_fd, UI_DEV_DESTROY)\n except Exception:\n pass\n try:\n os.close(uinput_fd)\n except Exception:\n pass\n\ndef kbd_write_event(uinput_fd, ev_type, code, value):\n \"\"\"Write an input event to the uinput keyboard device.\"\"\"\n now = time.time()\n sec = int(now)\n usec = int((now - sec) * 1000000)\n os.write(uinput_fd, struct.pack('llHHi', sec, usec, ev_type, code, value))\n\ndef kbd_syn(uinput_fd):\n kbd_write_event(uinput_fd, EV_SYN, SYN_REPORT, 0)\n\ndef handle_key_press(uinput_fd, cmd):\n \"\"\"Handle key_press command: press a key with optional modifiers.\"\"\"\n key = cmd.get('key', '').lower()\n modifiers = cmd.get('modifiers', [])\n keycode = KEY_MAP.get(key)\n if keycode is None:\n raise ValueError('Unknown key: ' + cmd.get('key', ''))\n # Press modifier keys\n mod_codes = []\n for mod in modifiers:\n mc = KEY_MAP.get(mod.lower())\n if mc is None:\n raise ValueError('Unknown modifier: ' + mod)\n mod_codes.append(mc)\n kbd_write_event(uinput_fd, EV_KEY, mc, 1)\n kbd_syn(uinput_fd)\n # Press and release main key\n kbd_write_event(uinput_fd, EV_KEY, keycode, 1)\n kbd_syn(uinput_fd)\n time.sleep(0.02)\n kbd_write_event(uinput_fd, EV_KEY, keycode, 0)\n kbd_syn(uinput_fd)\n # Release modifiers in reverse order\n for mc in reversed(mod_codes):\n kbd_write_event(uinput_fd, EV_KEY, mc, 0)\n kbd_syn(uinput_fd)\n\ndef handle_key_type(uinput_fd, cmd):\n \"\"\"Handle key_type command: type a string of text character by character.\"\"\"\n text = cmd.get('text', '')\n shift_code = KEY_MAP['shift']\n for ch in text:\n entry = CHAR_MAP.get(ch)\n if entry is None:\n continue # Skip unmapped characters\n key_name, needs_shift = entry\n keycode = KEY_MAP[key_name]\n if needs_shift:\n kbd_write_event(uinput_fd, EV_KEY, shift_code, 1)\n kbd_syn(uinput_fd)\n kbd_write_event(uinput_fd, EV_KEY, keycode, 1)\n kbd_syn(uinput_fd)\n time.sleep(0.01)\n kbd_write_event(uinput_fd, EV_KEY, keycode, 0)\n kbd_syn(uinput_fd)\n if needs_shift:\n kbd_write_event(uinput_fd, EV_KEY, shift_code, 0)\n kbd_syn(uinput_fd)\n time.sleep(0.01)\n\n# EVIOCGABS ioctl: _IOR('E', 0x40 + abs_code, struct input_absinfo)\n# struct input_absinfo = 6 x __s32 = 24 bytes\n# _IOR('E', N, 24) = (2 << 30) | (24 << 16) | (ord('E') << 8) | N\ndef EVIOCGABS(abs_code):\n return (2 << 30) | (24 << 16) | (ord('E') << 8) | (0x40 + abs_code)\n\ndef make_input_event(tv_sec, tv_usec, ev_type, code, value):\n return struct.pack('llHHi', tv_sec, tv_usec, ev_type, code, value)\n\ndef write_event(fd, ev_type, code, value):\n now = time.time()\n sec = int(now)\n usec = int((now - sec) * 1000000)\n os.write(fd, make_input_event(sec, usec, ev_type, code, value))\n\ndef syn_report(fd):\n write_event(fd, EV_SYN, SYN_REPORT, 0)\n\ndef touch_down(fd, slot, tracking_id, x, y):\n write_event(fd, EV_ABS, ABS_MT_SLOT, slot)\n write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, tracking_id)\n write_event(fd, EV_ABS, ABS_MT_POSITION_X, x)\n write_event(fd, EV_ABS, ABS_MT_POSITION_Y, y)\n write_event(fd, EV_ABS, ABS_X, x)\n write_event(fd, EV_ABS, ABS_Y, y)\n write_event(fd, EV_KEY, BTN_TOUCH, 1)\n syn_report(fd)\n\ndef touch_move(fd, slot, x, y):\n write_event(fd, EV_ABS, ABS_MT_SLOT, slot)\n write_event(fd, EV_ABS, ABS_MT_POSITION_X, x)\n write_event(fd, EV_ABS, ABS_MT_POSITION_Y, y)\n write_event(fd, EV_ABS, ABS_X, x)\n write_event(fd, EV_ABS, ABS_Y, y)\n syn_report(fd)\n\ndef touch_up(fd, slot):\n write_event(fd, EV_ABS, ABS_MT_SLOT, slot)\n write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, -1)\n write_event(fd, EV_KEY, BTN_TOUCH, 0)\n syn_report(fd)\n\ndef detect_screen_resolution():\n \"\"\"Detect screen resolution from framebuffer or DRM.\"\"\"\n # Try framebuffer first\n try:\n with open('/sys/class/graphics/fb0/virtual_size', 'r') as f:\n parts = f.read().strip().split(',')\n if len(parts) == 2:\n return int(parts[0]), int(parts[1])\n except Exception:\n pass\n\n # Try DRM\n try:\n import glob as g\n for mode_path in g.glob('/sys/class/drm/*/modes'):\n with open(mode_path, 'r') as f:\n line = f.readline().strip()\n if 'x' in line:\n parts = line.split('x')\n return int(parts[0]), int(parts[1])\n except Exception:\n pass\n\n return None, None\n\ndef find_touchscreen():\n \"\"\"Find the physical touchscreen event device by scanning /proc/bus/input/devices.\"\"\"\n try:\n with open('/proc/bus/input/devices', 'r') as f:\n content = f.read()\n except Exception:\n return None\n\n for block in content.split('\\n\\n'):\n lines = block.strip().split('\\n')\n name = ''\n handlers = ''\n props = ''\n evbits = ''\n absbits = ''\n for line in lines:\n if line.startswith('N: Name='):\n name = line.split('=', 1)[1].strip('\"')\n elif line.startswith('H: Handlers='):\n handlers = line.split('=', 1)[1]\n elif line.startswith('B: PROP='):\n props = line.split('=', 1)[1]\n elif line.startswith('B: EV='):\n evbits = line.split('=', 1)[1]\n elif line.startswith('B: ABS='):\n absbits = line.split('=', 1)[1]\n\n # Skip virtual devices (mcp-remotetouch)\n if 'mcp-remotetouch' in name:\n continue\n\n # Check for INPUT_PROP_DIRECT (bit 1 in PROP)\n try:\n prop_val = int(props.strip(), 16)\n except (ValueError, IndexError):\n prop_val = 0\n if not (prop_val & 0x02):\n continue\n\n # Check that it has ABS_MT_POSITION_X (bit 0x35) in ABS bitmask\n try:\n abs_parts = absbits.strip().split()\n abs_val = 0\n for i, part in enumerate(reversed(abs_parts)):\n abs_val |= int(part, 16) << (i * 32)\n except (ValueError, IndexError):\n abs_val = 0\n if not (abs_val & (1 << ABS_MT_POSITION_X)):\n continue\n\n # Extract event device number\n m = re.search(r'event(\\d+)', handlers)\n if m:\n return '/dev/input/event' + m.group(1)\n\n return None\n\nimport fcntl\n\ndef get_abs_range(fd, abs_code):\n \"\"\"Get the min/max range of an ABS axis using EVIOCGABS ioctl.\"\"\"\n try:\n buf = bytearray(24)\n fcntl.ioctl(fd, EVIOCGABS(abs_code), buf)\n value, minimum, maximum, fuzz, flat, resolution = struct.unpack('6i', buf)\n return minimum, maximum\n except Exception:\n return None, None\n\ndef open_touch_device(screen_width, screen_height):\n \"\"\"Open the physical touchscreen device for event injection.\"\"\"\n dev_path = find_touchscreen()\n if dev_path is None:\n raise RuntimeError('No physical touchscreen device found')\n\n fd = os.open(dev_path, os.O_WRONLY)\n\n # Read the actual ABS ranges from the device\n rd_fd = os.open(dev_path, os.O_RDONLY)\n x_min, x_max = get_abs_range(rd_fd, ABS_MT_POSITION_X)\n y_min, y_max = get_abs_range(rd_fd, ABS_MT_POSITION_Y)\n os.close(rd_fd)\n\n if x_max is None or y_max is None:\n x_max = screen_width - 1\n y_max = screen_height - 1\n x_min = 0\n y_min = 0\n\n return fd, dev_path, x_min, x_max, y_min, y_max\n\ndef send_response(cmd_id, status, message=None, screen_width=None, screen_height=None):\n resp = {'id': cmd_id, 'status': status}\n if message is not None:\n resp['message'] = message\n if screen_width is not None:\n resp['screen_width'] = screen_width\n if screen_height is not None:\n resp['screen_height'] = screen_height\n sys.stdout.write(json.dumps(resp) + '\\n')\n sys.stdout.flush()\n\ntracking_id_counter = 0\n\ndef next_tracking_id():\n global tracking_id_counter\n tracking_id_counter = (tracking_id_counter + 1) % 65536\n return tracking_id_counter\n\n# Coordinate mapping globals\ndev_x_min = 0\ndev_x_max = 0\ndev_y_min = 0\ndev_y_max = 0\nscr_w = 0\nscr_h = 0\n\ndef map_x(x):\n \"\"\"Map screen coordinate to device coordinate.\"\"\"\n return dev_x_min + int(x * (dev_x_max - dev_x_min) / (scr_w - 1))\n\ndef map_y(y):\n \"\"\"Map screen coordinate to device coordinate.\"\"\"\n return dev_y_min + int(y * (dev_y_max - dev_y_min) / (scr_h - 1))\n\ndef handle_tap(fd, cmd):\n x = map_x(int(cmd['x']))\n y = map_y(int(cmd['y']))\n duration_ms = cmd.get('duration_ms', 50)\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(duration_ms / 1000.0)\n touch_up(fd, 0)\n\ndef handle_swipe(fd, cmd):\n x1 = int(cmd['x'])\n y1 = int(cmd['y'])\n x2 = int(cmd['x2'])\n y2 = int(cmd['y2'])\n duration_ms = cmd.get('duration_ms', 300)\n steps = cmd.get('steps', max(int(duration_ms / 15), 2))\n tid = next_tracking_id()\n\n touch_down(fd, 0, tid, map_x(x1), map_y(y1))\n for i in range(1, steps + 1):\n t = i / steps\n cx = int(x1 + (x2 - x1) * t)\n cy = int(y1 + (y2 - y1) * t)\n time.sleep(duration_ms / 1000.0 / steps)\n touch_move(fd, 0, map_x(cx), map_y(cy))\n touch_up(fd, 0)\n\ndef handle_long_press(fd, cmd):\n x = map_x(int(cmd['x']))\n y = map_y(int(cmd['y']))\n duration_ms = cmd.get('duration_ms', 800)\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(duration_ms / 1000.0)\n touch_up(fd, 0)\n\ndef handle_double_tap(fd, cmd):\n x = map_x(int(cmd['x']))\n y = map_y(int(cmd['y']))\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(0.05)\n touch_up(fd, 0)\n time.sleep(0.1)\n tid = next_tracking_id()\n touch_down(fd, 0, tid, x, y)\n time.sleep(0.05)\n touch_up(fd, 0)\n\ndef main():\n global dev_x_min, dev_x_max, dev_y_min, dev_y_max, scr_w, scr_h\n fd = None\n kbd_fd = None\n try:\n for line in sys.stdin:\n line = line.strip()\n if not line:\n continue\n try:\n cmd = json.loads(line)\n except json.JSONDecodeError as e:\n sys.stderr.write('Invalid JSON: ' + str(e) + '\\n')\n continue\n\n cmd_id = cmd.get('id', '?')\n cmd_type = cmd.get('type', '')\n\n try:\n if cmd_type == 'init':\n scr_w = cmd.get('screen_width', 0)\n scr_h = cmd.get('screen_height', 0)\n if scr_w <= 0 or scr_h <= 0:\n det_w, det_h = detect_screen_resolution()\n if det_w and det_h:\n scr_w = det_w\n scr_h = det_h\n else:\n scr_w = scr_w or 800\n scr_h = scr_h or 480\n fd, dev_path, dev_x_min, dev_x_max, dev_y_min, dev_y_max = open_touch_device(scr_w, scr_h)\n # Best-effort keyboard setup \u2014 touch works even if uinput fails\n try:\n kbd_fd = setup_uinput_keyboard()\n kbd_msg = ' (keyboard: ok)'\n except Exception as ke:\n kbd_fd = None\n kbd_msg = ' (keyboard: unavailable - ' + str(ke) + ')'\n send_response(cmd_id, 'ready', 'injecting into ' + dev_path + kbd_msg, scr_w, scr_h)\n elif cmd_type == 'shutdown':\n send_response(cmd_id, 'ok', 'shutting down')\n break\n elif fd is None:\n send_response(cmd_id, 'error', 'device not initialized, send init first')\n elif cmd_type == 'tap':\n handle_tap(fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'swipe':\n handle_swipe(fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'long_press':\n handle_long_press(fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'double_tap':\n handle_double_tap(fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'key_press':\n if kbd_fd is None:\n send_response(cmd_id, 'error', 'keyboard not available: /dev/uinput not accessible')\n else:\n handle_key_press(kbd_fd, cmd)\n send_response(cmd_id, 'ok')\n elif cmd_type == 'key_type':\n if kbd_fd is None:\n send_response(cmd_id, 'error', 'keyboard not available: /dev/uinput not accessible')\n else:\n handle_key_type(kbd_fd, cmd)\n send_response(cmd_id, 'ok')\n else:\n send_response(cmd_id, 'error', 'unknown command: ' + cmd_type)\n except PermissionError:\n send_response(cmd_id, 'error', 'Permission denied. Run with sudo or ensure user is in the input group: sudo usermod -aG input $USER')\n except Exception as e:\n send_response(cmd_id, 'error', str(e))\n finally:\n if kbd_fd is not None:\n destroy_uinput_keyboard(kbd_fd)\n if fd is not None:\n try:\n os.close(fd)\n except Exception:\n pass\n\nif __name__ == '__main__':\n main()\n";
|
package/build/python-daemon.js
CHANGED
|
@@ -3,44 +3,188 @@ import sys
|
|
|
3
3
|
import os
|
|
4
4
|
import json
|
|
5
5
|
import struct
|
|
6
|
-
import fcntl
|
|
7
6
|
import time
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
UI_SET_EVBIT = 0x40045564
|
|
11
|
-
UI_SET_ABSBIT = 0x40045567
|
|
12
|
-
UI_SET_PROPBIT = 0x4004556e
|
|
13
|
-
UI_DEV_SETUP = 0x405c5503
|
|
14
|
-
UI_DEV_CREATE = 0x5501
|
|
15
|
-
UI_DEV_DESTROY = 0x5502
|
|
7
|
+
import glob
|
|
8
|
+
import re
|
|
16
9
|
|
|
17
10
|
# Event types
|
|
18
11
|
EV_SYN = 0x00
|
|
12
|
+
EV_KEY = 0x01
|
|
19
13
|
EV_ABS = 0x03
|
|
20
14
|
|
|
21
15
|
# Sync codes
|
|
22
16
|
SYN_REPORT = 0x00
|
|
23
17
|
|
|
18
|
+
# Key codes
|
|
19
|
+
BTN_TOUCH = 0x14a
|
|
20
|
+
|
|
24
21
|
# ABS codes
|
|
22
|
+
ABS_X = 0x00
|
|
23
|
+
ABS_Y = 0x01
|
|
25
24
|
ABS_MT_SLOT = 0x2f
|
|
26
25
|
ABS_MT_TRACKING_ID = 0x39
|
|
27
26
|
ABS_MT_POSITION_X = 0x35
|
|
28
27
|
ABS_MT_POSITION_Y = 0x36
|
|
29
28
|
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
# uinput constants
|
|
30
|
+
UI_SET_EVBIT = 0x40045564
|
|
31
|
+
UI_SET_KEYBIT = 0x40045565
|
|
32
|
+
UI_DEV_CREATE = 0x5501
|
|
33
|
+
UI_DEV_DESTROY = 0x5502
|
|
34
|
+
EV_REP = 0x14
|
|
35
|
+
|
|
36
|
+
# Key code mapping: key name -> Linux keycode
|
|
37
|
+
KEY_MAP = {
|
|
38
|
+
'a': 30, 'b': 48, 'c': 46, 'd': 32, 'e': 18, 'f': 33, 'g': 34, 'h': 35,
|
|
39
|
+
'i': 23, 'j': 36, 'k': 37, 'l': 38, 'm': 50, 'n': 49, 'o': 24, 'p': 25,
|
|
40
|
+
'q': 16, 'r': 19, 's': 31, 't': 20, 'u': 22, 'v': 47, 'w': 17, 'x': 45,
|
|
41
|
+
'y': 21, 'z': 44,
|
|
42
|
+
'1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, '8': 9, '9': 10, '0': 11,
|
|
43
|
+
'enter': 28, 'tab': 15, 'space': 57, 'backspace': 14, 'escape': 1, 'delete': 111,
|
|
44
|
+
'up': 103, 'down': 108, 'left': 105, 'right': 106,
|
|
45
|
+
'home': 102, 'end': 107, 'pageup': 104, 'pagedown': 109, 'insert': 110,
|
|
46
|
+
'ctrl': 29, 'shift': 42, 'alt': 56, 'meta': 125,
|
|
47
|
+
'ctrl_r': 97, 'shift_r': 54, 'alt_r': 100,
|
|
48
|
+
'f1': 59, 'f2': 60, 'f3': 61, 'f4': 62, 'f5': 63, 'f6': 64,
|
|
49
|
+
'f7': 65, 'f8': 66, 'f9': 67, 'f10': 68, 'f11': 87, 'f12': 88,
|
|
50
|
+
'minus': 12, 'equal': 13, 'leftbrace': 26, 'rightbrace': 27,
|
|
51
|
+
'semicolon': 39, 'apostrophe': 40, 'grave': 41, 'backslash': 43,
|
|
52
|
+
'comma': 51, 'dot': 52, 'slash': 53, 'capslock': 58,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# Character to (key_name, needs_shift) mapping for key_type
|
|
56
|
+
CHAR_MAP = {
|
|
57
|
+
'a': ('a', False), 'b': ('b', False), 'c': ('c', False), 'd': ('d', False),
|
|
58
|
+
'e': ('e', False), 'f': ('f', False), 'g': ('g', False), 'h': ('h', False),
|
|
59
|
+
'i': ('i', False), 'j': ('j', False), 'k': ('k', False), 'l': ('l', False),
|
|
60
|
+
'm': ('m', False), 'n': ('n', False), 'o': ('o', False), 'p': ('p', False),
|
|
61
|
+
'q': ('q', False), 'r': ('r', False), 's': ('s', False), 't': ('t', False),
|
|
62
|
+
'u': ('u', False), 'v': ('v', False), 'w': ('w', False), 'x': ('x', False),
|
|
63
|
+
'y': ('y', False), 'z': ('z', False),
|
|
64
|
+
'A': ('a', True), 'B': ('b', True), 'C': ('c', True), 'D': ('d', True),
|
|
65
|
+
'E': ('e', True), 'F': ('f', True), 'G': ('g', True), 'H': ('h', True),
|
|
66
|
+
'I': ('i', True), 'J': ('j', True), 'K': ('k', True), 'L': ('l', True),
|
|
67
|
+
'M': ('m', True), 'N': ('n', True), 'O': ('o', True), 'P': ('p', True),
|
|
68
|
+
'Q': ('q', True), 'R': ('r', True), 'S': ('s', True), 'T': ('t', True),
|
|
69
|
+
'U': ('u', True), 'V': ('v', True), 'W': ('w', True), 'X': ('x', True),
|
|
70
|
+
'Y': ('y', True), 'Z': ('z', True),
|
|
71
|
+
'0': ('0', False), '1': ('1', False), '2': ('2', False), '3': ('3', False),
|
|
72
|
+
'4': ('4', False), '5': ('5', False), '6': ('6', False), '7': ('7', False),
|
|
73
|
+
'8': ('8', False), '9': ('9', False),
|
|
74
|
+
' ': ('space', False), '\\t': ('tab', False), '\\n': ('enter', False),
|
|
75
|
+
'-': ('minus', False), '=': ('equal', False),
|
|
76
|
+
'[': ('leftbrace', False), ']': ('rightbrace', False),
|
|
77
|
+
';': ('semicolon', False), "'": ('apostrophe', False),
|
|
78
|
+
'\`': ('grave', False), '\\\\': ('backslash', False),
|
|
79
|
+
',': ('comma', False), '.': ('dot', False), '/': ('slash', False),
|
|
80
|
+
'!': ('1', True), '@': ('2', True), '#': ('3', True), '$': ('4', True),
|
|
81
|
+
'%': ('5', True), '^': ('6', True), '&': ('7', True), '*': ('8', True),
|
|
82
|
+
'(': ('9', True), ')': ('0', True),
|
|
83
|
+
'_': ('minus', True), '+': ('equal', True),
|
|
84
|
+
'{': ('leftbrace', True), '}': ('rightbrace', True),
|
|
85
|
+
':': ('semicolon', True), '"': ('apostrophe', True),
|
|
86
|
+
'~': ('grave', True), '|': ('backslash', True),
|
|
87
|
+
'<': ('comma', True), '>': ('dot', True), '?': ('slash', True),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def setup_uinput_keyboard():
|
|
91
|
+
"""Create a virtual keyboard device via /dev/uinput."""
|
|
92
|
+
uinput_fd = os.open('/dev/uinput', os.O_WRONLY | os.O_NONBLOCK)
|
|
93
|
+
# Enable EV_KEY and EV_REP event types
|
|
94
|
+
fcntl.ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY)
|
|
95
|
+
fcntl.ioctl(uinput_fd, UI_SET_EVBIT, EV_REP)
|
|
96
|
+
# Enable all keycodes in KEY_MAP
|
|
97
|
+
for keycode in KEY_MAP.values():
|
|
98
|
+
fcntl.ioctl(uinput_fd, UI_SET_KEYBIT, keycode)
|
|
99
|
+
# Write uinput_user_dev struct: 80-byte name + 1036 bytes of zeros = 1116 bytes
|
|
100
|
+
name = b'mcp-remotetouch-kbd'
|
|
101
|
+
dev_struct = name + b'\\x00' * (80 - len(name)) # name[80]
|
|
102
|
+
dev_struct += struct.pack('HH', 0x03, 0x01) # id: bustype=BUS_VIRTUAL, vendor
|
|
103
|
+
dev_struct += struct.pack('HH', 0x01, 0x01) # id: product, version
|
|
104
|
+
dev_struct += b'\\x00' * (1116 - len(dev_struct)) # ff_effects_max + absmin/max/fuzz/flat
|
|
105
|
+
os.write(uinput_fd, dev_struct)
|
|
106
|
+
fcntl.ioctl(uinput_fd, UI_DEV_CREATE)
|
|
107
|
+
time.sleep(0.2) # Wait for device to be registered
|
|
108
|
+
return uinput_fd
|
|
109
|
+
|
|
110
|
+
def destroy_uinput_keyboard(uinput_fd):
|
|
111
|
+
"""Destroy the virtual keyboard device."""
|
|
112
|
+
try:
|
|
113
|
+
fcntl.ioctl(uinput_fd, UI_DEV_DESTROY)
|
|
114
|
+
except Exception:
|
|
115
|
+
pass
|
|
116
|
+
try:
|
|
117
|
+
os.close(uinput_fd)
|
|
118
|
+
except Exception:
|
|
119
|
+
pass
|
|
38
120
|
|
|
39
|
-
|
|
121
|
+
def kbd_write_event(uinput_fd, ev_type, code, value):
|
|
122
|
+
"""Write an input event to the uinput keyboard device."""
|
|
123
|
+
now = time.time()
|
|
124
|
+
sec = int(now)
|
|
125
|
+
usec = int((now - sec) * 1000000)
|
|
126
|
+
os.write(uinput_fd, struct.pack('llHHi', sec, usec, ev_type, code, value))
|
|
127
|
+
|
|
128
|
+
def kbd_syn(uinput_fd):
|
|
129
|
+
kbd_write_event(uinput_fd, EV_SYN, SYN_REPORT, 0)
|
|
130
|
+
|
|
131
|
+
def handle_key_press(uinput_fd, cmd):
|
|
132
|
+
"""Handle key_press command: press a key with optional modifiers."""
|
|
133
|
+
key = cmd.get('key', '').lower()
|
|
134
|
+
modifiers = cmd.get('modifiers', [])
|
|
135
|
+
keycode = KEY_MAP.get(key)
|
|
136
|
+
if keycode is None:
|
|
137
|
+
raise ValueError('Unknown key: ' + cmd.get('key', ''))
|
|
138
|
+
# Press modifier keys
|
|
139
|
+
mod_codes = []
|
|
140
|
+
for mod in modifiers:
|
|
141
|
+
mc = KEY_MAP.get(mod.lower())
|
|
142
|
+
if mc is None:
|
|
143
|
+
raise ValueError('Unknown modifier: ' + mod)
|
|
144
|
+
mod_codes.append(mc)
|
|
145
|
+
kbd_write_event(uinput_fd, EV_KEY, mc, 1)
|
|
146
|
+
kbd_syn(uinput_fd)
|
|
147
|
+
# Press and release main key
|
|
148
|
+
kbd_write_event(uinput_fd, EV_KEY, keycode, 1)
|
|
149
|
+
kbd_syn(uinput_fd)
|
|
150
|
+
time.sleep(0.02)
|
|
151
|
+
kbd_write_event(uinput_fd, EV_KEY, keycode, 0)
|
|
152
|
+
kbd_syn(uinput_fd)
|
|
153
|
+
# Release modifiers in reverse order
|
|
154
|
+
for mc in reversed(mod_codes):
|
|
155
|
+
kbd_write_event(uinput_fd, EV_KEY, mc, 0)
|
|
156
|
+
kbd_syn(uinput_fd)
|
|
157
|
+
|
|
158
|
+
def handle_key_type(uinput_fd, cmd):
|
|
159
|
+
"""Handle key_type command: type a string of text character by character."""
|
|
160
|
+
text = cmd.get('text', '')
|
|
161
|
+
shift_code = KEY_MAP['shift']
|
|
162
|
+
for ch in text:
|
|
163
|
+
entry = CHAR_MAP.get(ch)
|
|
164
|
+
if entry is None:
|
|
165
|
+
continue # Skip unmapped characters
|
|
166
|
+
key_name, needs_shift = entry
|
|
167
|
+
keycode = KEY_MAP[key_name]
|
|
168
|
+
if needs_shift:
|
|
169
|
+
kbd_write_event(uinput_fd, EV_KEY, shift_code, 1)
|
|
170
|
+
kbd_syn(uinput_fd)
|
|
171
|
+
kbd_write_event(uinput_fd, EV_KEY, keycode, 1)
|
|
172
|
+
kbd_syn(uinput_fd)
|
|
173
|
+
time.sleep(0.01)
|
|
174
|
+
kbd_write_event(uinput_fd, EV_KEY, keycode, 0)
|
|
175
|
+
kbd_syn(uinput_fd)
|
|
176
|
+
if needs_shift:
|
|
177
|
+
kbd_write_event(uinput_fd, EV_KEY, shift_code, 0)
|
|
178
|
+
kbd_syn(uinput_fd)
|
|
179
|
+
time.sleep(0.01)
|
|
180
|
+
|
|
181
|
+
# EVIOCGABS ioctl: _IOR('E', 0x40 + abs_code, struct input_absinfo)
|
|
182
|
+
# struct input_absinfo = 6 x __s32 = 24 bytes
|
|
183
|
+
# _IOR('E', N, 24) = (2 << 30) | (24 << 16) | (ord('E') << 8) | N
|
|
184
|
+
def EVIOCGABS(abs_code):
|
|
185
|
+
return (2 << 30) | (24 << 16) | (ord('E') << 8) | (0x40 + abs_code)
|
|
40
186
|
|
|
41
187
|
def make_input_event(tv_sec, tv_usec, ev_type, code, value):
|
|
42
|
-
# struct input_event uses struct timeval (long, long) + __u16 + __u16 + __s32
|
|
43
|
-
# native long size handles 32/64 bit automatically
|
|
44
188
|
return struct.pack('llHHi', tv_sec, tv_usec, ev_type, code, value)
|
|
45
189
|
|
|
46
190
|
def write_event(fd, ev_type, code, value):
|
|
@@ -57,73 +201,149 @@ def touch_down(fd, slot, tracking_id, x, y):
|
|
|
57
201
|
write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, tracking_id)
|
|
58
202
|
write_event(fd, EV_ABS, ABS_MT_POSITION_X, x)
|
|
59
203
|
write_event(fd, EV_ABS, ABS_MT_POSITION_Y, y)
|
|
204
|
+
write_event(fd, EV_ABS, ABS_X, x)
|
|
205
|
+
write_event(fd, EV_ABS, ABS_Y, y)
|
|
206
|
+
write_event(fd, EV_KEY, BTN_TOUCH, 1)
|
|
60
207
|
syn_report(fd)
|
|
61
208
|
|
|
62
209
|
def touch_move(fd, slot, x, y):
|
|
63
210
|
write_event(fd, EV_ABS, ABS_MT_SLOT, slot)
|
|
64
211
|
write_event(fd, EV_ABS, ABS_MT_POSITION_X, x)
|
|
65
212
|
write_event(fd, EV_ABS, ABS_MT_POSITION_Y, y)
|
|
213
|
+
write_event(fd, EV_ABS, ABS_X, x)
|
|
214
|
+
write_event(fd, EV_ABS, ABS_Y, y)
|
|
66
215
|
syn_report(fd)
|
|
67
216
|
|
|
68
217
|
def touch_up(fd, slot):
|
|
69
218
|
write_event(fd, EV_ABS, ABS_MT_SLOT, slot)
|
|
70
219
|
write_event(fd, EV_ABS, ABS_MT_TRACKING_ID, -1)
|
|
220
|
+
write_event(fd, EV_KEY, BTN_TOUCH, 0)
|
|
71
221
|
syn_report(fd)
|
|
72
222
|
|
|
73
|
-
def
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
223
|
+
def detect_screen_resolution():
|
|
224
|
+
"""Detect screen resolution from framebuffer or DRM."""
|
|
225
|
+
# Try framebuffer first
|
|
226
|
+
try:
|
|
227
|
+
with open('/sys/class/graphics/fb0/virtual_size', 'r') as f:
|
|
228
|
+
parts = f.read().strip().split(',')
|
|
229
|
+
if len(parts) == 2:
|
|
230
|
+
return int(parts[0]), int(parts[1])
|
|
231
|
+
except Exception:
|
|
232
|
+
pass
|
|
233
|
+
|
|
234
|
+
# Try DRM
|
|
235
|
+
try:
|
|
236
|
+
import glob as g
|
|
237
|
+
for mode_path in g.glob('/sys/class/drm/*/modes'):
|
|
238
|
+
with open(mode_path, 'r') as f:
|
|
239
|
+
line = f.readline().strip()
|
|
240
|
+
if 'x' in line:
|
|
241
|
+
parts = line.split('x')
|
|
242
|
+
return int(parts[0]), int(parts[1])
|
|
243
|
+
except Exception:
|
|
244
|
+
pass
|
|
245
|
+
|
|
246
|
+
return None, None
|
|
247
|
+
|
|
248
|
+
def find_touchscreen():
|
|
249
|
+
"""Find the physical touchscreen event device by scanning /proc/bus/input/devices."""
|
|
250
|
+
try:
|
|
251
|
+
with open('/proc/bus/input/devices', 'r') as f:
|
|
252
|
+
content = f.read()
|
|
253
|
+
except Exception:
|
|
254
|
+
return None
|
|
255
|
+
|
|
256
|
+
for block in content.split('\\n\\n'):
|
|
257
|
+
lines = block.strip().split('\\n')
|
|
258
|
+
name = ''
|
|
259
|
+
handlers = ''
|
|
260
|
+
props = ''
|
|
261
|
+
evbits = ''
|
|
262
|
+
absbits = ''
|
|
263
|
+
for line in lines:
|
|
264
|
+
if line.startswith('N: Name='):
|
|
265
|
+
name = line.split('=', 1)[1].strip('"')
|
|
266
|
+
elif line.startswith('H: Handlers='):
|
|
267
|
+
handlers = line.split('=', 1)[1]
|
|
268
|
+
elif line.startswith('B: PROP='):
|
|
269
|
+
props = line.split('=', 1)[1]
|
|
270
|
+
elif line.startswith('B: EV='):
|
|
271
|
+
evbits = line.split('=', 1)[1]
|
|
272
|
+
elif line.startswith('B: ABS='):
|
|
273
|
+
absbits = line.split('=', 1)[1]
|
|
274
|
+
|
|
275
|
+
# Skip virtual devices (mcp-remotetouch)
|
|
276
|
+
if 'mcp-remotetouch' in name:
|
|
277
|
+
continue
|
|
278
|
+
|
|
279
|
+
# Check for INPUT_PROP_DIRECT (bit 1 in PROP)
|
|
280
|
+
try:
|
|
281
|
+
prop_val = int(props.strip(), 16)
|
|
282
|
+
except (ValueError, IndexError):
|
|
283
|
+
prop_val = 0
|
|
284
|
+
if not (prop_val & 0x02):
|
|
285
|
+
continue
|
|
286
|
+
|
|
287
|
+
# Check that it has ABS_MT_POSITION_X (bit 0x35) in ABS bitmask
|
|
288
|
+
try:
|
|
289
|
+
abs_parts = absbits.strip().split()
|
|
290
|
+
abs_val = 0
|
|
291
|
+
for i, part in enumerate(reversed(abs_parts)):
|
|
292
|
+
abs_val |= int(part, 16) << (i * 32)
|
|
293
|
+
except (ValueError, IndexError):
|
|
294
|
+
abs_val = 0
|
|
295
|
+
if not (abs_val & (1 << ABS_MT_POSITION_X)):
|
|
296
|
+
continue
|
|
297
|
+
|
|
298
|
+
# Extract event device number
|
|
299
|
+
m = re.search(r'event(\\d+)', handlers)
|
|
300
|
+
if m:
|
|
301
|
+
return '/dev/input/event' + m.group(1)
|
|
302
|
+
|
|
303
|
+
return None
|
|
120
304
|
|
|
121
|
-
|
|
305
|
+
import fcntl
|
|
122
306
|
|
|
123
|
-
def
|
|
307
|
+
def get_abs_range(fd, abs_code):
|
|
308
|
+
"""Get the min/max range of an ABS axis using EVIOCGABS ioctl."""
|
|
309
|
+
try:
|
|
310
|
+
buf = bytearray(24)
|
|
311
|
+
fcntl.ioctl(fd, EVIOCGABS(abs_code), buf)
|
|
312
|
+
value, minimum, maximum, fuzz, flat, resolution = struct.unpack('6i', buf)
|
|
313
|
+
return minimum, maximum
|
|
314
|
+
except Exception:
|
|
315
|
+
return None, None
|
|
316
|
+
|
|
317
|
+
def open_touch_device(screen_width, screen_height):
|
|
318
|
+
"""Open the physical touchscreen device for event injection."""
|
|
319
|
+
dev_path = find_touchscreen()
|
|
320
|
+
if dev_path is None:
|
|
321
|
+
raise RuntimeError('No physical touchscreen device found')
|
|
322
|
+
|
|
323
|
+
fd = os.open(dev_path, os.O_WRONLY)
|
|
324
|
+
|
|
325
|
+
# Read the actual ABS ranges from the device
|
|
326
|
+
rd_fd = os.open(dev_path, os.O_RDONLY)
|
|
327
|
+
x_min, x_max = get_abs_range(rd_fd, ABS_MT_POSITION_X)
|
|
328
|
+
y_min, y_max = get_abs_range(rd_fd, ABS_MT_POSITION_Y)
|
|
329
|
+
os.close(rd_fd)
|
|
330
|
+
|
|
331
|
+
if x_max is None or y_max is None:
|
|
332
|
+
x_max = screen_width - 1
|
|
333
|
+
y_max = screen_height - 1
|
|
334
|
+
x_min = 0
|
|
335
|
+
y_min = 0
|
|
336
|
+
|
|
337
|
+
return fd, dev_path, x_min, x_max, y_min, y_max
|
|
338
|
+
|
|
339
|
+
def send_response(cmd_id, status, message=None, screen_width=None, screen_height=None):
|
|
124
340
|
resp = {'id': cmd_id, 'status': status}
|
|
125
341
|
if message is not None:
|
|
126
342
|
resp['message'] = message
|
|
343
|
+
if screen_width is not None:
|
|
344
|
+
resp['screen_width'] = screen_width
|
|
345
|
+
if screen_height is not None:
|
|
346
|
+
resp['screen_height'] = screen_height
|
|
127
347
|
sys.stdout.write(json.dumps(resp) + '\\n')
|
|
128
348
|
sys.stdout.flush()
|
|
129
349
|
|
|
@@ -134,9 +354,25 @@ def next_tracking_id():
|
|
|
134
354
|
tracking_id_counter = (tracking_id_counter + 1) % 65536
|
|
135
355
|
return tracking_id_counter
|
|
136
356
|
|
|
357
|
+
# Coordinate mapping globals
|
|
358
|
+
dev_x_min = 0
|
|
359
|
+
dev_x_max = 0
|
|
360
|
+
dev_y_min = 0
|
|
361
|
+
dev_y_max = 0
|
|
362
|
+
scr_w = 0
|
|
363
|
+
scr_h = 0
|
|
364
|
+
|
|
365
|
+
def map_x(x):
|
|
366
|
+
"""Map screen coordinate to device coordinate."""
|
|
367
|
+
return dev_x_min + int(x * (dev_x_max - dev_x_min) / (scr_w - 1))
|
|
368
|
+
|
|
369
|
+
def map_y(y):
|
|
370
|
+
"""Map screen coordinate to device coordinate."""
|
|
371
|
+
return dev_y_min + int(y * (dev_y_max - dev_y_min) / (scr_h - 1))
|
|
372
|
+
|
|
137
373
|
def handle_tap(fd, cmd):
|
|
138
|
-
x = int(cmd['x'])
|
|
139
|
-
y = int(cmd['y'])
|
|
374
|
+
x = map_x(int(cmd['x']))
|
|
375
|
+
y = map_y(int(cmd['y']))
|
|
140
376
|
duration_ms = cmd.get('duration_ms', 50)
|
|
141
377
|
tid = next_tracking_id()
|
|
142
378
|
touch_down(fd, 0, tid, x, y)
|
|
@@ -152,18 +388,18 @@ def handle_swipe(fd, cmd):
|
|
|
152
388
|
steps = cmd.get('steps', max(int(duration_ms / 15), 2))
|
|
153
389
|
tid = next_tracking_id()
|
|
154
390
|
|
|
155
|
-
touch_down(fd, 0, tid, x1, y1)
|
|
391
|
+
touch_down(fd, 0, tid, map_x(x1), map_y(y1))
|
|
156
392
|
for i in range(1, steps + 1):
|
|
157
393
|
t = i / steps
|
|
158
394
|
cx = int(x1 + (x2 - x1) * t)
|
|
159
395
|
cy = int(y1 + (y2 - y1) * t)
|
|
160
396
|
time.sleep(duration_ms / 1000.0 / steps)
|
|
161
|
-
touch_move(fd, 0, cx, cy)
|
|
397
|
+
touch_move(fd, 0, map_x(cx), map_y(cy))
|
|
162
398
|
touch_up(fd, 0)
|
|
163
399
|
|
|
164
400
|
def handle_long_press(fd, cmd):
|
|
165
|
-
x = int(cmd['x'])
|
|
166
|
-
y = int(cmd['y'])
|
|
401
|
+
x = map_x(int(cmd['x']))
|
|
402
|
+
y = map_y(int(cmd['y']))
|
|
167
403
|
duration_ms = cmd.get('duration_ms', 800)
|
|
168
404
|
tid = next_tracking_id()
|
|
169
405
|
touch_down(fd, 0, tid, x, y)
|
|
@@ -171,8 +407,8 @@ def handle_long_press(fd, cmd):
|
|
|
171
407
|
touch_up(fd, 0)
|
|
172
408
|
|
|
173
409
|
def handle_double_tap(fd, cmd):
|
|
174
|
-
x = int(cmd['x'])
|
|
175
|
-
y = int(cmd['y'])
|
|
410
|
+
x = map_x(int(cmd['x']))
|
|
411
|
+
y = map_y(int(cmd['y']))
|
|
176
412
|
tid = next_tracking_id()
|
|
177
413
|
touch_down(fd, 0, tid, x, y)
|
|
178
414
|
time.sleep(0.05)
|
|
@@ -184,7 +420,9 @@ def handle_double_tap(fd, cmd):
|
|
|
184
420
|
touch_up(fd, 0)
|
|
185
421
|
|
|
186
422
|
def main():
|
|
423
|
+
global dev_x_min, dev_x_max, dev_y_min, dev_y_max, scr_w, scr_h
|
|
187
424
|
fd = None
|
|
425
|
+
kbd_fd = None
|
|
188
426
|
try:
|
|
189
427
|
for line in sys.stdin:
|
|
190
428
|
line = line.strip()
|
|
@@ -201,10 +439,25 @@ def main():
|
|
|
201
439
|
|
|
202
440
|
try:
|
|
203
441
|
if cmd_type == 'init':
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
442
|
+
scr_w = cmd.get('screen_width', 0)
|
|
443
|
+
scr_h = cmd.get('screen_height', 0)
|
|
444
|
+
if scr_w <= 0 or scr_h <= 0:
|
|
445
|
+
det_w, det_h = detect_screen_resolution()
|
|
446
|
+
if det_w and det_h:
|
|
447
|
+
scr_w = det_w
|
|
448
|
+
scr_h = det_h
|
|
449
|
+
else:
|
|
450
|
+
scr_w = scr_w or 800
|
|
451
|
+
scr_h = scr_h or 480
|
|
452
|
+
fd, dev_path, dev_x_min, dev_x_max, dev_y_min, dev_y_max = open_touch_device(scr_w, scr_h)
|
|
453
|
+
# Best-effort keyboard setup — touch works even if uinput fails
|
|
454
|
+
try:
|
|
455
|
+
kbd_fd = setup_uinput_keyboard()
|
|
456
|
+
kbd_msg = ' (keyboard: ok)'
|
|
457
|
+
except Exception as ke:
|
|
458
|
+
kbd_fd = None
|
|
459
|
+
kbd_msg = ' (keyboard: unavailable - ' + str(ke) + ')'
|
|
460
|
+
send_response(cmd_id, 'ready', 'injecting into ' + dev_path + kbd_msg, scr_w, scr_h)
|
|
208
461
|
elif cmd_type == 'shutdown':
|
|
209
462
|
send_response(cmd_id, 'ok', 'shutting down')
|
|
210
463
|
break
|
|
@@ -222,16 +475,29 @@ def main():
|
|
|
222
475
|
elif cmd_type == 'double_tap':
|
|
223
476
|
handle_double_tap(fd, cmd)
|
|
224
477
|
send_response(cmd_id, 'ok')
|
|
478
|
+
elif cmd_type == 'key_press':
|
|
479
|
+
if kbd_fd is None:
|
|
480
|
+
send_response(cmd_id, 'error', 'keyboard not available: /dev/uinput not accessible')
|
|
481
|
+
else:
|
|
482
|
+
handle_key_press(kbd_fd, cmd)
|
|
483
|
+
send_response(cmd_id, 'ok')
|
|
484
|
+
elif cmd_type == 'key_type':
|
|
485
|
+
if kbd_fd is None:
|
|
486
|
+
send_response(cmd_id, 'error', 'keyboard not available: /dev/uinput not accessible')
|
|
487
|
+
else:
|
|
488
|
+
handle_key_type(kbd_fd, cmd)
|
|
489
|
+
send_response(cmd_id, 'ok')
|
|
225
490
|
else:
|
|
226
491
|
send_response(cmd_id, 'error', 'unknown command: ' + cmd_type)
|
|
227
492
|
except PermissionError:
|
|
228
|
-
send_response(cmd_id, 'error', 'Permission denied
|
|
493
|
+
send_response(cmd_id, 'error', 'Permission denied. Run with sudo or ensure user is in the input group: sudo usermod -aG input $USER')
|
|
229
494
|
except Exception as e:
|
|
230
495
|
send_response(cmd_id, 'error', str(e))
|
|
231
496
|
finally:
|
|
497
|
+
if kbd_fd is not None:
|
|
498
|
+
destroy_uinput_keyboard(kbd_fd)
|
|
232
499
|
if fd is not None:
|
|
233
500
|
try:
|
|
234
|
-
fcntl.ioctl(fd, UI_DEV_DESTROY)
|
|
235
501
|
os.close(fd)
|
|
236
502
|
except Exception:
|
|
237
503
|
pass
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"python-daemon.js","sourceRoot":"","sources":["../src/python-daemon.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG
|
|
1
|
+
{"version":3,"file":"python-daemon.js","sourceRoot":"","sources":["../src/python-daemon.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0fnC,CAAC"}
|
|
@@ -16,8 +16,7 @@ export class SshTouchSessionManager {
|
|
|
16
16
|
pending: null,
|
|
17
17
|
};
|
|
18
18
|
this.sessions.set(sessionId, session);
|
|
19
|
-
const
|
|
20
|
-
const pythonCmd = `python3 -u -c "import base64,sys;exec(base64.b64decode(sys.argv[1]))" "${scriptBase64}"`;
|
|
19
|
+
const pythonCmd = `python3 -u -c "import sys,base64;exec(base64.b64decode(input()))"`;
|
|
21
20
|
const remoteCmd = config.useSudo ? `sudo ${pythonCmd}` : pythonCmd;
|
|
22
21
|
const sshArgs = [
|
|
23
22
|
"-T",
|
|
@@ -35,6 +34,9 @@ export class SshTouchSessionManager {
|
|
|
35
34
|
stdio: ["pipe", "pipe", "pipe"],
|
|
36
35
|
});
|
|
37
36
|
session.process = proc;
|
|
37
|
+
// Send the daemon script via stdin to avoid ARG_MAX limits on embedded systems
|
|
38
|
+
const scriptBase64 = Buffer.from(PYTHON_DAEMON_SCRIPT).toString("base64");
|
|
39
|
+
proc.stdin.write(scriptBase64 + "\n");
|
|
38
40
|
const rl = createInterface({ input: proc.stdout });
|
|
39
41
|
rl.on("line", (line) => {
|
|
40
42
|
let resp;
|
|
@@ -83,6 +85,13 @@ export class SshTouchSessionManager {
|
|
|
83
85
|
this.cleanup(session);
|
|
84
86
|
throw new Error(`Daemon init failed: ${resp.message}`);
|
|
85
87
|
}
|
|
88
|
+
// Update config with daemon-detected screen resolution
|
|
89
|
+
if (resp.screen_width) {
|
|
90
|
+
session.config.screenWidth = resp.screen_width;
|
|
91
|
+
}
|
|
92
|
+
if (resp.screen_height) {
|
|
93
|
+
session.config.screenHeight = resp.screen_height;
|
|
94
|
+
}
|
|
86
95
|
session.active = true;
|
|
87
96
|
}
|
|
88
97
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssh-touch-session.js","sourceRoot":"","sources":["../src/ssh-touch-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,oBAAoB,GAAG,KAAK,CAAC;AACnC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAEjC,MAAM,OAAO,sBAAsB;IACzB,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEnD,KAAK,CAAC,OAAO,CAAC,MAAqB;QACjC,MAAM,SAAS,GAAG,UAAU,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAiB;YAC5B,EAAE,EAAE,SAAS;YACb,MAAM;YACN,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,IAAI;SACd,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAEtC,MAAM,
|
|
1
|
+
{"version":3,"file":"ssh-touch-session.js","sourceRoot":"","sources":["../src/ssh-touch-session.ts"],"names":[],"mappings":"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"}
|
package/build/types.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ export interface SessionConfig {
|
|
|
4
4
|
user: string;
|
|
5
5
|
port: number;
|
|
6
6
|
sshKey?: string;
|
|
7
|
-
screenWidth
|
|
8
|
-
screenHeight
|
|
7
|
+
screenWidth?: number;
|
|
8
|
+
screenHeight?: number;
|
|
9
9
|
useSudo: boolean;
|
|
10
10
|
}
|
|
11
11
|
export interface TouchSession {
|
|
@@ -18,7 +18,7 @@ export interface TouchSession {
|
|
|
18
18
|
reject: (reason: Error) => void;
|
|
19
19
|
} | null;
|
|
20
20
|
}
|
|
21
|
-
export type DaemonCommandType = "init" | "tap" | "swipe" | "long_press" | "double_tap" | "shutdown";
|
|
21
|
+
export type DaemonCommandType = "init" | "tap" | "swipe" | "long_press" | "double_tap" | "key_press" | "key_type" | "shutdown";
|
|
22
22
|
export interface DaemonCommand {
|
|
23
23
|
id: string;
|
|
24
24
|
type: DaemonCommandType;
|
|
@@ -30,9 +30,14 @@ export interface DaemonCommand {
|
|
|
30
30
|
steps?: number;
|
|
31
31
|
screen_width?: number;
|
|
32
32
|
screen_height?: number;
|
|
33
|
+
key?: string;
|
|
34
|
+
modifiers?: string[];
|
|
35
|
+
text?: string;
|
|
33
36
|
}
|
|
34
37
|
export interface DaemonResponse {
|
|
35
38
|
id: string;
|
|
36
39
|
status: "ok" | "error" | "ready";
|
|
37
40
|
message?: string;
|
|
41
|
+
screen_width?: number;
|
|
42
|
+
screen_height?: number;
|
|
38
43
|
}
|