Packages

Bluetooth (discovery, SPP/HFP/HID) for Mob apps (extracted from mob core)

Current section

Files

Jump to
mob_bluetooth priv native jni mob_bluetooth_jni.c
Raw

priv/native/jni/mob_bluetooth_jni.c

// mob_bluetooth_jni.c — JNI delivery thunks for the mob_bluetooth plugin.
//
// Copied VERBATIM from mob-core's beam_jni.c Bluetooth section, with ONLY the
// JNI symbol prefix renamed:
// Java_com_example_mob_1plugin_1demo_MobBridge_nativeDeliverBt*
// → Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBt*
//
// Compiled as a plain C object via the plugin `jni_source` pipeline
// (build.zig `-Dplugin_jni_sources`) — NOT a NIF init (no
// STATIC_ERLANG_NIF_LIBNAME). Each thunk unmarshals the Java args into C
// primitives, calls the matching `mob_deliver_bt_*` export (defined in the
// sibling zig NIF `mob_bluetooth_nif.zig`, linked into the same .so), then
// releases.
//
// mob-core's beam_jni.c gets these `mob_deliver_bt_*` prototypes from
// `mob_beam.h`; this plugin source isn't built against that header, so the
// prototypes are declared inline below (copied byte-for-byte from the
// `mob_deliver_bt_*` block of mob_beam.h, which mirrors the zig export
// signatures).
#include <jni.h>
#include <stddef.h>
// ── mob_deliver_bt_* prototypes (from the zig NIF, replicating mob_beam.h) ──
// Discovery (no-payload 2-tuples)
void mob_deliver_bt_discovery_started(jlong pid);
void mob_deliver_bt_discovery_finished(jlong pid);
void mob_deliver_bt_discovery_cancelled(jlong pid);
// Discovery / pairing events (3-tuples, no session)
void mob_deliver_bt_discovered(jlong pid, const char *address, const char *name, int bonded);
void mob_deliver_bt_paired(jlong pid, const char *address, const char *name, int bonded);
void mob_deliver_bt_pair_failed(jlong pid, const char *address, const char *reason);
void mob_deliver_bt_unpaired(jlong pid, const char *address);
void mob_deliver_bt_error(jlong pid, const char *reason);
// Paired-list streaming (begin / entry / finish)
void mob_deliver_bt_paired_list_begin(jlong pid);
void mob_deliver_bt_paired_list_entry(jlong pid, const char *address, const char *name, int bonded);
void mob_deliver_bt_paired_list_finish(jlong pid);
// HFP profile
void mob_deliver_bt_hfp_connecting(jlong pid, int session, const char *address);
void mob_deliver_bt_hfp_connected(jlong pid, int session, const char *address, const char *name);
void mob_deliver_bt_hfp_connect_failed(jlong pid, const char *address, const char *reason);
void mob_deliver_bt_hfp_disconnected(jlong pid, int session, const char *reason_atom);
void mob_deliver_bt_hfp_vendor_subscribed(jlong pid, int session);
void mob_deliver_bt_hfp_vendor_at(jlong pid, int session, const char *cmd, int cmd_type,
const char *args, const char *address);
void mob_deliver_bt_hfp_sco_started(jlong pid, int session, const char *address);
void mob_deliver_bt_hfp_sco_stopped(jlong pid, int session);
void mob_deliver_bt_hfp_error(jlong pid, int session, const char *reason);
// SPP profile
void mob_deliver_bt_spp_connected(jlong pid, int session, const char *address, const char *name);
void mob_deliver_bt_spp_connect_failed(jlong pid, const char *address, const char *reason);
void mob_deliver_bt_spp_disconnected(jlong pid, int session, const char *reason_atom);
void mob_deliver_bt_spp_data(jlong pid, int session, const char *bytes, size_t len);
void mob_deliver_bt_spp_written(jlong pid, int session, int size);
void mob_deliver_bt_spp_error(jlong pid, int session, const char *reason);
// ── Bluetooth Classic (Mob.Bt suite) — JNI thunks ───────────────────────
// Each thunk unmarshals Java args into C primitives, calls the matching
// mob_deliver_bt_* helper, then releases.
// ── Adapter-level events (no session) ──────────────────────────────────
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtDiscoveryStarted(JNIEnv* env, jclass cls,
jlong pid) {
mob_deliver_bt_discovery_started(pid);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtDiscoveryFinished(JNIEnv* env, jclass cls,
jlong pid) {
mob_deliver_bt_discovery_finished(pid);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtDiscoveryCancelled(JNIEnv* env, jclass cls,
jlong pid) {
mob_deliver_bt_discovery_cancelled(pid);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtDiscovered(JNIEnv* env, jclass cls,
jlong pid, jstring address, jstring name, jboolean bonded) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_name = (*env)->GetStringUTFChars(env, name, NULL);
mob_deliver_bt_discovered(pid, c_address, c_name, bonded ? 1 : 0);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, name, c_name);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtPaired(JNIEnv* env, jclass cls,
jlong pid, jstring address, jstring name, jboolean bonded) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_name = (*env)->GetStringUTFChars(env, name, NULL);
mob_deliver_bt_paired(pid, c_address, c_name, bonded ? 1 : 0);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, name, c_name);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtPairFailed(JNIEnv* env, jclass cls,
jlong pid, jstring address, jstring reason) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_pair_failed(pid, c_address, c_reason);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtUnpaired(JNIEnv* env, jclass cls,
jlong pid, jstring address) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
mob_deliver_bt_unpaired(pid, c_address);
(*env)->ReleaseStringUTFChars(env, address, c_address);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtError(JNIEnv* env, jclass cls,
jlong pid, jstring reason) {
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_error(pid, c_reason);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}
// ── Paired-list streaming builder ──────────────────────────────────────
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtPairedListBegin(JNIEnv* env, jclass cls,
jlong pid) {
mob_deliver_bt_paired_list_begin(pid);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtPairedListEntry(JNIEnv* env, jclass cls,
jlong pid, jstring address, jstring name, jboolean bonded) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_name = (*env)->GetStringUTFChars(env, name, NULL);
mob_deliver_bt_paired_list_entry(pid, c_address, c_name, bonded ? 1 : 0);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, name, c_name);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtPairedListFinish(JNIEnv* env, jclass cls,
jlong pid) {
mob_deliver_bt_paired_list_finish(pid);
}
// ── HFP profile ────────────────────────────────────────────────────────
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpConnecting(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring address) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
mob_deliver_bt_hfp_connecting(pid, (int)session, c_address);
(*env)->ReleaseStringUTFChars(env, address, c_address);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpConnected(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring address, jstring name) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_name = (*env)->GetStringUTFChars(env, name, NULL);
mob_deliver_bt_hfp_connected(pid, (int)session, c_address, c_name);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, name, c_name);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpConnectFailed(JNIEnv* env, jclass cls,
jlong pid, jstring address, jstring reason) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_hfp_connect_failed(pid, c_address, c_reason);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpDisconnected(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring reason) {
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_hfp_disconnected(pid, (int)session, c_reason);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpVendorSubscribed(JNIEnv* env, jclass cls,
jlong pid, jint session) {
mob_deliver_bt_hfp_vendor_subscribed(pid, (int)session);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpVendorAt(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring cmd, jint cmd_type, jstring args, jstring address) {
const char* c_cmd = (*env)->GetStringUTFChars(env, cmd, NULL);
const char* c_args = (*env)->GetStringUTFChars(env, args, NULL);
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
mob_deliver_bt_hfp_vendor_at(pid, (int)session, c_cmd, (int)cmd_type, c_args, c_address);
(*env)->ReleaseStringUTFChars(env, cmd, c_cmd);
(*env)->ReleaseStringUTFChars(env, args, c_args);
(*env)->ReleaseStringUTFChars(env, address, c_address);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpScoStarted(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring address) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
mob_deliver_bt_hfp_sco_started(pid, (int)session, c_address);
(*env)->ReleaseStringUTFChars(env, address, c_address);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpScoStopped(JNIEnv* env, jclass cls,
jlong pid, jint session) {
mob_deliver_bt_hfp_sco_stopped(pid, (int)session);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtHfpError(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring reason) {
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_hfp_error(pid, (int)session, c_reason);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}
// ── SPP profile ────────────────────────────────────────────────────────
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtSppConnected(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring address, jstring name) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_name = (*env)->GetStringUTFChars(env, name, NULL);
mob_deliver_bt_spp_connected(pid, (int)session, c_address, c_name);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, name, c_name);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtSppConnectFailed(JNIEnv* env, jclass cls,
jlong pid, jstring address, jstring reason) {
const char* c_address = (*env)->GetStringUTFChars(env, address, NULL);
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_spp_connect_failed(pid, c_address, c_reason);
(*env)->ReleaseStringUTFChars(env, address, c_address);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtSppDisconnected(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring reason) {
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_spp_disconnected(pid, (int)session, c_reason);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtSppData(JNIEnv* env, jclass cls,
jlong pid, jint session, jbyteArray data) {
jsize len = (*env)->GetArrayLength(env, data);
jbyte* buf = (*env)->GetByteArrayElements(env, data, NULL);
mob_deliver_bt_spp_data(pid, (int)session, (const char*)buf, (size_t)len);
(*env)->ReleaseByteArrayElements(env, data, buf, JNI_ABORT);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtSppWritten(JNIEnv* env, jclass cls,
jlong pid, jint session, jint size) {
mob_deliver_bt_spp_written(pid, (int)session, (int)size);
}
JNIEXPORT void JNICALL
Java_io_mob_bluetooth_MobBluetoothBridge_nativeDeliverBtSppError(JNIEnv* env, jclass cls,
jlong pid, jint session, jstring reason) {
const char* c_reason = (*env)->GetStringUTFChars(env, reason, NULL);
mob_deliver_bt_spp_error(pid, (int)session, c_reason);
(*env)->ReleaseStringUTFChars(env, reason, c_reason);
}