android_ble/
l2cap_channel.rs1use std::io::{Read, Write};
4use std::sync::Arc;
5use std::task::{Context, Poll};
6use std::{fmt, pin, slice, thread};
7
8use futures_lite::io::{AsyncRead, AsyncWrite, BlockOn};
9use java_spaghetti::{ByteArray, Global, Local, PrimitiveArray};
10use log::{debug, trace, warn};
11
12use super::bindings::android::bluetooth::{BluetoothDevice, BluetoothSocket};
13use super::error::ErrorKind;
14use super::util::OptionExt;
15use super::vm_context::{android_api_level, jni_with_env};
16
17const PIPE_CAPACITY: usize = 0x100000; macro_rules! derive_async_read {
20 ($type:ty, $field:tt) => {
21 impl AsyncRead for $type {
22 fn poll_read(
23 mut self: pin::Pin<&mut Self>,
24 cx: &mut Context<'_>,
25 buf: &mut [u8],
26 ) -> Poll<std::io::Result<usize>> {
27 let reader = pin::pin!(&mut self.$field);
28 reader.poll_read(cx, buf)
29 }
30 }
31 };
32}
33
34macro_rules! derive_async_write {
35 ($type:ty, $field:tt) => {
36 impl AsyncWrite for $type {
37 fn poll_write(
38 mut self: pin::Pin<&mut Self>,
39 cx: &mut Context<'_>,
40 buf: &[u8],
41 ) -> Poll<std::io::Result<usize>> {
42 let writer = pin::pin!(&mut self.$field);
43 writer.poll_write(cx, buf)
44 }
45
46 fn poll_flush(
47 mut self: pin::Pin<&mut Self>,
48 cx: &mut Context<'_>,
49 ) -> Poll<std::io::Result<()>> {
50 let writer = pin::pin!(&mut self.$field);
51 writer.poll_flush(cx)
52 }
53
54 fn poll_close(
55 mut self: pin::Pin<&mut Self>,
56 cx: &mut Context<'_>,
57 ) -> Poll<std::io::Result<()>> {
58 let writer = pin::pin!(&mut self.$field);
59 writer.poll_close(cx)
60 }
61
62 fn poll_write_vectored(
63 mut self: pin::Pin<&mut Self>,
64 cx: &mut Context<'_>,
65 bufs: &[std::io::IoSlice<'_>],
66 ) -> Poll<std::io::Result<usize>> {
67 let writer = pin::pin!(&mut self.$field);
68 writer.poll_write_vectored(cx, bufs)
69 }
70 }
71 };
72}
73
74pub fn open_l2cap_channel(
75 device: Global<BluetoothDevice>,
76 psm: u16,
77 secure: bool,
78) -> std::prelude::v1::Result<(L2capChannelReader, L2capChannelWriter), crate::Error> {
79 if android_api_level() < 29 {
80 return Err(crate::Error::new(
81 ErrorKind::NotSupported,
82 None,
83 "creating L2CAP channel requires Android API level 29 or higher",
84 ));
85 }
86 jni_with_env(|env| {
87 let device = device.as_local(env);
88
89 let channel = if secure {
90 device.createL2capChannel(psm as _)?.non_null()?
91 } else {
92 device.createInsecureL2capChannel(psm as _)?.non_null()?
93 };
94
95 channel.connect()?;
96
97 let closer = Arc::new(L2capCloser {
101 channel: channel.as_global(),
102 });
103
104 let (read_receiver, read_sender) = piper::pipe(PIPE_CAPACITY);
105 let (write_receiver, write_sender) = piper::pipe(PIPE_CAPACITY);
106 let input_stream = channel.getInputStream()?.non_null()?.as_global();
107 let output_stream = channel.getOutputStream()?.non_null()?.as_global();
108
109 thread::spawn(move || {
116 debug!("l2cap read thread running!");
117 let mut read_sender = BlockOn::new(read_sender);
118
119 jni_with_env(|env| {
120 let stream = input_stream.as_local(env);
121 let arr: Local<ByteArray> = ByteArray::new(env, 1024);
122
123 loop {
124 match stream.read_byte_array(&arr) {
125 Ok(n) if n < 0 => {
126 warn!("failed to read from l2cap channel: {}", n);
127 break;
128 }
129 Err(e) => {
130 warn!("failed to read from l2cap channel: {:?}", e);
131 break;
132 }
133 Ok(n) => {
134 let n = n as usize;
135 let mut buf = vec![0u8; n];
136 arr.get_region(0, u8toi8_mut(&mut buf));
137 if let Err(e) = read_sender.write_all(&buf) {
138 warn!("failed to enqueue received l2cap packet: {:?}", e);
139 break;
140 }
141 }
142 }
143 }
144 });
145
146 debug!("l2cap read thread exiting!");
147 });
148
149 thread::spawn(move || {
150 debug!("l2cap write thread running!");
151 let mut write_receiver = BlockOn::new(write_receiver);
152 jni_with_env(|env| {
153 let stream = output_stream.as_local(env);
154 let mut buf = vec![0; PIPE_CAPACITY];
155
156 loop {
157 match write_receiver.read(&mut buf) {
158 Err(e) => {
159 warn!("failed to dequeue l2cap packet to send: {:?}", e);
160 break;
161 }
162 Ok(0) => {
163 trace!("Stream ended");
164 break;
165 }
166 Ok(packet) => {
167 let b = ByteArray::new_from(env, u8toi8(&buf[..packet]));
168 if let Err(e) = stream.write_byte_array(b) {
169 warn!("failed to write to l2cap channel: {:?}", e);
170 break;
171 };
172 }
173 }
174 }
175 });
176
177 debug!("l2cap write thread exiting!");
178 });
179
180 Ok((
181 L2capChannelReader {
182 _closer: closer.clone(),
183 stream: read_receiver,
184 },
185 L2capChannelWriter {
186 _closer: closer,
187 stream: write_sender,
188 },
189 ))
190 })
191}
192
193pub(super) struct L2capCloser {
195 channel: Global<BluetoothSocket>,
196}
197
198impl L2capCloser {
199 fn close(&self) {
200 jni_with_env(|env| {
201 let channel = self.channel.as_local(env);
202 match channel.close() {
203 Ok(()) => debug!("l2cap channel closed"),
204 Err(e) => warn!("failed to close channel: {:?}", e),
205 };
206 });
207 }
208}
209
210impl Drop for L2capCloser {
211 fn drop(&mut self) {
212 self.close()
213 }
214}
215
216pub struct L2capChannel {
218 pub(super) reader: L2capChannelReader,
219 pub(super) writer: L2capChannelWriter,
220}
221
222impl L2capChannel {
223 pub fn split(self) -> (L2capChannelReader, L2capChannelWriter) {
225 (self.reader, self.writer)
226 }
227}
228
229derive_async_read!(L2capChannel, reader);
230derive_async_write!(L2capChannel, writer);
231
232pub struct L2capChannelReader {
234 stream: piper::Reader,
235 _closer: Arc<L2capCloser>,
236}
237
238derive_async_read!(L2capChannelReader, stream);
239
240impl fmt::Debug for L2capChannelReader {
241 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
242 f.write_str("L2capChannelReader")
243 }
244}
245
246pub struct L2capChannelWriter {
248 stream: piper::Writer,
249 _closer: Arc<L2capCloser>,
250}
251
252derive_async_write!(L2capChannelWriter, stream);
253
254impl fmt::Debug for L2capChannelWriter {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 f.write_str("L2capChannelWriter")
257 }
258}
259
260fn u8toi8(slice: &[u8]) -> &[i8] {
261 let len = slice.len();
262 let data = slice.as_ptr() as *const i8;
263 unsafe { slice::from_raw_parts(data, len) }
265}
266
267fn u8toi8_mut(slice: &mut [u8]) -> &mut [i8] {
268 let len = slice.len();
269 let data = slice.as_mut_ptr() as *mut i8;
270 unsafe { slice::from_raw_parts_mut(data, len) }
272}