diff --git a/README.md b/README.md index 75f2b40..e44b146 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,29 @@ chuniio driver for tasoller custom 2.0 firmware +Uses WinUSB driver instead of libusb + +Written in Zig (Sorry, I can't stand Windows-flavoured C++) + +Downloads avaliable in [releases](https://dev.s-ul.net/akiroz/chuniio-tasoller/-/releases) + ## USB Protocol Custom firmware USB device: 1CCF:2333 - Interface 1 - Endpoint 4 IN Interrupt (0x84) + - data len: 36 bytes + - data[0-2]: {0x68, 0x66, 0x84} (magic?) - data[3] bit 0-5: beam 1-6 (1 = blocked) bit 6-7: fn1 & fn2 (1 = pressed) - data[4-35]: touch sensor 1-32 pressure - Endpoint 3 OUT Bulk (0x03) + - data len: 240 bytes + - data[0-2]: {0x42, 0x4C, 0x00} (magic?) + - data[3-95]: Slider LED (GRB order, right->left) + - data[96-167]: Left LED (GRB order top->bottom) + - data[168-239]: Right LED (GRB order bottom->top) ### Build diff --git a/src/main.zig b/src/main.zig index 69205b4..03c6a79 100644 --- a/src/main.zig +++ b/src/main.zig @@ -51,6 +51,7 @@ var input_thread: ?std.Thread = null; var usb_op = std.Thread.Mutex{}; var usb_in = std.mem.zeroes([0x24]u8); +var usb_out = std.mem.zeroes([80*3]u8); var tasoller: ?*anyopaque = null; fn tasoller_init() !void { @@ -114,8 +115,12 @@ fn tasoller_init() !void { std.log.err("[chuniio] WinUsb_Initialize: {any}", .{GetLastError()}); return error.AccessError; } + + // Init magic bytes + std.mem.copy(u8, usb_out[0..3], &[_]u8{0x42, 0x4C, 0x00}); } +// Poll input regardless of slider start/stop fn input_thread_proc() void { while(true) { usb_op.lock(); @@ -130,6 +135,8 @@ fn input_thread_proc() void { fn slider_thread_proc(callback: chuni_io_slider_callback_t) void { var pressure = std.mem.zeroes([32]u8); while(slider_active) { + // Tasoller order: top->bottom, left->right + // Chunithm order: top->bottom, right->left for(usb_in[4..]) |val, i| pressure[if(i%2 == 0) 30-i else 32-i] = val; callback.?(&pressure); std.time.sleep(1_000_000); // 1ms @@ -204,14 +211,22 @@ export fn chuni_io_slider_stop() void { export fn chuni_io_slider_set_leds(rgb: ?[*]u8) void { if(rgb == null) return; + + var n: u32 = 0; + const out = usb_out[3..96]; + while(n < 31) : (n += 1) { + out[n*3+0] = rgb.?[n*3+2]; + out[n*3+1] = rgb.?[n*3+1]; + out[n*3+2] = rgb.?[n*3+0]; + } + usb_op.lock(); defer usb_op.unlock(); - _ = rgb; + if(WinUsb_WritePipe(tasoller, 0x03, @ptrCast(*u8, &usb_out), usb_out.len, &n, null) == 0) { + std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()}); + } } pub fn main() !void { try tasoller_init(); - // input_thread_proc(); - _ = try std.Thread.spawn(.{}, input_thread_proc, .{}); - while(true) {} } \ No newline at end of file