summaryrefslogtreecommitdiff
path: root/system/gd/rust/shim/src/hci.rs
blob: a297e55174f855fcfb206c6ecbd6f9a95b69cd21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Hci shim

use crate::bridge::ffi;
use bluetooth_rs::hci::facade::HciFacadeService;
use bt_facade_helpers::U8SliceRunnable;
use bt_packets::hci::{AclPacket, CommandPacket, IsoPacket, Packet, ScoPacket};
use std::sync::Arc;
use tokio::runtime::Runtime;

// we take ownership when we get the callbacks
unsafe impl Send for ffi::u8SliceCallback {}
unsafe impl Send for ffi::u8SliceOnceCallback {}

struct CallbackWrapper {
    cb: cxx::UniquePtr<ffi::u8SliceCallback>,
}

impl U8SliceRunnable for CallbackWrapper {
    fn run(&self, data: &[u8]) {
        self.cb.Run(data);
    }
}

pub struct Hci {
    internal: HciFacadeService,
    rt: Arc<Runtime>,
}

impl Hci {
    pub fn new(rt: Arc<Runtime>, internal: HciFacadeService) -> Self {
        Self { internal, rt }
    }
}

pub fn hci_send_command(
    hci: &mut Hci,
    data: &[u8],
    callback: cxx::UniquePtr<ffi::u8SliceOnceCallback>,
) {
    log::error!("sending command: {:02x?}", data);
    match CommandPacket::parse(data) {
        Ok(packet) => {
            let mut commands = hci.internal.commands.clone();
            hci.rt.spawn(async move {
                let resp = commands.send(packet).await.unwrap();
                callback.Run(&resp.to_bytes());
            });
        }
        Err(e) => panic!("could not parse command: {:?} {:02x?}", e, data),
    }
}

pub fn hci_send_acl(hci: &mut Hci, data: &[u8]) {
    match AclPacket::parse(data) {
        Ok(packet) => {
            let tx = hci.internal.acl_tx.clone();
            hci.rt.spawn(async move {
                tx.send(packet).await.unwrap();
            });
        }
        Err(e) => panic!("could not parse acl: {:?} {:02x?}", e, data),
    }
}

pub fn hci_send_sco(hci: &mut Hci, data: &[u8]) {
    match ScoPacket::parse(data) {
        Ok(packet) => {
            let tx = hci.internal.sco_tx.clone();
            hci.rt.spawn(async move {
                tx.send(packet).await.unwrap();
            });
        }
        Err(e) => panic!("could not parse sco: {:?} {:02x?}", e, data),
    }
}

pub fn hci_send_iso(hci: &mut Hci, data: &[u8]) {
    match IsoPacket::parse(data) {
        Ok(packet) => {
            let tx = hci.internal.iso_tx.clone();
            hci.rt.spawn(async move {
                tx.send(packet).await.unwrap();
            });
        }
        Err(e) => panic!("could not parse iso: {:?} {:02x?}", e, data),
    }
}

pub fn hci_register_event(hci: &mut Hci, event: u8) {
    let mut hci_facade = hci.internal.clone();
    hci.rt.spawn(async move {
        hci_facade.register_event(event.into()).await;
    });
}

pub fn hci_register_le_event(hci: &mut Hci, subevent: u8) {
    let mut hci_facade = hci.internal.clone();
    hci.rt.spawn(async move {
        hci_facade.register_le_event(subevent.into()).await;
    });
}

pub fn hci_set_acl_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallback>) {
    hci.internal.acl_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}

pub fn hci_set_sco_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallback>) {
    hci.internal.sco_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}

pub fn hci_set_iso_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallback>) {
    hci.internal.iso_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}

pub fn hci_set_evt_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallback>) {
    hci.internal.evt_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}

pub fn hci_set_le_evt_callback(hci: &mut Hci, cb: cxx::UniquePtr<ffi::u8SliceCallback>) {
    hci.internal.le_evt_rx.stream_runnable(&hci.rt, CallbackWrapper { cb });
}