generated from sirlilpanda/kicad-project-template-actionless
159 lines
5.2 KiB
Zig
159 lines
5.2 KiB
Zig
// NimBLE wrapper — requires CONFIG_BT_NIMBLE_ENABLED in sdkconfig.
|
|
//
|
|
// Enable via:
|
|
// idf.py menuconfig → Component config → Bluetooth → NimBLE
|
|
//
|
|
// When enabled, re-run `idf.py reconfigure` to regenerate the bindings.
|
|
// NimBLE symbols (ble_hs_*, ble_gap_*, ble_gatt_*) will appear in idf-sys.zig.
|
|
const sys = @import("sys");
|
|
|
|
comptime {
|
|
if (!@hasDecl(sys, "CONFIG_BT_NIMBLE_ENABLED"))
|
|
@compileError(
|
|
\\NimBLE is not enabled. Enable it via:
|
|
\\ idf.py menuconfig → Component config → Bluetooth
|
|
\\ → Host → NimBLE - BLE stack
|
|
\\Then run: idf.py reconfigure
|
|
);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// NimBLE type aliases (available only when CONFIG_BT_NIMBLE_ENABLED=y)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
pub const HsCfg = sys.ble_hs_cfg_t;
|
|
pub const GapConnDesc = sys.ble_gap_conn_desc;
|
|
pub const GapAdvParams = sys.ble_gap_adv_params;
|
|
pub const GapConnParams = sys.ble_gap_conn_params;
|
|
pub const GattSvcDef = sys.ble_gatt_svc_def;
|
|
pub const GattCharDef = sys.ble_gatt_chr_def;
|
|
pub const GattDscrDef = sys.ble_gatt_dsc_def;
|
|
pub const Uuid16 = sys.ble_uuid16_t;
|
|
pub const Uuid128 = sys.ble_uuid128_t;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Host stack
|
|
// ---------------------------------------------------------------------------
|
|
|
|
pub const Host = struct {
|
|
/// Initialize the NimBLE host stack (call before syncing).
|
|
pub fn init() void {
|
|
sys.nimble_port_init();
|
|
}
|
|
|
|
/// Start the NimBLE host task.
|
|
pub fn run() void {
|
|
sys.nimble_port_run();
|
|
}
|
|
|
|
/// Free task resources (call from host task on exit).
|
|
pub fn freeThenResume() void {
|
|
sys.nimble_port_freertos_deinit();
|
|
}
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// GAP (Generic Access Profile)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
pub const Gap = struct {
|
|
pub const AdvType = sys.ble_gap_adv_type;
|
|
pub const EventCb = sys.ble_gap_event_fn;
|
|
|
|
pub fn setDeviceName(name: [*:0]const u8) !void {
|
|
const rc = sys.ble_svc_gap_device_name_set(name);
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
|
|
pub fn advStart(
|
|
own_addr_type: u8,
|
|
direct_addr: ?*const sys.ble_addr_t,
|
|
duration_ms: i32,
|
|
params: ?*const GapAdvParams,
|
|
cb: ?EventCb,
|
|
cb_arg: ?*anyopaque,
|
|
) !void {
|
|
const rc = sys.ble_gap_adv_start(own_addr_type, direct_addr, duration_ms, params, cb, cb_arg);
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
|
|
pub fn advStop() !void {
|
|
const rc = sys.ble_gap_adv_stop();
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
|
|
pub fn connect(
|
|
own_addr_type: u8,
|
|
peer_addr: *const sys.ble_addr_t,
|
|
duration_ms: i32,
|
|
params: ?*const GapConnParams,
|
|
cb: EventCb,
|
|
cb_arg: ?*anyopaque,
|
|
) !void {
|
|
const rc = sys.ble_gap_connect(own_addr_type, peer_addr, duration_ms, params, cb, cb_arg);
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
|
|
pub fn terminate(conn_handle: u16, hci_reason: u8) !void {
|
|
const rc = sys.ble_gap_terminate(conn_handle, hci_reason);
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// GATT Server
|
|
// ---------------------------------------------------------------------------
|
|
|
|
pub const GattServer = struct {
|
|
pub fn registerSvcs(svcs: []const GattSvcDef) !void {
|
|
const rc = sys.ble_gatts_add_svcs(svcs.ptr);
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
|
|
pub fn count(svcs: []const GattSvcDef, out: *sys.ble_gatt_svc_def_iter) !void {
|
|
_ = svcs;
|
|
_ = out;
|
|
}
|
|
|
|
pub fn notify(conn_handle: u16, attr_handle: u16) !void {
|
|
const rc = sys.ble_gatts_notify(conn_handle, attr_handle);
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
|
|
pub fn indicate(conn_handle: u16, attr_handle: u16) !void {
|
|
const rc = sys.ble_gatts_indicate(conn_handle, attr_handle);
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Advertising data builder (OOP API)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
pub const AdvFields = struct {
|
|
fields: sys.ble_hs_adv_fields = .{},
|
|
|
|
pub fn setFlags(self: *AdvFields, flags: u8) void {
|
|
self.fields.flags = flags;
|
|
self.fields.flags_is_present = 1;
|
|
}
|
|
|
|
pub fn setName(self: *AdvFields, name: [*:0]const u8, complete: bool) void {
|
|
self.fields.name = name;
|
|
self.fields.name_len = @intCast(std.mem.len(name));
|
|
self.fields.name_is_complete = @intFromBool(complete);
|
|
}
|
|
|
|
pub fn setTxPwrLvl(self: *AdvFields, level: i8) void {
|
|
self.fields.tx_pwr_lvl = level;
|
|
self.fields.tx_pwr_lvl_is_present = 1;
|
|
}
|
|
|
|
pub fn build(self: *AdvFields, buf: []u8, out_len: *u8) !void {
|
|
const rc = sys.ble_hs_adv_set_fields(&self.fields, buf.ptr, out_len, @intCast(buf.len));
|
|
if (rc != 0) return error.NimbleError;
|
|
}
|
|
};
|
|
|
|
const std = @import("std");
|