#!/opt/lnxall_app/bin/lua

-- Created by jiaqiang.ye@lnxall.com
-- Simple Touchscreen press emulator
-- 2025/11/25

local struct = require 'struct'
local invoker = require 'invoker'

local gfmt = string.format
local g_fd = nil
local g_dev = nil

local EV_ABS               = 3
local ABS_MT_TRACKING_ID   = 57
local ABS_MT_POSITION_X    = 53
local ABS_MT_POSITION_Y    = 54
local EV_KEY               = 1
local BTN_TOUCH            = 330
local ABS_X                = 0
local ABS_Y                = 1
local EV_MSC               = 4
local MSC_TIMESTAMP        = 5
local UP                   = 0
local DOWN                 = 1
local EV_SYN               = 0
local SYN_REPORT           = 0
local MSC_SCAN             = 4
local KEY_LEFTALT          = 0x38
local KEY_F9               = 0x43

local g_key0 = KEY_LEFTALT
local g_key1 = KEY_F9

-- /dev/input/event3: 0004 0004 000700e2
-- /dev/input/event3: 0001 0038 00000001
-- /dev/input/event3: 0000 0000 00000000
-- /dev/input/event3: 0004 0004 00070042
-- /dev/input/event3: 0001 0043 00000001
-- /dev/input/event3: 0000 0000 00000000
-- /dev/input/event3: 0004 0004 000700e2
-- /dev/input/event3: 0001 0038 00000000
-- /dev/input/event3: 0000 0000 00000000
-- /dev/input/event3: 0004 0004 00070042
-- /dev/input/event3: 0001 0043 00000000
-- /dev/input/event3: 0000 0000 00000000
-- /dev/input/event3: EV_MSC       MSC_SCAN             000700e2
-- /dev/input/event3: EV_KEY       KEY_LEFTALT          DOWN
-- /dev/input/event3: EV_SYN       SYN_REPORT           00000000
-- /dev/input/event3: EV_MSC       MSC_SCAN             00070042
-- /dev/input/event3: EV_KEY       KEY_F9               DOWN
-- /dev/input/event3: EV_SYN       SYN_REPORT           00000000
-- /dev/input/event3: EV_MSC       MSC_SCAN             00070042
-- /dev/input/event3: EV_KEY       KEY_F9               UP
-- /dev/input/event3: EV_SYN       SYN_REPORT           00000000
-- /dev/input/event3: EV_MSC       MSC_SCAN             000700e2
-- /dev/input/event3: EV_KEY       KEY_LEFTALT          UP
-- /dev/input/event3: EV_SYN       SYN_REPORT           00000000
--
-- /dev/input/event4: 0004 0004 000700e1
-- /dev/input/event4: 0001 002a 00000001
-- /dev/input/event4: 0000 0000 00000000
-- /dev/input/event4: 0004 0004 00070046
-- /dev/input/event4: 0001 0063 00000001
-- /dev/input/event4: 0000 0000 00000000
-- /dev/input/event4: 0004 0004 00070046
-- /dev/input/event4: 0001 0063 00000000
-- /dev/input/event4: 0000 0000 00000000
-- /dev/input/event4: 0004 0004 000700e1
-- /dev/input/event4: 0001 002a 00000000
-- /dev/input/event4: 0000 0000 00000000
-- /dev/input/event4: EV_MSC       MSC_SCAN             000700e1
-- /dev/input/event4: EV_KEY       KEY_LEFTSHIFT        DOWN
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000000
-- /dev/input/event4: EV_KEY       KEY_LEFTSHIFT        REPEAT
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000001
-- /dev/input/event4: EV_KEY       KEY_LEFTSHIFT        REPEAT
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000001
-- /dev/input/event4: EV_KEY       KEY_LEFTSHIFT        REPEAT
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000001
-- /dev/input/event4: EV_KEY       KEY_LEFTSHIFT        REPEAT
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000001
-- /dev/input/event4: EV_MSC       MSC_SCAN             00070046
-- /dev/input/event4: EV_KEY       KEY_SYSRQ            DOWN
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000000
-- /dev/input/event4: EV_MSC       MSC_SCAN             00070046
-- /dev/input/event4: EV_KEY       KEY_SYSRQ            UP
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000000
-- /dev/input/event4: EV_MSC       MSC_SCAN             000700e1
-- /dev/input/event4: EV_KEY       KEY_LEFTSHIFT        UP
-- /dev/input/event4: EV_SYN       SYN_REPORT           00000000

local function press_init()
	local dev = arg[1]
	if invoker.statfile(dev) ~= "character" then
		local _, output = invoker.invoke(invoker.OUTPUT,
			"/bin/bash", "-c", "libinput list-devices 2>/dev/null | grep -A 1 -e 'Keyboard emulator'")
		if type(output) ~= "string" then output = "" end
		dev = string.match(output, "Kernel:%s+([^%s]+)")
		if invoker.statfile(dev) ~= "character" then
			io.stderr:write("Error, input device not specified.\n")
			io.stderr:write("Execute command:\n\tinput-emulator start kbd\n")
			io.stderr:write("For Shift-PSC: altf9 path/to/event  0x2a 0x63\n")
			io.stderr:flush()
			return false
		end
	end
	g_dev = dev

	local keyv = arg[2]
	if keyv and #keyv > 0 then keyv = tonumber(keyv) end
	if type(keyv) == "number" and keyv >= 0 then g_key0 = keyv end

	keyv = arg[3]
	if keyv and #keyv > 0 then keyv = tonumber(keyv) end
	if type(keyv) == "number" and keyv >= 0 then g_key1 = keyv end

	io.stdout:write(gfmt("Press combination key: 0x%x + 0x%x -> %s\n",
		g_key0, g_key1, dev))
	io.stdout:flush()
	return true
end

local function open_device()
	local fd = invoker.open(g_dev, 524290)
	if not fd then
		io.stderr:write(gfmt("Eror, failed to open device: %s\n", g_dev))
		io.stderr:flush()
		return false
	end
	g_fd = fd
	return true
end

local function write_event(evkey, evcode, value)
	local ups, upm = invoker.uptime()
	local wbuf = struct.pack("<I8I8HHi4", ups, upm * 1000, evkey, evcode, value)
	if invoker.writefd(g_fd, wbuf) ~= #wbuf then
		io.stderr:write("Error, write Event has failed.\n")
		io.stderr:flush()
		return false
	end
	return true
end

local function touchscreen(key0, key1)
	write_event(EV_MSC, MSC_SCAN,       0x700e2)
	write_event(EV_KEY, key0,           DOWN)
	write_event(EV_SYN, SYN_REPORT,     0x0)
	invoker.msleep(50)

	write_event(EV_MSC, MSC_SCAN,       0x70042)
	write_event(EV_KEY, key1,           DOWN)
	write_event(EV_SYN, SYN_REPORT,     0x0)
	invoker.msleep(100)

	write_event(EV_MSC, MSC_SCAN,       0x70042)
	write_event(EV_KEY, key1,           UP)
	write_event(EV_SYN, SYN_REPORT,     0x0)
	invoker.msleep(50)
	write_event(EV_MSC, MSC_SCAN,       0x700e2)
	write_event(EV_KEY, key0,           UP)
	write_event(EV_SYN, SYN_REPORT,     0x0)
	return true
end

if not press_init() then os.exit(1) end
if not open_device() then os.exit(2) end
touchscreen(g_key0, g_key1)
os.exit(0)
