ssttevee/zig-libusb
zig builder and wrapper for libusb
This module takes full advantage of the zig build system to download and build libusb. There is also a thin zig layer for more natural integration in other zig code.
Tested with the following configurations:
Some effort was spent porting other build configurations as well. Please submit a pull request to verify or fix builds on your system if possible.
zig build --release=safe
Run zig build --help
for the full list of options offered by zig.
-Dtarget=[string] The CPU architecture, OS, and ABI to build for
-Dcpu=[string] Target CPU features to add or subtract
-Ddynamic-linker=[string] Path to interpreter on the target system
-Doptimize=[enum] Prioritize performance, safety, or binary size
Supported Values:
Debug
ReleaseSafe
ReleaseFast
ReleaseSmall
-Dstatic=[bool] Build static lib (default: true)
-Dshared=[bool] Build shared lib (default: true)
The zig layer tries OO-ify the library and remove manual bit-wise operations where possible.
Run this command from your project folder
zig fetch --save https://github.com/ssttevee/zig-libusb/archive/refs/tags/1.0.27.tar.gz
Then add this snippet to your build.zig
file
const libusb = b.dependency("libusb", .{
.optimize = optimize,
.target = target,
});
exe.root_module.addImport("libusb", libusb.module("libusb"));
const std = @import("std");
const libusb = @import("libusb");
pub fn main() !void {
try libusb.init(.{ .log_level = .info });
defer libusb.deinit();
const my_device = blk: {
const devices = try libusb.getDeviceList();
defer libusb.freeDeviceList(devices);
for (devices) |device| {
if (isMyDevice(device)) {
break :blk device.ref();
}
}
};
defer my_device.unref();
var config_desc = try my_device.getActiveConfigDescriptor();
defer config_desc.deinit();
const interface_desc = config_desc.interfacesSlice()[0].toSlice()[0];
const write_endpoint = interface_desc.endpointsSlice()[0];
std.debug.assert(write_endpoint.bmAttributes.transfer_type == .bulk);
std.debug.assert(write_endpoint.bEndpointAddress.direction == .output);
const device_handle = try my_device.open();
defer device_handle.close();
defer device_handle.reset() catch {};
const my_interface = try device_handle.claimInterface(interface_desc.bInterfaceNumber);
defer my_interface.release();
const w = my_interface.writable(write_endpoint.bEndpointAddress, 0);
try std.fmt.format(w.writer(), "Hello World\n", .{});
}
The raw c functions are also all accessible
const std = @import("std");
const libusb = @import("libusb");
pub fn main() !void {
try libusb.c.libusb_init_context(null, null, 0).result();
defer libusb.c.libusb_exit(null);
}