Added support for zig v0.11 #1
@ -64,6 +64,6 @@ Custom firmware USB device: 1CCF:2333
|
|||||||
```
|
```
|
||||||
$ git clone ...
|
$ git clone ...
|
||||||
$ git submodule update --init
|
$ git submodule update --init
|
||||||
$ zig build -Drelease-safe=true
|
$ zig build -Doptimize=ReleaseSafe
|
||||||
$ ls zig-out/lib/chuniio_tasoller.dll
|
$ ls zig-out/lib/chuniio_tasoller.dll
|
||||||
```
|
```
|
||||||
|
36
build.zig
36
build.zig
@ -1,20 +1,24 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const CrossTarget = std.zig.CrossTarget;
|
const CrossTarget = std.zig.CrossTarget;
|
||||||
|
const Build = std.build.Builder;
|
||||||
|
const Step = Build.Step;
|
||||||
|
|
||||||
pub fn build(b: *std.build.Builder) void {
|
pub fn build(b: *Build) void {
|
||||||
|
const mode = b.standardOptimizeOption(.{});
|
||||||
const lib86 = b.addSharedLibrary("chuniio_tasoller", "src/main.zig", .unversioned);
|
|
||||||
lib86.setBuildMode(b.standardReleaseOptions());
|
|
||||||
lib86.setTarget(CrossTarget{ .os_tag = .windows, .cpu_arch = .i386, .abi = .msvc });
|
|
||||||
lib86.install();
|
|
||||||
|
|
||||||
const lib64 = b.addSharedLibrary("chuniio_tasoller_x64", "src/main.zig", .unversioned);
|
const lib86 = b.addSharedLibrary(Build.SharedLibraryOptions{
|
||||||
lib64.setBuildMode(b.standardReleaseOptions());
|
.name = "chuniio_tasoller",
|
||||||
lib64.setTarget(CrossTarget{ .os_tag = .windows, .cpu_arch = .x86_64, .abi = .msvc });
|
.root_source_file = .{.path = "src/main.zig"},
|
||||||
lib64.install();
|
.target = CrossTarget{ .os_tag = .windows, .cpu_arch = .x86, .abi = .msvc },
|
||||||
|
.optimize = mode,
|
||||||
// const exe = b.addExecutable("tasoller_test", "src/main.zig");
|
});
|
||||||
// lib.setBuildMode(b.standardReleaseOptions());
|
b.installArtifact(lib86);
|
||||||
// exe.setTarget(target);
|
|
||||||
// exe.install();
|
const lib64 = b.addSharedLibrary(Build.SharedLibraryOptions{
|
||||||
}
|
.name = "chuniio_tasoller_x64",
|
||||||
|
.root_source_file = .{.path = "src/main.zig"},
|
||||||
|
.target = CrossTarget{ .os_tag = .windows, .cpu_arch = .x86_64, .abi = .msvc },
|
||||||
|
.optimize = mode,
|
||||||
|
});
|
||||||
|
b.installArtifact(lib64);
|
||||||
|
}
|
@ -1,4 +1,11 @@
|
|||||||
[chuniio]
|
[chuniio]
|
||||||
|
;; For Chunithm
|
||||||
|
;path=chuniio_tasoller.dll
|
||||||
|
;; For Chunithm NEW or newer
|
||||||
|
path32=chuniio_tasoller.dll
|
||||||
|
path64=chuniio_tasoller_x64.dll
|
||||||
|
|
||||||
|
;; Uncomment for Chunithm NEW or newer
|
||||||
chusan=1
|
chusan=1
|
||||||
|
|
||||||
[io3]
|
[io3]
|
||||||
|
171
src/main.zig
171
src/main.zig
@ -58,7 +58,7 @@ var input_thread: ?std.Thread = null;
|
|||||||
|
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
var usb_out_op = std.Thread.Mutex{};
|
var usb_out_op = std.Thread.Mutex{};
|
||||||
var usb_out = std.mem.zeroes([80*3]u8);
|
var usb_out = std.mem.zeroes([80 * 3]u8);
|
||||||
var usb_in: ?[]u8 = null;
|
var usb_in: ?[]u8 = null;
|
||||||
var tasoller: ?*anyopaque = null;
|
var tasoller: ?*anyopaque = null;
|
||||||
|
|
||||||
@ -67,11 +67,11 @@ pub fn main() !void {
|
|||||||
usb_in = try gpa.allocator().alloc(u8, 0x24);
|
usb_in = try gpa.allocator().alloc(u8, 0x24);
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
try tasoller_init();
|
try tasoller_init();
|
||||||
while(true) {
|
while (true) {
|
||||||
if(WinUsb_WritePipe(tasoller, 0x03, @ptrCast(*u8, &usb_out), usb_out.len, &i, null) == 0) {
|
if (WinUsb_WritePipe(tasoller, 0x03, @as(*u8, @ptrCast(&usb_out)), usb_out.len, &i, null) == 0) {
|
||||||
std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()});
|
std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()});
|
||||||
}
|
}
|
||||||
if(WinUsb_ReadPipe(tasoller, 0x84, usb_in.ptr, usb_in.len, &i, null) == 0) {
|
if (WinUsb_ReadPipe(tasoller, 0x84, usb_in.ptr, usb_in.len, &i, null) == 0) {
|
||||||
std.log.warn("[chuniio] WinUsb_ReadPipe: {any}", .{GetLastError()});
|
std.log.warn("[chuniio] WinUsb_ReadPipe: {any}", .{GetLastError()});
|
||||||
}
|
}
|
||||||
std.time.sleep(100_000_000);
|
std.time.sleep(100_000_000);
|
||||||
@ -81,8 +81,7 @@ pub fn main() !void {
|
|||||||
// MAIN DRIVER ======================================================================================================
|
// MAIN DRIVER ======================================================================================================
|
||||||
|
|
||||||
fn tasoller_init() !void {
|
fn tasoller_init() !void {
|
||||||
|
if (cfg.?.chusan == 1) {
|
||||||
if(cfg.?.chusan == 1) {
|
|
||||||
std.log.info("[chuniio] Initializing mode: chusan", .{});
|
std.log.info("[chuniio] Initializing mode: chusan", .{});
|
||||||
const szName = W("Local\\ChuniioTasoller");
|
const szName = W("Local\\ChuniioTasoller");
|
||||||
const hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, null, PAGE_READWRITE, 0, 0x24, szName) orelse {
|
const hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, null, PAGE_READWRITE, 0, 0x24, szName) orelse {
|
||||||
@ -93,8 +92,8 @@ fn tasoller_init() !void {
|
|||||||
std.log.err("[chuniio] MapViewOfFile: {any}", .{GetLastError()});
|
std.log.err("[chuniio] MapViewOfFile: {any}", .{GetLastError()});
|
||||||
return error.AccessError;
|
return error.AccessError;
|
||||||
};
|
};
|
||||||
usb_in = @ptrCast([*]u8, pBuf)[0..0x24];
|
usb_in = @as([*]u8, @ptrCast(pBuf))[0..0x24];
|
||||||
if(builtin.cpu.arch == .x86_64) return;
|
if (builtin.cpu.arch == .x86_64) return;
|
||||||
} else {
|
} else {
|
||||||
std.log.info("[chuniio] Initializing mode: chuni", .{});
|
std.log.info("[chuniio] Initializing mode: chuni", .{});
|
||||||
usb_in = gpa.allocator().alloc(u8, 0x24) catch |err| {
|
usb_in = gpa.allocator().alloc(u8, 0x24) catch |err| {
|
||||||
@ -104,66 +103,58 @@ fn tasoller_init() !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hDevInfo = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_USB_DEVICE, null, null, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
const hDevInfo = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_USB_DEVICE, null, null, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||||
if(hDevInfo == INVALID_HANDLE_VALUE) {
|
if (hDevInfo == INVALID_HANDLE_VALUE) {
|
||||||
std.log.err("[chuniio] SetupDiGetClassDevs: {any}", .{GetLastError()});
|
std.log.err("[chuniio] SetupDiGetClassDevs: {any}", .{GetLastError()});
|
||||||
return error.AccessError;
|
return error.AccessError;
|
||||||
}
|
}
|
||||||
defer _ = SetupDiDestroyDeviceInfoList(hDevInfo);
|
defer _ = SetupDiDestroyDeviceInfoList(hDevInfo);
|
||||||
|
|
||||||
var ifIdx: DWORD = 0;
|
var ifIdx: DWORD = 0;
|
||||||
var devIf = std.mem.zeroes(SP_DEVICE_INTERFACE_DATA);
|
var devIf = std.mem.zeroes(SP_DEVICE_INTERFACE_DATA);
|
||||||
devIf.cbSize = @sizeOf(SP_DEVICE_INTERFACE_DATA);
|
devIf.cbSize = @sizeOf(SP_DEVICE_INTERFACE_DATA);
|
||||||
var devicePath: ?[*:0]const u8 = null;
|
var devicePath: ?[*:0]const u8 = null;
|
||||||
while(SetupDiEnumDeviceInterfaces(hDevInfo, null, &GUID_DEVINTERFACE_USB_DEVICE, ifIdx, &devIf) != 0) : (ifIdx += 1) {
|
while (SetupDiEnumDeviceInterfaces(hDevInfo, null, &GUID_DEVINTERFACE_USB_DEVICE, ifIdx, &devIf) != 0) : (ifIdx += 1) {
|
||||||
var requiredSize: u32 = 0;
|
var requiredSize: u32 = 0;
|
||||||
var detailBuf align(4) = std.mem.zeroes([512]u8);
|
var detailBuf align(4) = std.mem.zeroes([512]u8);
|
||||||
var devIfDetail = @ptrCast(*SP_DEVICE_INTERFACE_DETAIL_DATA_A, &detailBuf);
|
var devIfDetail = @as(*SP_DEVICE_INTERFACE_DETAIL_DATA_A, @ptrCast(&detailBuf));
|
||||||
devIfDetail.cbSize = @sizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
devIfDetail.cbSize = @sizeOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
|
||||||
if(SetupDiGetDeviceInterfaceDetailA(hDevInfo, &devIf, devIfDetail, 263, &requiredSize, null) == 0) {
|
if (SetupDiGetDeviceInterfaceDetailA(hDevInfo, &devIf, devIfDetail, 263, &requiredSize, null) == 0) {
|
||||||
std.log.err("[chuniio] SetupDiGetDeviceInterfaceDetailA: {any}", .{GetLastError()});
|
std.log.err("[chuniio] SetupDiGetDeviceInterfaceDetailA: {any}", .{GetLastError()});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(requiredSize >= 263) {
|
if (requiredSize >= 263) {
|
||||||
std.log.err("[chuniio] SetupDiGetDeviceInterfaceDetailA: Path too long", .{});
|
std.log.err("[chuniio] SetupDiGetDeviceInterfaceDetailA: Path too long", .{});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const path = detailBuf[@offsetOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A, "DevicePath") .. requiredSize :0];
|
const path = detailBuf[@offsetOf(SP_DEVICE_INTERFACE_DETAIL_DATA_A, "DevicePath")..requiredSize :0];
|
||||||
// std.log.info("[chuniio] devPath: {s}", .{path});
|
// std.log.info("[chuniio] devPath: {s}", .{path});
|
||||||
if(std.mem.indexOf(u8, path, "vid_1ccf") == null) continue;
|
if (std.mem.indexOf(u8, path, "vid_1ccf") == null) continue;
|
||||||
if(std.mem.indexOf(u8, path, "pid_2333") == null) continue;
|
if (std.mem.indexOf(u8, path, "pid_2333") == null) continue;
|
||||||
devicePath = path;
|
devicePath = path;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(devicePath == null) {
|
if (devicePath == null) {
|
||||||
std.log.err("[chuniio] Tasoller not found", .{});
|
std.log.err("[chuniio] Tasoller not found", .{});
|
||||||
return error.AccessError;
|
return error.AccessError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hDeviceHandle = CreateFileA(
|
const hDeviceHandle = CreateFileA(devicePath, @as(FILE_ACCESS_FLAGS, @enumFromInt(GENERIC_READ | GENERIC_WRITE)), @as(FILE_SHARE_MODE, @enumFromInt(@intFromEnum(FILE_SHARE_READ) | @intFromEnum(FILE_SHARE_WRITE))), null, // Security Attributes
|
||||||
devicePath,
|
OPEN_EXISTING, .FILE_FLAG_OVERLAPPED, null // Template File
|
||||||
@intToEnum(FILE_ACCESS_FLAGS, GENERIC_READ | GENERIC_WRITE),
|
);
|
||||||
@intToEnum(FILE_SHARE_MODE, @enumToInt(FILE_SHARE_READ) | @enumToInt(FILE_SHARE_WRITE)),
|
|
||||||
null, // Security Attributes
|
if (hDeviceHandle == INVALID_HANDLE_VALUE) {
|
||||||
OPEN_EXISTING,
|
std.log.err("[chuniio] CreateFileA {any}: {any}\n", .{ devicePath, GetLastError() });
|
||||||
.FILE_FLAG_OVERLAPPED,
|
|
||||||
null // Template File
|
|
||||||
) orelse {
|
|
||||||
std.log.err("[chuniio] CreateFileA {s}: {any}", .{devicePath, GetLastError()});
|
|
||||||
return error.AccessError;
|
|
||||||
};
|
|
||||||
if(hDeviceHandle == INVALID_HANDLE_VALUE) {
|
|
||||||
std.log.err("[chuniio] CreateFileA {s}: {any}", .{devicePath, GetLastError()});
|
|
||||||
return error.AccessError;
|
return error.AccessError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(WinUsb_Initialize(hDeviceHandle, &tasoller) == 0) {
|
if (WinUsb_Initialize(hDeviceHandle, &tasoller) == 0) {
|
||||||
std.log.err("[chuniio] WinUsb_Initialize: {any}", .{GetLastError()});
|
std.log.err("[chuniio] WinUsb_Initialize: {any}\n", .{ GetLastError() });
|
||||||
return error.AccessError;
|
return error.AccessError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init magic bytes
|
// Init magic bytes
|
||||||
std.mem.copy(u8, usb_out[0..3], &[_]u8{0x42, 0x4C, 0x00});
|
std.mem.copy(u8, usb_out[0..3], &[_]u8{ 0x42, 0x4C, 0x00 });
|
||||||
|
|
||||||
input_thread = std.Thread.spawn(.{}, input_thread_proc, .{}) catch |err| {
|
input_thread = std.Thread.spawn(.{}, input_thread_proc, .{}) catch |err| {
|
||||||
std.log.err("[chuniio] Spawn input thread: {any}", .{err});
|
std.log.err("[chuniio] Spawn input thread: {any}", .{err});
|
||||||
return error.AccessError;
|
return error.AccessError;
|
||||||
@ -173,23 +164,23 @@ fn tasoller_init() !void {
|
|||||||
// Poll input regardless of slider start/stop
|
// Poll input regardless of slider start/stop
|
||||||
fn input_thread_proc() void {
|
fn input_thread_proc() void {
|
||||||
std.log.info("[chuniio] Input thread started", .{});
|
std.log.info("[chuniio] Input thread started", .{});
|
||||||
while(true) {
|
while (true) {
|
||||||
var len: u32 = 0;
|
var len: u32 = 0;
|
||||||
if(WinUsb_ReadPipe(tasoller, 0x84, @ptrCast(*u8, usb_in.?.ptr), @intCast(u32, usb_in.?.len), &len, null) == 0) {
|
if (WinUsb_ReadPipe(tasoller, 0x84, @as(*u8, @ptrCast(usb_in.?.ptr)), @as(u32, @intCast(usb_in.?.len)), &len, null) == 0) {
|
||||||
std.log.warn("[chuniio] WinUsb_ReadPipe: {any}", .{GetLastError()});
|
std.log.warn("[chuniio] WinUsb_ReadPipe: {any}", .{GetLastError()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const chuni_io_slider_callback_t = ?fn ([*c]const u8) callconv(.C) void;
|
const chuni_io_slider_callback_t = ?*fn ([*c]const u8) callconv(.C) void;
|
||||||
|
|
||||||
fn slider_thread_proc(callback: chuni_io_slider_callback_t) void {
|
fn slider_thread_proc(callback: chuni_io_slider_callback_t) void {
|
||||||
var pressure = std.mem.zeroes([32]u8);
|
var pressure = std.mem.zeroes([32]u8);
|
||||||
while(slider_active) {
|
while (slider_active) {
|
||||||
for(usb_in.?[4..]) |byte, i| {
|
for (usb_in.?[4..], 0..) |byte, i| {
|
||||||
// Tasoller order: top->bottom, left->right
|
// Tasoller order: top->bottom, left->right
|
||||||
// Chunithm order: top->bottom, right->left
|
// Chunithm order: top->bottom, right->left
|
||||||
pressure[if(i%2 == 0) 30-i else 32-i] = byte;
|
pressure[if (i % 2 == 0) 30 - i else 32 - i] = byte;
|
||||||
}
|
}
|
||||||
callback.?(&pressure);
|
callback.?(&pressure);
|
||||||
std.time.sleep(1_000_000); // 1ms, limit reporting to 1kHz max
|
std.time.sleep(1_000_000); // 1ms, limit reporting to 1kHz max
|
||||||
@ -205,59 +196,59 @@ export fn chuni_io_get_api_version() c_ushort {
|
|||||||
pub export fn DllMain(hDllHandle: HANDLE, dwReason: DWORD, lpreserved: LPVOID) BOOL {
|
pub export fn DllMain(hDllHandle: HANDLE, dwReason: DWORD, lpreserved: LPVOID) BOOL {
|
||||||
_ = hDllHandle;
|
_ = hDllHandle;
|
||||||
_ = lpreserved;
|
_ = lpreserved;
|
||||||
if(dwReason != DLL_PROCESS_ATTACH) return win32.zig.TRUE;
|
if (dwReason != DLL_PROCESS_ATTACH) return win32.zig.TRUE;
|
||||||
|
|
||||||
const cfg_file = ".\\segatools.ini";
|
const cfg_file = ".\\segatools.ini";
|
||||||
std.log.info("[chuniio] Loading config from {s}", .{cfg_file});
|
std.log.info("[chuniio] Loading config from {s}", .{cfg_file});
|
||||||
cfg = .{
|
cfg = .{
|
||||||
.test_key = @intCast(i32, GetPrivateProfileIntA("io3", "test", 0x31, cfg_file)),
|
.test_key = @as(i32, @intCast(GetPrivateProfileIntA("io3", "test", 0x31, cfg_file))),
|
||||||
.serv_key = @intCast(i32, GetPrivateProfileIntA("io3", "service", 0x32, cfg_file)),
|
.serv_key = @as(i32, @intCast(GetPrivateProfileIntA("io3", "service", 0x32, cfg_file))),
|
||||||
.coin_key = @intCast(i32, GetPrivateProfileIntA("io3", "coin", 0x33, cfg_file)),
|
.coin_key = @as(i32, @intCast(GetPrivateProfileIntA("io3", "coin", 0x33, cfg_file))),
|
||||||
.chusan = @intCast(i32, GetPrivateProfileIntA("chuniio", "chusan", 0, cfg_file)),
|
.chusan = @as(i32, @intCast(GetPrivateProfileIntA("chuniio", "chusan", 0, cfg_file))),
|
||||||
};
|
};
|
||||||
|
|
||||||
return win32.zig.TRUE;
|
return win32.zig.TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_jvs_init() HRESULT {
|
export fn chuni_io_jvs_init() HRESULT {
|
||||||
if(cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return S_OK;
|
if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return S_OK;
|
||||||
tasoller_init() catch return E_FAIL;
|
tasoller_init() catch return E_FAIL;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_jvs_poll(opbtn: ?[*]u8, beams: ?[*]u8) void {
|
export fn chuni_io_jvs_poll(opbtn: ?[*]u8, beams: ?[*]u8) void {
|
||||||
if(cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return;
|
if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return;
|
||||||
if(opbtn == null or beams == null) return;
|
if (opbtn == null or beams == null) return;
|
||||||
if(GetAsyncKeyState(cfg.?.test_key) != 0 or (usb_in.?[3] & (1 << 7)) != 0) opbtn.?.* |= (1 << 0);
|
if (GetAsyncKeyState(cfg.?.test_key) != 0 or (usb_in.?[3] & (1 << 7)) != 0) opbtn.?[0] |= (1 << 0);
|
||||||
if(GetAsyncKeyState(cfg.?.serv_key) != 0 or (usb_in.?[3] & (1 << 6)) != 0) opbtn.?.* |= (1 << 1);
|
if (GetAsyncKeyState(cfg.?.serv_key) != 0 or (usb_in.?[3] & (1 << 6)) != 0) opbtn.?[0] |= (1 << 1);
|
||||||
beams.?.* |= usb_in.?[3] & 0b111111;
|
beams.?[0] |= usb_in.?[3] & 0b111111;
|
||||||
}
|
}
|
||||||
|
|
||||||
var coin_conter: c_ushort = 0;
|
var coin_conter: c_ushort = 0;
|
||||||
var coin_prev_depressed = false;
|
var coin_prev_depressed = false;
|
||||||
export fn chuni_io_jvs_read_coin_counter(total: ?*c_ushort) void {
|
export fn chuni_io_jvs_read_coin_counter(total: ?*c_ushort) void {
|
||||||
if(cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return;
|
if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86_64) return;
|
||||||
if(total == null) return;
|
if (total == null) return;
|
||||||
|
|
||||||
const coin_depressed = GetAsyncKeyState(cfg.?.coin_key) != 0;
|
const coin_depressed = GetAsyncKeyState(cfg.?.coin_key) != 0;
|
||||||
if(coin_depressed and !coin_prev_depressed) coin_conter += 1;
|
if (coin_depressed and !coin_prev_depressed) coin_conter += 1;
|
||||||
coin_prev_depressed = coin_depressed;
|
coin_prev_depressed = coin_depressed;
|
||||||
total.?.* = coin_conter;
|
total.?.* = coin_conter;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_slider_init() HRESULT {
|
export fn chuni_io_slider_init() HRESULT {
|
||||||
if(cfg.?.chusan == 0) return S_OK;
|
if (cfg.?.chusan == 0) return S_OK;
|
||||||
tasoller_init() catch return E_FAIL;
|
tasoller_init() catch return E_FAIL;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_slider_start(callback: chuni_io_slider_callback_t) void {
|
export fn chuni_io_slider_start(callback: chuni_io_slider_callback_t) void {
|
||||||
if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return;
|
if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return;
|
||||||
if(callback == null) return;
|
if (callback == null) return;
|
||||||
|
|
||||||
thread_op.lock();
|
thread_op.lock();
|
||||||
defer thread_op.unlock();
|
defer thread_op.unlock();
|
||||||
if(slider_thread == null) {
|
if (slider_thread == null) {
|
||||||
slider_active = true;
|
slider_active = true;
|
||||||
slider_thread = std.Thread.spawn(.{}, slider_thread_proc, .{callback}) catch |err| {
|
slider_thread = std.Thread.spawn(.{}, slider_thread_proc, .{callback}) catch |err| {
|
||||||
std.log.err("[chuniio] Spawn slider thread: {any}", .{err});
|
std.log.err("[chuniio] Spawn slider thread: {any}", .{err});
|
||||||
@ -267,11 +258,11 @@ export fn chuni_io_slider_start(callback: chuni_io_slider_callback_t) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_slider_stop() void {
|
export fn chuni_io_slider_stop() void {
|
||||||
if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return;
|
if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return;
|
||||||
|
|
||||||
thread_op.lock();
|
thread_op.lock();
|
||||||
defer thread_op.unlock();
|
defer thread_op.unlock();
|
||||||
if(slider_thread != null) {
|
if (slider_thread != null) {
|
||||||
slider_active = false;
|
slider_active = false;
|
||||||
slider_thread.?.join();
|
slider_thread.?.join();
|
||||||
slider_thread = null;
|
slider_thread = null;
|
||||||
@ -279,52 +270,52 @@ export fn chuni_io_slider_stop() void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_slider_set_leds(rgb: ?[*]u8) void {
|
export fn chuni_io_slider_set_leds(rgb: ?[*]u8) void {
|
||||||
if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return;
|
if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return;
|
||||||
if(rgb == null) return;
|
if (rgb == null) return;
|
||||||
|
|
||||||
var n: u32 = 0;
|
var n: u32 = 0;
|
||||||
const out = usb_out[3..96];
|
const out = usb_out[3..96];
|
||||||
while(n < 31) : (n += 1) {
|
while (n < 31) : (n += 1) {
|
||||||
out[n*3+0] = rgb.?[n*3+2];
|
out[n * 3 + 0] = rgb.?[n * 3 + 2];
|
||||||
out[n*3+1] = rgb.?[n*3+1];
|
out[n * 3 + 1] = rgb.?[n * 3 + 1];
|
||||||
out[n*3+2] = rgb.?[n*3+0];
|
out[n * 3 + 2] = rgb.?[n * 3 + 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_out_op.lock();
|
usb_out_op.lock();
|
||||||
defer usb_out_op.unlock();
|
defer usb_out_op.unlock();
|
||||||
if(WinUsb_WritePipe(tasoller, 0x03, @ptrCast(*u8, &usb_out), usb_out.len, &n, null) == 0) {
|
if (WinUsb_WritePipe(tasoller, 0x03, @as(*u8, @ptrCast(&usb_out)), usb_out.len, &n, null) == 0) {
|
||||||
std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()});
|
std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_led_init() HRESULT{
|
export fn chuni_io_led_init() HRESULT {
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
export fn chuni_io_led_set_colors(board: u8, rgb: ?[*]u8) void {
|
export fn chuni_io_led_set_colors(board: u8, rgb: ?[*]u8) void {
|
||||||
if(cfg.?.chusan == 1 and builtin.cpu.arch != .i386) return;
|
if (cfg.?.chusan == 1 and builtin.cpu.arch != .x86) return;
|
||||||
if(rgb == null) return;
|
if (rgb == null) return;
|
||||||
|
|
||||||
var n: u32 = 0;
|
var n: u32 = 0;
|
||||||
if(board == 0) {
|
if (board == 0) {
|
||||||
const out = usb_out[96..168];
|
const out = usb_out[96..168];
|
||||||
while(n < 24) : (n += 1) {
|
while (n < 24) : (n += 1) {
|
||||||
out[n*3+1] = rgb.?[0x96];
|
out[n * 3 + 1] = rgb.?[0x96];
|
||||||
out[n*3+0] = rgb.?[0x97];
|
out[n * 3 + 0] = rgb.?[0x97];
|
||||||
out[n*3+2] = rgb.?[0x98];
|
out[n * 3 + 2] = rgb.?[0x98];
|
||||||
}
|
}
|
||||||
} else if(board == 1) {
|
} else if (board == 1) {
|
||||||
const out = usb_out[168..240];
|
const out = usb_out[168..240];
|
||||||
while(n < 24) : (n += 1) {
|
while (n < 24) : (n += 1) {
|
||||||
out[n*3+1] = rgb.?[0xb4];
|
out[n * 3 + 1] = rgb.?[0xb4];
|
||||||
out[n*3+0] = rgb.?[0xb5];
|
out[n * 3 + 0] = rgb.?[0xb5];
|
||||||
out[n*3+2] = rgb.?[0xb6];
|
out[n * 3 + 2] = rgb.?[0xb6];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_out_op.lock();
|
usb_out_op.lock();
|
||||||
defer usb_out_op.unlock();
|
defer usb_out_op.unlock();
|
||||||
if(WinUsb_WritePipe(tasoller, 0x03, @ptrCast(*u8, &usb_out), usb_out.len, &n, null) == 0) {
|
if (WinUsb_WritePipe(tasoller, 0x03, @as(*u8, @ptrCast(&usb_out)), usb_out.len, &n, null) == 0) {
|
||||||
std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()});
|
std.log.warn("[chuniio] WinUsb_WritePipe: {any}", .{GetLastError()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit a74c9dae6a1ccd361eb9a1d146a09c08d22f02b0
|
Subproject commit 6777f1db221d0cb50322842f558f03e3c3a4099f
|
Loading…
Reference in New Issue
Block a user