android_ble/
descriptor.rs1use std::sync::Arc;
2
3use java_spaghetti::ByteArray;
4
5use super::error::ErrorKind;
6use super::gatt_tree::{CachedWeak, DescriptorInner, GattTree};
7use super::jni::{ByteArrayExt, Monitor};
8use super::util::{BoolExt, IntExt, OptionExt};
9use super::vm_context::{android_api_level, jni_with_env};
10use super::{DeviceId, Result, Uuid};
11
12#[derive(Debug, Clone)]
14pub struct Descriptor {
15 dev_id: DeviceId,
16 service_id: Uuid,
17 char_id: Uuid,
18 desc_id: Uuid,
19 inner: CachedWeak<DescriptorInner>,
20}
21
22impl PartialEq for Descriptor {
23 fn eq(&self, other: &Self) -> bool {
24 self.dev_id == other.dev_id
25 && self.service_id == other.service_id
26 && self.char_id == other.char_id
27 && self.desc_id == other.desc_id
28 }
29}
30
31impl Eq for Descriptor {}
32
33impl Descriptor {
34 pub(crate) fn new(dev_id: DeviceId, service_id: Uuid, char_id: Uuid, desc_id: Uuid) -> Self {
35 Self {
36 dev_id,
37 service_id,
38 char_id,
39 desc_id,
40 inner: CachedWeak::new(),
41 }
42 }
43
44 pub fn uuid(&self) -> Uuid {
46 self.desc_id
47 }
48
49 pub async fn uuid_async(&self) -> Result<Uuid> {
51 Ok(self.desc_id)
52 }
53
54 pub async fn value(&self) -> Result<Vec<u8>> {
56 self.get_inner()?
57 .read
58 .last_value()
59 .ok_or(crate::Error::new(
60 ErrorKind::NotReady,
61 None,
62 "please call `Descriptor::read` at first",
63 ))?
64 }
65
66 pub async fn read(&self) -> Result<Vec<u8>> {
71 let conn = GattTree::check_connection(&self.dev_id)?;
72 let inner = self.get_inner()?;
73 let read_lock = inner.read.lock().await;
74 let _write_lock = inner.write.lock().await;
75 jni_with_env(|env| {
76 let gatt = &conn.gatt.as_ref(env);
77 let gatt = Monitor::new(gatt);
78 gatt.readDescriptor(inner.desc.as_ref(env))
79 .map_err(|e| e.into())
80 .and_then(|b| b.non_false())
81 })?;
82 drop((conn, inner));
83 read_lock
84 .wait_unlock()
85 .await
86 .ok_or_check_conn(&self.dev_id)?
87 }
88
89 pub async fn write(&self, value: &[u8]) -> Result<()> {
91 let conn = GattTree::check_connection(&self.dev_id)?;
92 let inner = self.get_inner()?;
93 let _read_lock = inner.read.lock().await;
94 let write_lock = inner.write.lock().await;
95 jni_with_env(|env| {
96 let gatt = conn.gatt.as_ref(env);
97 let gatt = Monitor::new(&gatt);
98 let desc = inner.desc.as_ref(env);
99 let array = ByteArray::from_slice(env, value);
100 if android_api_level() >= 33 {
101 gatt.writeDescriptor_BluetoothGattDescriptor_byte_array(desc, array)?
102 .check_status_code()
103 } else {
104 #[allow(deprecated)]
105 desc.setValue(array)?;
106 #[allow(deprecated)]
107 gatt.writeDescriptor_BluetoothGattDescriptor(desc)
108 .map_err(|e| e.into())
109 .and_then(|b| b.non_false())
110 }
111 })?;
112 drop((conn, inner));
113 write_lock
114 .wait_unlock()
115 .await
116 .ok_or_check_conn(&self.dev_id)?
117 }
118
119 fn get_inner(&self) -> Result<Arc<DescriptorInner>, crate::Error> {
120 self.inner.get_or_find(|| {
121 GattTree::find_descriptor(&self.dev_id, self.service_id, self.char_id, self.desc_id)
122 .ok_or_check_conn(&self.dev_id)
123 })
124 }
125}