aboutsummaryrefslogtreecommitdiff
path: root/src/syslua/lx/gip.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/syslua/lx/gip.lua')
-rw-r--r--src/syslua/lx/gip.lua177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/syslua/lx/gip.lua b/src/syslua/lx/gip.lua
new file mode 100644
index 0000000..8ae06bf
--- /dev/null
+++ b/src/syslua/lx/gip.lua
@@ -0,0 +1,177 @@
+local sys = require 'lx.sys'
+local protodef = require 'lx.protodef'
+local mainloop = require 'lx.mainloop'
+
+local gip = {}
+
+gip.proto = {
+ -- Definitions from proto/gip.h
+ GIPF_DOUBLE_BUFFER = 0x1,
+ GIPF_DAMAGE_NOTIF = 0x2,
+ GIPF_MODESET = 0x4,
+ GIPF_MOUSE_XY = 0x10,
+ GIPF_MOUSE_CURSOR = 0x20,
+
+ GIPC_RESET = 0,
+ GIPR_INITIATE = 1,
+ GIPR_OK = 2,
+ GIPR_FAILURE = 3,
+ GIPC_ENABLE_FEATURES = 4,
+ GIPC_DISABLE_FEATURES = 5,
+
+ GIPN_BUFFER_INFO = 10,
+ GIPC_QUERY_MODE = 11,
+ GIPR_MODE_INFO = 12,
+ GIPC_SET_MODE = 13,
+
+ GIPN_BUFFER_DAMAGE = 14,
+ GIPC_SWITCH_BUFFER = 15,
+
+ GIPN_KEY_DOWN = 20,
+ GIPN_KEY_UP = 21,
+
+ GIPN_MOUSE_DATA = 30,
+ GIPN_MOUSE_XY = 31,
+ GIPN_MOUSE_PRESSED = 32,
+ GIPN_MOUSE_RELEASED = 33,
+
+ gip_msg_header = {
+ fmt = 'LLL', -- code, req_id, arg
+ len = 12
+ },
+ -- buffer_info_msg = protodef.token .. protodef.fb_info
+ buffer_info_msg = {
+ len = protodef.token.len + protodef.fb_info.len
+ },
+ -- mode_info_msg = protodef.fb_info
+ mode_info_msg = {
+ len = protodef.fb_info.len
+ },
+ -- buffer_damage_msg = protodef.fb_region
+ buffer_damage_msg = {
+ len = protodef.fb_region.len
+ },
+}
+
+gip.new_handler = function(fd)
+ local h = {}
+ h.fd = fd
+
+ -- Replacable callbacks
+ function h:cb_reset(req_id, arg) end
+ function h:cb_initiate(req_id, arg) end
+ function h:cb_ok(req_id, arg) end
+ function h:cb_failure(req_id, arg) end
+ function h:cb_enable_features(req_id, arg) end
+ function h:cb_disable_features(req_id, arg) end
+ function h:cb_query_mode(req_id, arg) end
+ function h:cb_set_mode(req_id, arg) end
+ function h:cb_switch_buffer(req_id, arg) end
+ function h:cb_key_down(req_id, arg) end
+ function h:cb_key_up(req_id, arg) end
+ function h:cb_buffer_info(req_id, arg, token, fb_info) end
+ function h:cb_mode_info(req_id, arg, fb_info) end
+ function h:cb_buffer_damage(req_id, arg, region) end
+ function h:cb_unknown_message(code, req_id, arg) error("Unknown GIP message") end
+ function h:fd_error() error("GIP FD error") end
+
+ h.requests_in_progress = {}
+ h.msg_id = 0
+
+ h.mainloop_fd = mainloop.add_fd(h.fd, function() h:fd_error() end)
+
+ function h:send_msg(code, req_id, arg, data)
+ if req_id == nil then
+ req_id = h.msg_id
+ h.msg_id = h.msg_id + 1
+ end
+
+ local msgdata = string.pack(gip.proto.gip_msg_header.fmt, code, req_id, arg)
+ if code == gip.proto.GIPN_BUFFER_INFO then
+ msgdata = msgdata .. string.pack(protodef.token.fmt, data.tok)
+ .. string.pack(protodef.fb_info.fmt, data.geom.width, data.geom.height,
+ data.geom.pitch, data.geom.bpp, data.geom.memory_model)
+ elseif code == gip.proto.GIPN_MODE_INFO then
+ error("Not implemented") --TODO
+ elseif code == gip.proto.GIPN_BUFFER_DAMAGE then
+ error("Not implemented") --TODO
+ end
+
+ h.mainloop_fd:write(msgdata)
+ return req_id
+ end
+
+ function h:cmd(code, arg, data, cb)
+ local req_id = h:send_msg(code, nil, arg, data)
+ h.requests_in_progress[req_id] = cb
+ end
+
+ function h:got_reply(code, req_id, arg, data)
+ if h.requests_in_progress[req_id] ~= nil then
+ h.requests_in_progress[req_id](code, arg, data)
+ h.requests_in_progress[req_id] = nil
+ end
+ end
+
+ local function gip_handler(ev)
+ local code, req_id, arg = string.unpack(gip.proto.gip_msg_header.fmt, ev)
+
+ if code == gip.proto.GIPC_RESET then
+ h:cb_reset(req_id, arg)
+ elseif code == gip.proto.GIPR_INITIATE then
+ h:cb_initiate(req_id, arg)
+ h:got_reply(code, req_id, arg)
+ elseif code == gip.proto.GIPR_OK then
+ h:cb_ok(req_id, arg)
+ h:got_reply(code, req_id, arg)
+ elseif code == gip.proto.GIPR_FAILURE then
+ h:cb_failure(req_id, arg)
+ h:got_reply(code, req_id, arg)
+ elseif code == gip.proto.GIPC_ENABLE_FEATURE then
+ h:cb_enable_feature(req_id, arg)
+ elseif code == gip.proto.GIPC_DISABLE_FEATURE then
+ h:cb_disable_feature(req_id, arg)
+ elseif code == gip.proto.GIPC_QUERY_MODE then
+ h:cb_query_mode(req_id, arg)
+ elseif code == gip.proto.GIPC_SET_MODE then
+ h:cb_set_mode(req_id, arg)
+ elseif code == gip.proto.GIPC_SWITCH_BUFFER then
+ h:cb_switch_buffer(req_id, arg)
+ elseif code == gip.proto.GIPN_KEY_DOWN then
+ h:cb_key_down(req_id, arg)
+ elseif code == gip.proto.GIPN_KEY_UP then
+ h:cb_key_up(req_id, arg)
+ elseif code == gip.proto.GIPN_BUFFER_INFO then
+ h.mainloop_fd:expect(gip.proto.buffer_info_msg.len, function(msg)
+ local tok, p1 = string.unpack(protodef.token.fmt, msg)
+ local w, h, pitch, bpp, mm = string.unpack(protodef.fb_info.fmt, msg, p1)
+ h:cb_buffer_info(req_id, arg, token, {
+ width = w, height = h,
+ pitch = pitch, bpp = bpp, memory_model = mm })
+ end)
+ elseif code == gip.proto.GIPR_MODE_INFO then
+ h.mainloop_fd:expect(gip.proto.mode_info_msg.len, function(msg)
+ local w, h, pitch, bpp, mm = string.unpack(protodef.fb_info.fmt, msg)
+ local info = {
+ width = w, height = h,
+ pitch = pitch, bpp = bpp, memory_model = mm }
+ h:cb_mode_info(req_id, arg, info)
+ h:got_reply(code, req_id, arg, info)
+ end)
+ elseif code == gip.proto.GIPN_BUFFER_DAMAGE then
+ h.mainloop_fd:expect(gip.proto.buffer_damage_msg.len, function(msg)
+ local rx, ry, rw, rh = string.unpack(protodef.fb_region.fmt, msg)
+ h:cb_buffer_damage(req_id, arg, { x = rx, y = ry, w = rw, h = rh })
+ end)
+ else
+ h:cb_unknown_message(code, req_id, arg)
+ end
+
+ h.mainloop_fd:expect(gip.proto.gip_msg_header.len, gip_handler)
+ end
+ h.mainloop_fd:expect(gip.proto.gip_msg_header.len, gip_handler)
+
+ return h
+end
+
+return gip