M .gitignore => .gitignore +2 -0
@@ 1,3 1,5 @@
/evdev-dump-events
/uinput-pointer
/gy-801-dump
+/pointerc
+/pointerd
M Makefile => Makefile +4 -2
@@ 1,5 1,7 @@
-evdev-dump-events uinput-pointer:
+evdev-dump-events uinput-pointer pointerc:
hare build -levdev -o $@ tools/$@/
gy-801-dump:
hare build -o $@ tools/$@/
-.PHONY: evdev-dump-events uinput-pointer gy-801-dump
+pointerd:
+ hare build -levdev -o $@ cmd/$@/
+.PHONY: evdev-dump-events uinput-pointer gy-801-dump pointerd pointerc
A cmd/pointerd/main.ha => cmd/pointerd/main.ha +58 -0
@@ 0,0 1,58 @@
+use evdev;
+use evdev::uinput;
+use fmt;
+use io;
+use net;
+use net::ip;
+use net::udp;
+use proto::control;
+use rt;
+use time;
+
+export fn main() void = {
+ const evdev = evdev::new();
+ defer evdev::destroy(evdev);
+ evdev::set_name(evdev, "motion-control pointer");
+ evdev::enable_event_type(evdev, evdev::EV_REL)!;
+ evdev::enable_event_code(evdev, evdev::EV_REL, evdev::REL_X, null)!;
+ evdev::enable_event_code(evdev, evdev::EV_REL, evdev::REL_Y, null)!;
+ evdev::enable_event_type(evdev, evdev::EV_KEY)!;
+ evdev::enable_event_code(evdev, evdev::EV_KEY, evdev::BTN_LEFT, null)!;
+ evdev::enable_event_code(evdev, evdev::EV_KEY, evdev::BTN_MIDDLE, null)!;
+ evdev::enable_event_code(evdev, evdev::EV_KEY, evdev::BTN_RIGHT, null)!;
+
+ const uinput = match (uinput::create_from_device(evdev, uinput::OPEN_MANAGED)) {
+ case let uinput: uinput::uinput =>
+ yield uinput;
+ case let err: rt::errno =>
+ fmt::fatalf("Failed to create uinput dev: {}", rt::strerror(err));
+ };
+ defer uinput::destroy(uinput);
+
+ const addr = ip::ANY_V6, port = control::DEFAULT_PORT;
+ const sock = match(udp::listen(addr, port)) {
+ case let sock: io::file =>
+ yield sock;
+ case let err: net::error =>
+ fmt::fatalf("Failed to listen on {}:{}: {}",
+ ip::string(addr), port, net::strerror(err));
+ };
+ defer io::close(sock)!;
+
+ let buf = control::request {...};
+ for (true) {
+ const sz = udp::recvfrom(sock, buf.bytes, null, null)!;
+ if (sz != size(control::request)) {
+ fmt::errorln("Unexpected read size")!;
+ continue;
+ };
+ switch (buf.code) {
+ case control::code::RELATIVE_MOVEMENT =>
+ uinput::write_event(uinput, evdev::EV_REL, evdev::REL_X, buf.x)!;
+ uinput::write_event(uinput, evdev::EV_REL, evdev::REL_Y, buf.y)!;
+ uinput::write_event(uinput, evdev::EV_SYN, evdev::SYN_REPORT, 0)!;
+ case =>
+ fmt::errorfln("Unrecognized control code: {}", buf.code)!;
+ };
+ };
+};
A proto/control/types.ha => proto/control/types.ha +18 -0
@@ 0,0 1,18 @@
+export def DEFAULT_PORT: u16 = 0x519;
+
+export type code = enum u8 {
+ RELATIVE_MOVEMENT = 0,
+};
+
+export type request = union {
+ struct {
+ code: u8,
+ union {
+ struct {
+ x: i8,
+ y: i8,
+ },
+ },
+ },
+ bytes: [3]u8,
+};
A tools/pointerc/main.ha => tools/pointerc/main.ha +60 -0
@@ 0,0 1,60 @@
+use fmt;
+use io;
+use net;
+use net::ip;
+use net::udp;
+use os;
+use proto::control;
+use strconv;
+
+export fn main() int = {
+ if (len(os::args) != 5) {
+ fmt::fatalf("Usage: {} addr port x y", os::args[0]);
+ };
+ const addr = match (ip::parse(os::args[1])) {
+ case let addr: ip::addr =>
+ yield addr;
+ case ip::invalid =>
+ fmt::fatalf("Invalid address {}", os::args[1]);
+ };
+ const port = match (strconv::stou16(os::args[2])) {
+ case let port: u16 =>
+ yield port;
+ case =>
+ fmt::fatalf("Invalid port {}", os::args[2]);
+ };
+ const x = match (strconv::stoi8(os::args[3])) {
+ case let n: i8 =>
+ yield n;
+ case =>
+ fmt::fatalf("Invalid x {}", os::args[3]);
+ };
+ const y = match (strconv::stoi8(os::args[4])) {
+ case let n: i8 =>
+ yield n;
+ case =>
+ fmt::fatalf("Invalid y {}", os::args[4]);
+ };
+
+ const buf = control::request {
+ code = control::code::RELATIVE_MOVEMENT,
+ x = x,
+ y = y,
+ };
+
+ const sock = match (udp::connect(addr, port)) {
+ case let s: io::file =>
+ yield s;
+ case let err: net::error =>
+ fmt::fatalf("Cannot connect() {}:{}: {}", ip::string(addr), port, net::strerror(err));
+ };
+ defer io::close(sock)!;
+
+ match (udp::send(sock, buf.bytes)) {
+ case let err: net::error =>
+ fmt::fatalf("Cannot send(): {}", net::strerror(err));
+ case size =>
+ yield;
+ };
+ return 0;
+};