Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
7.0 kB · 259 lines
Zig
at zig
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260const USB_IDS_PATH = @import("build_options").USB_IDS_PATH;
const list = @import("list");const device = @import("device");const enumerate = @import("enumerate");const monitor = @import("monitor");const std = @import("std");const c = @import("ffi").c;const mem = std.mem;const fmt = std.fmt;
const Io = std.Io;
const alloc = std.heap.c_allocator;const io = Io.Threaded.global_single_threaded.io();
comptime { _ = device; _ = enumerate; _ = monitor;}
pub const Udev = struct { ref_count: c_int = 1,
const Self = @This();
fn asC(self: *Self) *c.struct_udev { return @ptrCast(self); }
fn fromC(ptr: *c.struct_udev) *Self { return @ptrCast(@alignCast(ptr)); }};
export fn udev_new() callconv(.c) ?*c.struct_udev { const udev = alloc.create(Udev) catch return null; udev.* = .{};
return udev.asC();}
export fn udev_ref(udev: ?*c.struct_udev) callconv(.c) ?*c.struct_udev { const ptr = udev orelse return null;
Udev.fromC(ptr).ref_count += 1; return ptr;}
export fn udev_unref(udev: ?*c.struct_udev) callconv(.c) ?*c.struct_udev { const ptr = udev orelse return null;
const self = Udev.fromC(ptr); self.ref_count -= 1;
if (self.ref_count > 0) { return self.asC(); }
alloc.destroy(self); return null;}
const LogFn = @typeInfo(@TypeOf(c.udev_set_log_fn)).@"fn".params[1].type.?;
export fn udev_set_log_fn( udev: ?*c.struct_udev, log_fn: LogFn,) callconv(.c) void { _ = udev; _ = log_fn;}
export fn udev_set_log_priority(udev: ?*c.struct_udev, priority: c_int) callconv(.c) void { _ = udev; _ = priority;}
export fn udev_get_log_priority(udev: ?*c.struct_udev) callconv(.c) c_int { _ = udev; return 0;}
const Hwdb = struct { head: list.ListEntry = .{}, refcount: c_int,
const Self = @This();
fn asC(self: *Self) *c.struct_udev_hwdb { return @ptrCast(self); }
fn fromC(ptr: *c.struct_udev_hwdb) *Self { return @ptrCast(@alignCast(ptr)); }};
fn copyUsbIdsName(buf: []u8, line: []const u8, search_start: usize) bool { const space_offset = mem.indexOfScalar(u8, line[search_start..], ' ') orelse return false; const name = mem.trimStart(u8, line[search_start + space_offset ..], " "); if (name.len == 0) return false;
const copy_len = @min(name.len, buf.len - 1); @memcpy(buf[0..copy_len], name[0..copy_len]); buf[copy_len] = 0; return true;}
pub fn usb_ids_lookup_vendor(vendorid: u16, buf: []u8) bool { if (buf.len == 0) return false; buf[0] = 0;
const file = Io.Dir.cwd().openFile(io, USB_IDS_PATH, .{}) catch return false; defer file.close(io);
var read_buffer: [4096]u8 = undefined; var file_reader = file.reader(io, &read_buffer); const reader = &file_reader.interface;
while (reader.takeDelimiter('\n') catch return false) |line| { const clean_line = mem.trimEnd(u8, line, "\r");
if (clean_line.len < 4 or clean_line[0] == '#' or clean_line[0] == '\t') { continue; }
const id = fmt.parseInt(u16, clean_line[0..4], 16) catch continue; if (id != vendorid) continue;
return copyUsbIdsName(buf, clean_line, 0); }
return false;}
pub fn usb_ids_lookup_product(vendorid: u16, productid: u16, buf: []u8) bool { if (buf.len == 0) return false; buf[0] = 0;
const file = Io.Dir.cwd().openFile(io, USB_IDS_PATH, .{}) catch return false; defer file.close(io);
var read_buffer: [4096]u8 = undefined; var file_reader = file.reader(io, &read_buffer); const reader = &file_reader.interface; var in_vendor = false;
while (reader.takeDelimiter('\n') catch return false) |line| { const clean_line = mem.trimEnd(u8, line, "\r"); if (clean_line.len == 0 or clean_line[0] == '#') continue;
if (in_vendor) { if (clean_line[0] != '\t') break; if (clean_line.len < 5 or clean_line[1] == '\t') continue;
const id = fmt.parseInt(u16, clean_line[1..5], 16) catch continue; if (id != productid) continue;
return copyUsbIdsName(buf, clean_line, 1); }
if (clean_line[0] == '\t' or clean_line.len < 4) continue;
const id = fmt.parseInt(u16, clean_line[0..4], 16) catch continue; if (id == vendorid) in_vendor = true; }
return false;}
export fn udev_hwdb_new(udev: ?*c.struct_udev) callconv(.c) ?*c.struct_udev_hwdb { _ = udev;
const hwdb = alloc.create(Hwdb) catch return null; hwdb.* = .{ .refcount = 1 };
return hwdb.asC();}
export fn udev_hwdb_ref(hwdb: ?*c.struct_udev_hwdb) callconv(.c) ?*c.struct_udev_hwdb { const ptr = hwdb orelse return null; Hwdb.fromC(ptr).refcount += 1;
return hwdb;}
export fn udev_hwdb_unref(hwdb: ?*c.struct_udev_hwdb) callconv(.c) ?*c.struct_udev_hwdb { const ptr = hwdb orelse return null; const self = Hwdb.fromC(ptr); self.refcount -= 1;
if (self.refcount > 0) { return null; }
list.udev_list_entry_free_all(self.head.asC()); alloc.destroy(self);
return null;}
export fn udev_hwdb_get_properties_list_entry(hwdb: ?*c.struct_udev_hwdb, modalias: [*c]const u8, flags: c_uint) callconv(.c) ?*c.udev_list_entry { _ = flags;
const hwdb_ptr = hwdb orelse return null; const modalias_ptr = modalias orelse return null;
const self = Hwdb.fromC(hwdb_ptr);
list.udev_list_entry_free_all(self.head.asC()); self.head.next = null;
const text = mem.span(modalias_ptr); const prefix = "usb:v";
var name: [64]u8 = undefined; if (mem.startsWith(u8, text, prefix) and text.len >= prefix.len + 4) { const vendor_start = prefix.len; const vendor_end = vendor_start + 4;
if (fmt.parseInt( u16, text[vendor_start..vendor_end], 16, )) |vendor_id| { const product_start = vendor_end + 1; const product_end = product_start + 4;
if (text.len >= product_end and text[vendor_end] == 'p') { if (fmt.parseInt( u16, text[product_start..product_end], 16, )) |product_id| { if (usb_ids_lookup_product(vendor_id, product_id, &name)) { _ = list.udev_list_entry_add(self.head.asC(), "ID_MODEL_FROM_DATABASE", name[0..].ptr, 0); } } else |_| {} } else { if (usb_ids_lookup_vendor(vendor_id, &name)) { _ = list.udev_list_entry_add(self.head.asC(), "ID_VENDOR_FROM_DATABASE", name[0..].ptr, 0); } } } else |_| {} }
if (self.head.next) |next| { return next.asC(); } else { return null; }}