1use core::cell::RefCell;
3use core::future::Future;
4use core::marker::PhantomData;
5
6use bt_hci::controller::Controller;
7use bt_hci::param::{ConnHandle, PhyKind, Status};
8use bt_hci::uuid::declarations::{CHARACTERISTIC, PRIMARY_SERVICE};
9use bt_hci::uuid::descriptors::CLIENT_CHARACTERISTIC_CONFIGURATION;
10use embassy_futures::select::{select, Either};
11use embassy_sync::blocking_mutex::raw::{NoopRawMutex, RawMutex};
12use embassy_sync::channel::{Channel, DynamicReceiver};
13use embassy_sync::pubsub::{self, PubSubChannel, WaitResult};
14use embassy_time::Duration;
15use heapless::Vec;
16
17use crate::att::{self, Att, AttClient, AttCmd, AttErrorCode, AttReq, AttRsp, AttServer, AttUns, ATT_HANDLE_VALUE_NTF};
18use crate::attribute::{AttributeData, Characteristic, CharacteristicProp, Uuid, CCCD};
19use crate::attribute_server::{AttributeServer, DynamicAttributeServer};
20use crate::connection::Connection;
21use crate::cursor::{ReadCursor, WriteCursor};
22use crate::pdu::Pdu;
23use crate::prelude::ConnectionEvent;
24#[cfg(feature = "security")]
25use crate::security_manager::BondInformation;
26use crate::types::gatt_traits::{AsGatt, FromGatt, FromGattError};
27use crate::types::l2cap::L2capHeader;
28use crate::{config, BleHostError, Error, PacketPool, Stack};
29
30pub enum GattConnectionEvent<'stack, 'server, P: PacketPool> {
32    Disconnected {
34        reason: Status,
36    },
37    PhyUpdated {
39        tx_phy: PhyKind,
41        rx_phy: PhyKind,
43    },
44    ConnectionParamsUpdated {
46        conn_interval: Duration,
48        peripheral_latency: u16,
50        supervision_timeout: Duration,
52    },
53    #[cfg(feature = "security")]
54    Bonded {
56        bond_info: BondInformation,
58    },
59    Gatt {
61        event: GattEvent<'stack, 'server, P>,
63    },
64}
65
66pub struct GattConnection<'stack, 'server, P: PacketPool> {
68    connection: Connection<'stack, P>,
69    pub(crate) server: &'server dyn DynamicAttributeServer<P>,
70}
71
72impl<P: PacketPool> Drop for GattConnection<'_, '_, P> {
73    fn drop(&mut self) {
74        trace!("[gatt {}] disconnecting from server", self.connection.handle().raw());
75        self.server.disconnect(&self.connection);
76    }
77}
78
79impl<'stack, 'server, P: PacketPool> GattConnection<'stack, 'server, P> {
80    pub(crate) fn try_new<'values, M: RawMutex, const AT: usize, const CT: usize, const CN: usize>(
83        connection: Connection<'stack, P>,
84        server: &'server AttributeServer<'values, M, P, AT, CT, CN>,
85    ) -> Result<Self, Error> {
86        trace!("[gatt {}] connecting to server", connection.handle().raw());
87        server.connect(&connection)?;
88        Ok(Self { connection, server })
89    }
90
91    pub async fn next(&self) -> GattConnectionEvent<'stack, 'server, P> {
95        match select(self.connection.next(), self.connection.next_gatt()).await {
96            Either::First(event) => match event {
97                ConnectionEvent::Disconnected { reason } => GattConnectionEvent::Disconnected { reason },
98                ConnectionEvent::ConnectionParamsUpdated {
99                    conn_interval,
100                    peripheral_latency,
101                    supervision_timeout,
102                } => GattConnectionEvent::ConnectionParamsUpdated {
103                    conn_interval,
104                    peripheral_latency,
105                    supervision_timeout,
106                },
107                ConnectionEvent::PhyUpdated { tx_phy, rx_phy } => GattConnectionEvent::PhyUpdated { tx_phy, rx_phy },
108                #[cfg(feature = "security")]
109                ConnectionEvent::Bonded { bond_info } => {
110                    if let Err(e) = self.server.update_identity(bond_info.identity) {
112                        error!("Failed to update identity in att server: {:?}", e);
113                    }
114                    GattConnectionEvent::Bonded { bond_info }
115                }
116            },
117            Either::Second(data) => GattConnectionEvent::Gatt {
118                event: GattEvent::new(GattData::new(data, self.connection.clone()), self.server),
119            },
120        }
121    }
122
123    pub fn raw(&self) -> &Connection<'stack, P> {
125        &self.connection
126    }
127}
128
129pub struct GattData<'stack, P: PacketPool> {
131    pdu: Option<Pdu<P::Packet>>,
132    connection: Connection<'stack, P>,
133}
134
135impl<'stack, P: PacketPool> GattData<'stack, P> {
136    pub(crate) const fn new(pdu: Pdu<P::Packet>, connection: Connection<'stack, P>) -> Self {
137        Self {
138            pdu: Some(pdu),
139            connection,
140        }
141    }
142
143    pub fn handle(&self) -> Option<u16> {
147        match self.incoming() {
148            AttClient::Request(AttReq::Write { handle, .. }) => Some(handle),
149            AttClient::Command(AttCmd::Write { handle, .. }) => Some(handle),
150            AttClient::Request(AttReq::Read { handle }) => Some(handle),
151            AttClient::Request(AttReq::ReadBlob { handle, .. }) => Some(handle),
152            _ => None,
153        }
154    }
155
156    pub fn incoming(&self) -> AttClient<'_> {
158        let att = unwrap!(Att::decode(self.pdu.as_ref().unwrap().as_ref()));
162        let Att::Client(client) = att else {
163            unreachable!("Expected Att::Client, got {:?}", att)
164        };
165
166        client
167    }
168
169    pub async fn reply(self, rsp: AttRsp<'_>) -> Result<(), Error> {
171        let pdu = send(&self.connection, AttServer::Response(rsp))?;
172        self.connection.send(pdu).await;
173        Ok(())
174    }
175
176    pub async fn send_unsolicited(connection: &Connection<'_, P>, uns: AttUns<'_>) -> Result<(), Error> {
178        let pdu = send(connection, AttServer::Unsolicited(uns))?;
179        connection.send(pdu).await;
180        Ok(())
181    }
182}
183
184pub enum GattEvent<'stack, 'server, P: PacketPool> {
186    Read(ReadEvent<'stack, 'server, P>),
188    Write(WriteEvent<'stack, 'server, P>),
190    Other(OtherEvent<'stack, 'server, P>),
192}
193
194impl<'stack, 'server, P: PacketPool> GattEvent<'stack, 'server, P> {
195    pub fn new(data: GattData<'stack, P>, server: &'server dyn DynamicAttributeServer<P>) -> Self {
197        let att = data.incoming();
198        match att {
199            AttClient::Request(AttReq::Write { .. }) | AttClient::Command(AttCmd::Write { .. }) => {
200                GattEvent::Write(WriteEvent { data, server })
201            }
202            AttClient::Request(AttReq::Read { .. }) | AttClient::Request(AttReq::ReadBlob { .. }) => {
203                GattEvent::Read(ReadEvent { data, server })
204            }
205            _ => GattEvent::Other(OtherEvent { data, server }),
206        }
207    }
208
209    pub fn accept(self) -> Result<Reply<'stack, P>, Error> {
211        match self {
212            Self::Read(e) => e.accept(),
213            Self::Write(e) => e.accept(),
214            Self::Other(e) => e.accept(),
215        }
216    }
217
218    pub fn reject(self, err: AttErrorCode) -> Result<Reply<'stack, P>, Error> {
220        match self {
221            Self::Read(e) => e.reject(err),
222            Self::Write(e) => e.reject(err),
223            Self::Other(e) => e.reject(err),
224        }
225    }
226
227    pub fn payload(&self) -> &GattData<'stack, P> {
229        match self {
230            Self::Read(e) => e.payload(),
231            Self::Write(e) => e.payload(),
232            Self::Other(e) => e.payload(),
233        }
234    }
235
236    pub fn into_payload(self) -> GattData<'stack, P> {
243        match self {
244            Self::Read(e) => e.into_payload(),
245            Self::Write(e) => e.into_payload(),
246            Self::Other(e) => e.into_payload(),
247        }
248    }
249}
250
251pub struct ReadEvent<'stack, 'server, P: PacketPool> {
253    data: GattData<'stack, P>,
254    server: &'server dyn DynamicAttributeServer<P>,
255}
256
257impl<'stack, P: PacketPool> ReadEvent<'stack, '_, P> {
258    pub fn handle(&self) -> u16 {
260        unwrap!(self.data.handle())
263    }
264
265    pub fn accept(mut self) -> Result<Reply<'stack, P>, Error> {
269        process(&mut self.data, self.server, Ok(()))
270    }
271
272    pub fn reject(mut self, err: AttErrorCode) -> Result<Reply<'stack, P>, Error> {
274        process(&mut self.data, self.server, Err(err))
275    }
276
277    pub fn payload(&self) -> &GattData<'stack, P> {
279        &self.data
280    }
281
282    pub fn into_payload(mut self) -> GattData<'stack, P> {
289        GattData {
290            pdu: self.data.pdu.take(),
291            connection: self.data.connection.clone(),
292        }
293    }
294}
295
296impl<P: PacketPool> Drop for ReadEvent<'_, '_, P> {
297    fn drop(&mut self) {
298        let _ = process(&mut self.data, self.server, Ok(()));
299    }
300}
301
302pub struct WriteEvent<'stack, 'server, P: PacketPool> {
304    data: GattData<'stack, P>,
305    server: &'server dyn DynamicAttributeServer<P>,
306}
307
308impl<'stack, P: PacketPool> WriteEvent<'stack, '_, P> {
309    pub fn handle(&self) -> u16 {
311        unwrap!(self.data.handle())
314    }
315
316    pub fn data(&self) -> &[u8] {
318        &self.data.pdu.as_ref().unwrap().as_ref()[3..]
320    }
321
322    pub fn value<T: FromGatt>(&self, _c: &Characteristic<T>) -> Result<T, FromGattError> {
324        T::from_gatt(self.data())
325    }
326
327    pub fn accept(mut self) -> Result<Reply<'stack, P>, Error> {
331        process(&mut self.data, self.server, Ok(()))
332    }
333
334    pub fn reject(mut self, err: AttErrorCode) -> Result<Reply<'stack, P>, Error> {
336        process(&mut self.data, self.server, Err(err))
337    }
338
339    pub fn payload(&self) -> &GattData<'stack, P> {
341        &self.data
342    }
343
344    pub fn into_payload(mut self) -> GattData<'stack, P> {
351        GattData {
352            pdu: self.data.pdu.take(),
353            connection: self.data.connection.clone(),
354        }
355    }
356}
357
358impl<P: PacketPool> Drop for WriteEvent<'_, '_, P> {
359    fn drop(&mut self) {
360        let _ = process(&mut self.data, self.server, Ok(()));
361    }
362}
363
364pub struct OtherEvent<'stack, 'server, P: PacketPool> {
366    data: GattData<'stack, P>,
367    server: &'server dyn DynamicAttributeServer<P>,
368}
369
370impl<'stack, P: PacketPool> OtherEvent<'stack, '_, P> {
371    pub fn accept(mut self) -> Result<Reply<'stack, P>, Error> {
375        process(&mut self.data, self.server, Ok(()))
376    }
377
378    pub fn reject(mut self, err: AttErrorCode) -> Result<Reply<'stack, P>, Error> {
380        process(&mut self.data, self.server, Err(err))
381    }
382
383    pub fn payload(&self) -> &GattData<'stack, P> {
385        &self.data
386    }
387
388    pub fn into_payload(mut self) -> GattData<'stack, P> {
395        GattData {
396            pdu: self.data.pdu.take(),
397            connection: self.data.connection.clone(),
398        }
399    }
400}
401
402impl<P: PacketPool> Drop for OtherEvent<'_, '_, P> {
403    fn drop(&mut self) {
404        let _ = process(&mut self.data, self.server, Ok(()));
405    }
406}
407
408fn process<'stack, P>(
409    data: &mut GattData<'stack, P>,
410    server: &dyn DynamicAttributeServer<P>,
411    result: Result<(), AttErrorCode>,
412) -> Result<Reply<'stack, P>, Error>
413where
414    P: PacketPool,
415{
416    if let Some(pdu) = data.pdu.take() {
417        let res = match result {
418            Ok(_) => process_accept(&pdu, &data.connection, server),
419            Err(code) => process_reject(&pdu, &data.connection, code),
420        };
421        res
422    } else {
423        Ok(Reply::new(data.connection.clone(), None))
424    }
425}
426
427fn process_accept<'stack, P>(
428    pdu: &Pdu<P::Packet>,
429    connection: &Connection<'stack, P>,
430    server: &dyn DynamicAttributeServer<P>,
431) -> Result<Reply<'stack, P>, Error>
432where
433    P: PacketPool,
434{
435    let att = unwrap!(Att::decode(pdu.as_ref()));
438    let Att::Client(att) = att else {
439        unreachable!("Expected Att::Client, got {:?}", att)
440    };
441    let mut tx = P::allocate().ok_or(Error::OutOfMemory)?;
442    let mut w = WriteCursor::new(tx.as_mut());
443    let (mut header, mut data) = w.split(4)?;
444    if let Some(written) = server.process(connection, &att, data.write_buf())? {
445        let mtu = connection.get_att_mtu();
446        data.commit(written)?;
447        data.truncate(mtu as usize);
448        header.write(data.len() as u16)?;
449        header.write(4_u16)?;
450        let len = header.len() + data.len();
451        let pdu = Pdu::new(tx, len);
452        Ok(Reply::new(connection.clone(), Some(pdu)))
453    } else {
454        Ok(Reply::new(connection.clone(), None))
455    }
456}
457
458fn process_reject<'stack, P: PacketPool>(
459    pdu: &Pdu<P::Packet>,
460    connection: &Connection<'stack, P>,
461    code: AttErrorCode,
462) -> Result<Reply<'stack, P>, Error> {
463    let att = unwrap!(Att::decode(pdu.as_ref()));
466    let Att::Client(att) = att else {
467        unreachable!("Expected Att::Client, got {:?}", att)
468    };
469    let handle = match att {
470        AttClient::Request(AttReq::Write { handle, .. }) => handle,
471        AttClient::Command(AttCmd::Write { handle, .. }) => handle,
472        AttClient::Request(AttReq::Read { handle }) => handle,
473        AttClient::Request(AttReq::ReadBlob { handle, .. }) => handle,
474        _ => 0, };
476    let request = pdu.as_ref()[0];
478    let rsp = AttRsp::Error { request, handle, code };
479    let pdu = send(connection, AttServer::Response(rsp))?;
480    Ok(Reply::new(connection.clone(), Some(pdu)))
481}
482
483fn send<'stack, P: PacketPool>(conn: &Connection<'stack, P>, att: AttServer<'_>) -> Result<Pdu<P::Packet>, Error> {
484    let mut tx = P::allocate().ok_or(Error::OutOfMemory)?;
485    let mut w = WriteCursor::new(tx.as_mut());
486    let (mut header, mut data) = w.split(4)?;
487    data.write(Att::Server(att))?;
488
489    let mtu = conn.get_att_mtu();
490    data.truncate(mtu as usize);
491    header.write(data.len() as u16)?;
492    header.write(4_u16)?;
493    let len = header.len() + data.len();
494    Ok(Pdu::new(tx, len))
495}
496
497pub struct Reply<'stack, P: PacketPool> {
502    connection: Connection<'stack, P>,
503    pdu: Option<Pdu<P::Packet>>,
504}
505
506impl<'stack, P: PacketPool> Reply<'stack, P> {
507    fn new(connection: Connection<'stack, P>, pdu: Option<Pdu<P::Packet>>) -> Self {
508        Self { connection, pdu }
509    }
510
511    pub fn try_send(mut self) -> Result<(), Error> {
515        if let Some(pdu) = self.pdu.take() {
516            self.connection.try_send(pdu)
517        } else {
518            Ok(())
519        }
520    }
521
522    pub async fn send(mut self) {
524        if let Some(pdu) = self.pdu.take() {
525            self.connection.send(pdu).await
526        }
527    }
528}
529
530impl<P: PacketPool> Drop for Reply<'_, P> {
531    fn drop(&mut self) {
532        if let Some(pdu) = self.pdu.take() {
533            if self.connection.try_send(pdu).is_err() {
534                warn!("[gatt] error sending reply (outbound buffer full)");
535            }
536        }
537    }
538}
539
540pub struct NotificationListener<'lst, const MTU: usize> {
542    handle: u16,
543    listener: pubsub::DynSubscriber<'lst, Notification<MTU>>,
544}
545
546impl<'lst, const MTU: usize> NotificationListener<'lst, MTU> {
547    #[allow(clippy::should_implement_trait)]
548    pub async fn next(&mut self) -> Notification<MTU> {
550        loop {
551            if let WaitResult::Message(m) = self.listener.next_message().await {
552                if m.handle == self.handle {
553                    return m;
554                }
555            }
556        }
557    }
558}
559
560const MAX_NOTIF: usize = config::GATT_CLIENT_NOTIFICATION_MAX_SUBSCRIBERS;
561const NOTIF_QSIZE: usize = config::GATT_CLIENT_NOTIFICATION_QUEUE_SIZE;
562
563pub struct GattClient<'reference, T: Controller, P: PacketPool, const MAX_SERVICES: usize> {
565    known_services: RefCell<Vec<ServiceHandle, MAX_SERVICES>>,
566    rx: DynamicReceiver<'reference, (ConnHandle, Pdu<P::Packet>)>,
567    stack: &'reference Stack<'reference, T, P>,
568    connection: Connection<'reference, P>,
569    response_channel: Channel<NoopRawMutex, (ConnHandle, Pdu<P::Packet>), 1>,
570
571    notifications: PubSubChannel<NoopRawMutex, Notification<512>, NOTIF_QSIZE, MAX_NOTIF, 1>,
573}
574
575#[derive(Debug, PartialEq, Clone)]
577#[cfg_attr(feature = "defmt", derive(defmt::Format))]
578pub struct Notification<const MTU: usize> {
579    handle: u16,
580    data: [u8; MTU],
581    len: usize,
582}
583
584impl<const MTU: usize> AsRef<[u8]> for Notification<MTU> {
585    fn as_ref(&self) -> &[u8] {
586        &self.data[..self.len]
587    }
588}
589
590#[cfg_attr(feature = "defmt", derive(defmt::Format))]
592#[derive(Debug, PartialEq, Clone)]
593pub struct ServiceHandle {
594    start: u16,
595    end: u16,
596    uuid: Uuid,
597}
598
599pub(crate) struct Response<P> {
600    pdu: Pdu<P>,
601    handle: ConnHandle,
602}
603
604pub(crate) trait Client<'d, E, P: PacketPool> {
606    fn request(&self, req: AttReq<'_>) -> impl Future<Output = Result<Response<P::Packet>, BleHostError<E>>>;
608    fn command(&self, cmd: AttCmd<'_>) -> impl Future<Output = Result<(), BleHostError<E>>>;
609}
610
611impl<'reference, T: Controller, P: PacketPool, const MAX_SERVICES: usize> Client<'reference, T::Error, P>
612    for GattClient<'reference, T, P, MAX_SERVICES>
613{
614    async fn request(&self, req: AttReq<'_>) -> Result<Response<P::Packet>, BleHostError<T::Error>> {
615        let data = Att::Client(AttClient::Request(req));
616
617        self.send_att_data(data).await?;
618
619        let (h, pdu) = self.response_channel.receive().await;
620
621        assert_eq!(h, self.connection.handle());
622        Ok(Response { handle: h, pdu })
623    }
624
625    async fn command(&self, cmd: AttCmd<'_>) -> Result<(), BleHostError<T::Error>> {
626        let data = Att::Client(AttClient::Command(cmd));
627
628        self.send_att_data(data).await?;
629
630        Ok(())
631    }
632}
633
634impl<'reference, T: Controller, P: PacketPool, const MAX_SERVICES: usize> GattClient<'reference, T, P, MAX_SERVICES> {
635    async fn send_att_data(&self, data: Att<'_>) -> Result<(), BleHostError<T::Error>> {
636        let header = L2capHeader {
637            channel: crate::types::l2cap::L2CAP_CID_ATT,
638            length: data.size() as u16,
639        };
640
641        let mut buf = P::allocate().ok_or(Error::OutOfMemory)?;
642        let mut w = WriteCursor::new(buf.as_mut());
643        w.write_hci(&header)?;
644        w.write(data)?;
645        let len = w.len();
646
647        self.connection.send(Pdu::new(buf, len)).await;
648        Ok(())
649    }
650}
651
652impl<'reference, C: Controller, P: PacketPool, const MAX_SERVICES: usize> GattClient<'reference, C, P, MAX_SERVICES> {
653    pub async fn new(
655        stack: &'reference Stack<'reference, C, P>,
656        connection: &Connection<'reference, P>,
657    ) -> Result<GattClient<'reference, C, P, MAX_SERVICES>, BleHostError<C::Error>> {
658        let l2cap = L2capHeader { channel: 4, length: 3 };
659        let mut buf = P::allocate().ok_or(Error::OutOfMemory)?;
660        let mut w = WriteCursor::new(buf.as_mut());
661        w.write_hci(&l2cap)?;
662        w.write(att::Att::Client(att::AttClient::Request(att::AttReq::ExchangeMtu {
663            mtu: P::MTU as u16 - 4,
664        })))?;
665
666        let len = w.len();
667        connection.send(Pdu::new(buf, len)).await;
668        Ok(Self {
669            known_services: RefCell::new(heapless::Vec::new()),
670            rx: stack.host.att_client.receiver().into(),
671            stack,
672            connection: connection.clone(),
673
674            response_channel: Channel::new(),
675
676            notifications: PubSubChannel::new(),
677        })
678    }
679
680    pub async fn services_by_uuid(
682        &self,
683        uuid: &Uuid,
684    ) -> Result<Vec<ServiceHandle, MAX_SERVICES>, BleHostError<C::Error>> {
685        let mut start: u16 = 0x0001;
686        let mut result = Vec::new();
687
688        loop {
689            let data = att::AttReq::FindByTypeValue {
690                start_handle: start,
691                end_handle: 0xffff,
692                att_type: PRIMARY_SERVICE.into(),
693                att_value: uuid.as_raw(),
694            };
695
696            let response = self.request(data).await?;
697            let res = Self::response(response.pdu.as_ref())?;
698            match res {
699                AttRsp::Error { request, handle, code } => {
700                    if code == att::AttErrorCode::ATTRIBUTE_NOT_FOUND {
701                        break;
702                    }
703                    return Err(Error::Att(code).into());
704                }
705                AttRsp::FindByTypeValue { mut it } => {
706                    let mut end: u16 = 0;
707                    while let Some(res) = it.next() {
708                        let (handle, e) = res?;
709                        end = e;
710                        let svc = ServiceHandle {
711                            start: handle,
712                            end,
713                            uuid: uuid.clone(),
714                        };
715                        result.push(svc.clone()).map_err(|_| Error::InsufficientSpace)?;
716                        self.known_services
717                            .borrow_mut()
718                            .push(svc)
719                            .map_err(|_| Error::InsufficientSpace)?;
720                    }
721                    if end == 0xFFFF {
722                        break;
723                    }
724                    start = end + 1;
725                }
726                res => {
727                    trace!("[gatt client] response: {:?}", res);
728                    return Err(Error::UnexpectedGattResponse.into());
729                }
730            }
731        }
732
733        Ok(result)
734    }
735
736    pub async fn characteristic_by_uuid<T: AsGatt>(
738        &self,
739        service: &ServiceHandle,
740        uuid: &Uuid,
741    ) -> Result<Characteristic<T>, BleHostError<C::Error>> {
742        let mut start: u16 = service.start;
743        loop {
744            let data = att::AttReq::ReadByType {
745                start,
746                end: service.end,
747                attribute_type: CHARACTERISTIC.into(),
748            };
749            let response = self.request(data).await?;
750
751            match Self::response(response.pdu.as_ref())? {
752                AttRsp::ReadByType { mut it } => {
753                    while let Some(Ok((handle, item))) = it.next() {
754                        let expected_items_len = 5;
755                        let item_len = item.len();
756
757                        if item_len < expected_items_len {
758                            return Err(Error::MalformedCharacteristicDeclaration {
759                                expected: expected_items_len,
760                                actual: item_len,
761                            }
762                            .into());
763                        }
764                        if let AttributeData::Declaration {
765                            props,
766                            handle,
767                            uuid: decl_uuid,
768                        } = AttributeData::decode_declaration(item)?
769                        {
770                            if *uuid == decl_uuid {
771                                let cccd_handle =
773                                    if props.any(&[CharacteristicProp::Indicate, CharacteristicProp::Notify]) {
774                                        Some(self.get_characteristic_cccd(handle).await?.0)
775                                    } else {
776                                        None
777                                    };
778
779                                return Ok(Characteristic {
780                                    handle,
781                                    cccd_handle,
782                                    phantom: PhantomData,
783                                });
784                            }
785
786                            if handle == 0xFFFF {
787                                return Err(Error::NotFound.into());
788                            }
789                            start = handle + 1;
790                        } else {
791                            return Err(Error::InvalidCharacteristicDeclarationData.into());
792                        }
793                    }
794                }
795                AttRsp::Error { request, handle, code } => return Err(Error::Att(code).into()),
796                _ => {
797                    return Err(Error::UnexpectedGattResponse.into());
798                }
799            }
800        }
801    }
802
803    async fn get_characteristic_cccd(&self, char_handle: u16) -> Result<(u16, CCCD), BleHostError<C::Error>> {
804        let data = att::AttReq::ReadByType {
805            start: char_handle,
806            end: char_handle + 1,
807            attribute_type: CLIENT_CHARACTERISTIC_CONFIGURATION.into(),
808        };
809
810        let response = self.request(data).await?;
811
812        match Self::response(response.pdu.as_ref())? {
813            AttRsp::ReadByType { mut it } => {
814                if let Some(Ok((handle, item))) = it.next() {
815                    if item.is_empty() {
819                        Ok((handle, CCCD(0)))
820                    } else {
821                        Ok((
822                            handle,
823                            CCCD(u16::from_le_bytes(
824                                item.try_into()
825                                    .map_err(|_| Error::InvalidCccdHandleLength(item.len()))?,
826                            )),
827                        ))
828                    }
829                } else {
830                    Err(Error::NotFound.into())
831                }
832            }
833            AttRsp::Error { request, handle, code } => Err(Error::Att(code).into()),
834            _ => Err(Error::UnexpectedGattResponse.into()),
835        }
836    }
837
838    pub async fn read_characteristic<T: AsGatt>(
842        &self,
843        characteristic: &Characteristic<T>,
844        dest: &mut [u8],
845    ) -> Result<usize, BleHostError<C::Error>> {
846        let data = att::AttReq::Read {
847            handle: characteristic.handle,
848        };
849
850        let response = self.request(data).await?;
851
852        match Self::response(response.pdu.as_ref())? {
853            AttRsp::Read { data } => {
854                let to_copy = data.len().min(dest.len());
855                dest[..to_copy].copy_from_slice(&data[..to_copy]);
856                Ok(to_copy)
857            }
858            AttRsp::Error { request, handle, code } => Err(Error::Att(code).into()),
859            _ => Err(Error::UnexpectedGattResponse.into()),
860        }
861    }
862
863    pub async fn read_characteristic_by_uuid(
867        &self,
868        service: &ServiceHandle,
869        uuid: &Uuid,
870        dest: &mut [u8],
871    ) -> Result<usize, BleHostError<C::Error>> {
872        let data = att::AttReq::ReadByType {
873            start: service.start,
874            end: service.end,
875            attribute_type: uuid.clone(),
876        };
877
878        let response = self.request(data).await?;
879
880        match Self::response(response.pdu.as_ref())? {
881            AttRsp::ReadByType { mut it } => {
882                let mut to_copy = 0;
883                if let Some(item) = it.next() {
884                    let (_handle, data) = item?;
885                    to_copy = data.len().min(dest.len());
886                    dest[..to_copy].copy_from_slice(&data[..to_copy]);
887                }
888                Ok(to_copy)
889            }
890            AttRsp::Error { request, handle, code } => Err(Error::Att(code).into()),
891            _ => Err(Error::UnexpectedGattResponse.into()),
892        }
893    }
894
895    pub async fn write_characteristic<T: FromGatt>(
897        &self,
898        handle: &Characteristic<T>,
899        buf: &[u8],
900    ) -> Result<(), BleHostError<C::Error>> {
901        let data = att::AttReq::Write {
902            handle: handle.handle,
903            data: buf,
904        };
905
906        let response = self.request(data).await?;
907        match Self::response(response.pdu.as_ref())? {
908            AttRsp::Write => Ok(()),
909            AttRsp::Error { request, handle, code } => Err(Error::Att(code).into()),
910            _ => Err(Error::UnexpectedGattResponse.into()),
911        }
912    }
913
914    pub async fn write_characteristic_without_response<T: FromGatt>(
916        &self,
917        handle: &Characteristic<T>,
918        buf: &[u8],
919    ) -> Result<(), BleHostError<C::Error>> {
920        let data = att::AttCmd::Write {
921            handle: handle.handle,
922            data: buf,
923        };
924
925        self.command(data).await?;
926
927        Ok(())
928    }
929
930    pub async fn subscribe<T: AsGatt>(
934        &self,
935        characteristic: &Characteristic<T>,
936        indication: bool,
937    ) -> Result<NotificationListener<'_, 512>, BleHostError<C::Error>> {
938        let properties = u16::to_le_bytes(if indication { 0x02 } else { 0x01 });
939
940        let data = att::AttReq::Write {
941            handle: characteristic.cccd_handle.ok_or(Error::NotSupported)?,
942            data: &properties,
943        };
944
945        let response = self.request(data).await?;
947
948        match Self::response(response.pdu.as_ref())? {
949            AttRsp::Write => match self.notifications.dyn_subscriber() {
950                Ok(listener) => Ok(NotificationListener {
951                    listener,
952                    handle: characteristic.handle,
953                }),
954                Err(embassy_sync::pubsub::Error::MaximumSubscribersReached) => {
955                    Err(Error::GattSubscriberLimitReached.into())
956                }
957                Err(_) => Err(Error::Other.into()),
958            },
959            AttRsp::Error { request, handle, code } => Err(Error::Att(code).into()),
960            _ => Err(Error::UnexpectedGattResponse.into()),
961        }
962    }
963
964    pub async fn unsubscribe<T: AsGatt>(
966        &self,
967        characteristic: &Characteristic<T>,
968    ) -> Result<(), BleHostError<C::Error>> {
969        let properties = u16::to_le_bytes(0);
970        let data = att::AttReq::Write {
971            handle: characteristic.cccd_handle.ok_or(Error::NotSupported)?,
972            data: &[0, 0],
973        };
974
975        let response = self.request(data).await?;
977
978        match Self::response(response.pdu.as_ref())? {
979            AttRsp::Write => Ok(()),
980            AttRsp::Error { request, handle, code } => Err(Error::Att(code).into()),
981            _ => Err(Error::UnexpectedGattResponse.into()),
982        }
983    }
984
985    async fn handle_notification_packet(&self, data: &[u8]) -> Result<(), BleHostError<C::Error>> {
987        let mut r = ReadCursor::new(data);
988        let value_handle: u16 = r.read()?;
989        let value_attr = r.remaining();
990
991        let handle = value_handle;
992
993        let mut data = [0u8; 512];
995        let to_copy = data.len().min(value_attr.len());
996        data[..to_copy].copy_from_slice(&value_attr[..to_copy]);
997        let n = Notification {
998            handle,
999            data,
1000            len: to_copy,
1001        };
1002        self.notifications.immediate_publisher().publish_immediate(n);
1003        Ok(())
1004    }
1005
1006    pub async fn task(&self) -> Result<(), BleHostError<C::Error>> {
1008        loop {
1009            let (handle, pdu) = self.rx.receive().await;
1010            let data = pdu.as_ref();
1011            if pdu.as_ref()[0] == ATT_HANDLE_VALUE_NTF {
1013                self.handle_notification_packet(&pdu.as_ref()[1..]).await?;
1014            } else {
1015                self.response_channel.send((handle, pdu)).await;
1016            }
1017        }
1018    }
1019
1020    fn response<'a>(data: &'a [u8]) -> Result<AttRsp<'a>, BleHostError<C::Error>> {
1021        let att = Att::decode(data)?;
1022        match att {
1023            Att::Server(AttServer::Response(rsp)) => Ok(rsp),
1024            _ => Err(Error::UnexpectedGattResponse.into()),
1025        }
1026    }
1027}