Skip to main content

trouble_host/
att.rs

1//! Attribute Protocol (ATT) PDU definitions
2use core::fmt::Display;
3use core::mem;
4
5use crate::codec;
6use crate::cursor::{ReadCursor, WriteCursor};
7use crate::types::uuid::*;
8
9pub(crate) const ATT_READ_BY_GROUP_TYPE_REQ: u8 = 0x10;
10pub(crate) const ATT_READ_BY_GROUP_TYPE_RSP: u8 = 0x11;
11pub(crate) const ATT_ERROR_RSP: u8 = 0x01;
12pub(crate) const ATT_READ_BY_TYPE_REQ: u8 = 0x08;
13pub(crate) const ATT_READ_BY_TYPE_RSP: u8 = 0x09;
14pub(crate) const ATT_READ_REQ: u8 = 0x0a;
15pub(crate) const ATT_READ_RSP: u8 = 0x0b;
16pub(crate) const ATT_WRITE_REQ: u8 = 0x12;
17pub(crate) const ATT_WRITE_CMD: u8 = 0x52;
18pub(crate) const ATT_WRITE_RSP: u8 = 0x13;
19pub(crate) const ATT_EXCHANGE_MTU_REQ: u8 = 0x02;
20pub(crate) const ATT_EXCHANGE_MTU_RSP: u8 = 0x03;
21pub(crate) const ATT_FIND_BY_TYPE_VALUE_REQ: u8 = 0x06;
22pub(crate) const ATT_FIND_BY_TYPE_VALUE_RSP: u8 = 0x07;
23pub(crate) const ATT_FIND_INFORMATION_REQ: u8 = 0x04;
24pub(crate) const ATT_FIND_INFORMATION_RSP: u8 = 0x05;
25pub(crate) const ATT_PREPARE_WRITE_REQ: u8 = 0x16;
26pub(crate) const ATT_PREPARE_WRITE_RSP: u8 = 0x17;
27pub(crate) const ATT_EXECUTE_WRITE_REQ: u8 = 0x18;
28pub(crate) const ATT_EXECUTE_WRITE_RSP: u8 = 0x19;
29pub(crate) const ATT_READ_MULTIPLE_REQ: u8 = 0x20;
30pub(crate) const ATT_READ_MULTIPLE_RSP: u8 = 0x21;
31pub(crate) const ATT_READ_BLOB_REQ: u8 = 0x0c;
32pub(crate) const ATT_READ_BLOB_RSP: u8 = 0x0d;
33pub(crate) const ATT_HANDLE_VALUE_NTF: u8 = 0x1b;
34pub(crate) const ATT_HANDLE_VALUE_IND: u8 = 0x1d;
35pub(crate) const ATT_HANDLE_VALUE_CFM: u8 = 0x1e;
36
37/// Attribute Error Code
38///
39/// This enum type describes the `ATT_ERROR_RSP` PDU from the Bluetooth Core Specification
40/// Version 6.0 | Vol 3, Part F (page 1491)
41/// See also: Core Specification Supplement, Part B: Common Profile and Service Error Codes
42#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43#[derive(Debug, PartialEq, Eq, Clone, Copy)]
44pub struct AttErrorCode {
45    value: u8,
46}
47
48impl AttErrorCode {
49    /// Attempted to use a handle that isn't valid on this server
50    pub const INVALID_HANDLE: Self = Self { value: 0x01 };
51    /// The attribute cannot be read
52    pub const READ_NOT_PERMITTED: Self = Self { value: 0x02 };
53    /// The attribute cannot be written due to permissions
54    pub const WRITE_NOT_PERMITTED: Self = Self { value: 0x03 };
55    /// The attribute PDU was invalid
56    pub const INVALID_PDU: Self = Self { value: 0x04 };
57    /// The attribute requires authentication before it can be read or written
58    pub const INSUFFICIENT_AUTHENTICATION: Self = Self { value: 0x05 };
59    /// ATT Server does not support the request received from the client
60    pub const REQUEST_NOT_SUPPORTED: Self = Self { value: 0x06 };
61    /// Offset specified was past the end of the attribute
62    pub const INVALID_OFFSET: Self = Self { value: 0x07 };
63    /// The attribute requires authorisation before it can be read or written
64    pub const INSUFFICIENT_AUTHORISATION: Self = Self { value: 0x08 };
65    /// Too many prepare writes have been queued
66    pub const PREPARE_QUEUE_FULL: Self = Self { value: 0x09 };
67    /// No attribute found within the given attribute handle range
68    pub const ATTRIBUTE_NOT_FOUND: Self = Self { value: 0x0a };
69    /// The attribute cannot be read using the ATT_READ_BLOB_REQ PDU
70    pub const ATTRIBUTE_NOT_LONG: Self = Self { value: 0x0b };
71    /// The Encryption Key Size used for encrypting this link is too short
72    pub const INSUFFICIENT_ENCRYPTION_KEY_SIZE: Self = Self { value: 0x0c };
73    /// The attribute value length is invalid for the operation
74    pub const INVALID_ATTRIBUTE_VALUE_LENGTH: Self = Self { value: 0x0d };
75    /// The attribute request that was requested had encountered an error that was unlikely, and therefore could not be completed as requested
76    pub const UNLIKELY_ERROR: Self = Self { value: 0x0e };
77    /// The attribute requires encryption before it can be read or written
78    pub const INSUFFICIENT_ENCRYPTION: Self = Self { value: 0x0f };
79    /// The attribute type is not a supported grouping attribute as defined by a higher layer specification
80    pub const UNSUPPORTED_GROUP_TYPE: Self = Self { value: 0x10 };
81    /// Insufficient Resources to complete the request
82    pub const INSUFFICIENT_RESOURCES: Self = Self { value: 0x11 };
83    /// The server requests the client to rediscover the database
84    pub const DATABASE_OUT_OF_SYNC: Self = Self { value: 0x12 };
85    /// The attribute parameter value was not allowed
86    pub const VALUE_NOT_ALLOWED: Self = Self { value: 0x13 };
87
88    /// Common profile and service error codes
89    /// The write request could not be fulfilled for reasons other than permissions
90    pub const WRITE_REQUEST_REJECTED: Self = Self { value: 0xFC };
91    /// The client characteristic configuration descriptor (CCCD) is not configured according to the requirements of the profile or service
92    pub const CCCD_IMPROPERLY_CONFIGURED: Self = Self { value: 0xFD };
93    /// The profile or service request could not be serviced because an operation that has been previousl triggered is still in progress
94    pub const PROCEDURE_ALREADY_IN_PROGRESS: Self = Self { value: 0xFE };
95    /// The attribute value is out of range as defined by a profile or service specification
96    pub const OUT_OF_RANGE: Self = Self { value: 0xFF };
97
98    /// Create a new error code from a raw value
99    pub const fn new(value: u8) -> Self {
100        Self { value }
101    }
102
103    /// Get the raw value of this error code
104    pub const fn to_u8(self) -> u8 {
105        self.value
106    }
107}
108
109impl Display for AttErrorCode {
110    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
111        match self {
112            &Self::INVALID_HANDLE => {
113                f.write_str("invalid handle: Attempted to use a handle that isn't valid on this server")
114            }
115            &Self::READ_NOT_PERMITTED => f.write_str("read not permitted: the attribute cannot be read"),
116            &Self::WRITE_NOT_PERMITTED => f.write_str("write not permitted: the attribute cannot be written due to permissions"),
117            &Self::INVALID_PDU => f.write_str("invalid pdu: the attribute PDU was invalid"),
118            &Self::INSUFFICIENT_AUTHENTICATION => f.write_str(
119                "insufficient authentication: the attribute requires authentication before it can be written",
120            ),
121            &Self::REQUEST_NOT_SUPPORTED => {
122                f.write_str("request not supported: ATT server does not support the request received from the client")
123            }
124            &Self::INVALID_OFFSET => f.write_str("Offset specified was past the end of the attribute"),
125            &Self::INSUFFICIENT_AUTHORISATION => f.write_str(
126                "insufficient authorisation: the attribute requires authorisation before it can be read or written",
127            ),
128            &Self::PREPARE_QUEUE_FULL => f.write_str("prepare queue full: too many prepare writes have been queued"),
129            &Self::ATTRIBUTE_NOT_FOUND => f.write_str("attribute not found: no attribute found within the given attribute handle range"),
130            &Self::ATTRIBUTE_NOT_LONG => f.write_str("The attribute cannot be read using the ATT_READ_BLOB_REQ PDU"),
131            &Self::INSUFFICIENT_ENCRYPTION_KEY_SIZE => f.write_str("insufficient encryption key size: the encryption key size used for encrypting this link is too short"),
132            &Self::INVALID_ATTRIBUTE_VALUE_LENGTH => f.write_str("invalid attribute value length: the attribute value length is invalid for the operation"),
133            &Self::UNLIKELY_ERROR => f.write_str("unlikely error: the attribute request encountered an error that was unlikely, and therefore could not be completed"),
134            &Self::INSUFFICIENT_ENCRYPTION => f.write_str("insufficient encryption: the attribute requires encryption before it can be read or written"),
135            &Self::UNSUPPORTED_GROUP_TYPE => f.write_str("unsupported group type: the attribute type is not a supported grouping attribute as defined by a higher layer specification"),
136            &Self::INSUFFICIENT_RESOURCES => f.write_str("insufficient resources: insufficient resources to complete the request"),
137            &Self::DATABASE_OUT_OF_SYNC => f.write_str("the server requests the client to rediscover the database"),
138            &Self::VALUE_NOT_ALLOWED => f.write_str("value not allowed: the attribute parameter value was not allowed"),
139
140            &Self{value: 0x80..=0x9F} => write!(f, "application error code {}: check the application documentation of the device which produced this error code", self.value),
141
142            &Self::WRITE_REQUEST_REJECTED => f.write_str("write request rejected: the write request could not be fulfilled for reasons other than permissions"),
143            &Self::CCCD_IMPROPERLY_CONFIGURED => f.write_str("CCCD improperly configured: the client characteristic configuration descriptor (CCCD) is not configured according to the requirements of the profile or service"),
144            &Self::PROCEDURE_ALREADY_IN_PROGRESS => f.write_str("procedure already in progress: the profile or service request could not be serviced because an operation that has been previousl triggered is still in progress"),
145            &Self::OUT_OF_RANGE => f.write_str("out of range: the attribute value is out of range as defined by a profile or service specification"),
146
147            other => write!(f, "unknown error code {other}: check the most recent bluetooth spec"),
148        }
149    }
150}
151
152impl codec::Encode for AttErrorCode {
153    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
154        dest[0] = self.value;
155        Ok(())
156    }
157}
158
159impl codec::Decode<'_> for AttErrorCode {
160    fn decode(src: &[u8]) -> Result<Self, codec::Error> {
161        Ok(Self { value: src[0] })
162    }
163}
164
165impl codec::Type for AttErrorCode {
166    fn size(&self) -> usize {
167        mem::size_of::<u8>()
168    }
169}
170
171/// ATT Client PDU (Request, Command, Confirmation)
172///
173/// The ATT Client PDU is used to send requests, commands and confirmations to the ATT Server
174#[cfg_attr(feature = "defmt", derive(defmt::Format))]
175#[derive(Debug)]
176pub enum AttClient<'d> {
177    /// ATT Request PDU
178    Request(AttReq<'d>),
179    /// ATT Command PDU
180    Command(AttCmd<'d>),
181    /// ATT Confirmation PDU
182    Confirmation(AttCfm),
183}
184
185/// ATT Request PDU
186#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187#[derive(Debug)]
188pub enum AttReq<'d> {
189    /// Read By Group Type Request
190    ReadByGroupType {
191        /// Start attribute handle
192        start: u16,
193        /// End attribute handle
194        end: u16,
195        /// Group type
196        group_type: Uuid,
197    },
198    /// Read By Type Request
199    ReadByType {
200        /// Start attribute handle
201        start: u16,
202        /// End attribute handle
203        end: u16,
204        /// Attribute type
205        attribute_type: Uuid,
206    },
207    /// Read Request
208    Read {
209        /// Attribute handle
210        handle: u16,
211    },
212    /// Write Request
213    Write {
214        /// Attribute handle
215        handle: u16,
216        /// Attribute value
217        data: &'d [u8],
218    },
219    /// Exchange MTU Request
220    ExchangeMtu {
221        /// Client MTU
222        mtu: u16,
223    },
224    /// Find By Type Value Request
225    FindByTypeValue {
226        /// Start attribute handle
227        start_handle: u16,
228        /// End attribute handle
229        end_handle: u16,
230        /// Attribute type
231        att_type: u16,
232        /// Attribute value
233        att_value: &'d [u8],
234    },
235    /// Find Information Request
236    FindInformation {
237        /// Start attribute handle
238        start_handle: u16,
239        /// End attribute handle
240        end_handle: u16,
241    },
242    /// Prepare Write Request
243    PrepareWrite {
244        /// Attribute handle
245        handle: u16,
246        /// Attribute offset
247        offset: u16,
248        /// Attribute value
249        value: &'d [u8],
250    },
251    /// Execute Write Request
252    ExecuteWrite {
253        /// Flags
254        flags: u8,
255    },
256    /// Read Multiple Request
257    ReadMultiple {
258        /// Attribute handles
259        handles: &'d [u8],
260    },
261    /// Read Blob Request
262    ReadBlob {
263        /// Attribute handle
264        handle: u16,
265        /// Attribute offset
266        offset: u16,
267    },
268}
269
270/// ATT Command PDU
271#[cfg_attr(feature = "defmt", derive(defmt::Format))]
272#[derive(Debug)]
273pub enum AttCmd<'d> {
274    /// Write Command
275    Write {
276        /// Attribute handle
277        handle: u16,
278        /// Attribute value
279        data: &'d [u8],
280    },
281}
282
283/// ATT Confirmation PDU
284#[cfg_attr(feature = "defmt", derive(defmt::Format))]
285#[derive(Debug)]
286pub enum AttCfm {
287    /// Confirm Indication
288    ConfirmIndication,
289}
290
291/// ATT Server PDU (Response, Unsolicited)
292#[cfg_attr(feature = "defmt", derive(defmt::Format))]
293#[derive(Debug)]
294pub enum AttServer<'d> {
295    /// ATT Response PDU
296    Response(AttRsp<'d>),
297    /// ATT Unsolicited PDU
298    Unsolicited(AttUns<'d>),
299}
300
301/// ATT Response PDU
302#[cfg_attr(feature = "defmt", derive(defmt::Format))]
303#[derive(Debug)]
304pub enum AttRsp<'d> {
305    /// Exchange MTU Response
306    ExchangeMtu {
307        /// Server MTU
308        mtu: u16,
309    },
310    /// Find By Type Value Response
311    FindByTypeValue {
312        /// Iterator over the found handles
313        it: FindByTypeValueIter<'d>,
314    },
315    /// Find Information Response
316    FindInformation {
317        /// Iterator over the found handles and UUIDs
318        it: FindInformationIter<'d>,
319    },
320    /// Error Response
321    Error {
322        /// Request opcode
323        request: u8,
324        /// Attribute handle
325        handle: u16,
326        /// Error code
327        code: AttErrorCode,
328    },
329    /// Read by Type Response
330    ReadByType {
331        /// Iterator over the found handles
332        it: ReadByTypeIter<'d>,
333    },
334    /// Read by Group Type Response
335    ReadByGroupType {
336        /// Iterator over the found handles
337        it: ReadByTypeIter<'d>,
338    },
339    /// Read Response
340    Read {
341        /// Attribute value
342        data: &'d [u8],
343    },
344    /// Read Blob Response
345    ReadBlob {
346        /// Attribute value part
347        data: &'d [u8],
348    },
349    /// Write Response
350    Write,
351}
352
353/// ATT Unsolicited PDU
354#[cfg_attr(feature = "defmt", derive(defmt::Format))]
355#[derive(Debug)]
356pub enum AttUns<'d> {
357    /// Notify
358    Notify {
359        /// Attribute handle
360        handle: u16,
361        /// Attribute value
362        data: &'d [u8],
363    },
364    /// Indicate
365    Indicate {
366        /// Attribute handle
367        handle: u16,
368        /// Attribute value
369        data: &'d [u8],
370    },
371}
372
373/// ATT Protocol Data Unit (PDU)
374#[cfg_attr(feature = "defmt", derive(defmt::Format))]
375#[derive(Debug)]
376pub enum Att<'d> {
377    /// ATT Client PDU (Request, Command, Confirmation)
378    ///
379    /// The ATT Client PDU is used to send requests, commands and confirmations to the ATT Server
380    Client(AttClient<'d>),
381    /// ATT Server PDU (Response, Unsolicited)
382    ///
383    /// The ATT Server PDU is used to send responses and unsolicited ATT PDUs (notifications and indications) to the ATT Client
384    Server(AttServer<'d>),
385}
386
387/// An Iterator-like type for iterating over the found handles
388#[cfg_attr(feature = "defmt", derive(defmt::Format))]
389#[derive(Clone, Debug)]
390pub struct FindByTypeValueIter<'d> {
391    cursor: ReadCursor<'d>,
392}
393
394impl FindByTypeValueIter<'_> {
395    /// Get the next pair of start and end attribute handles
396    #[allow(clippy::should_implement_trait)]
397    pub fn next(&mut self) -> Option<Result<(u16, u16), crate::Error>> {
398        if self.cursor.available() >= 4 {
399            let res = (|| {
400                let handle: u16 = self.cursor.read()?;
401                let end: u16 = self.cursor.read()?;
402                Ok((handle, end))
403            })();
404            Some(res)
405        } else {
406            None
407        }
408    }
409}
410
411/// An Iterator-like type for iterating over the found handles
412#[cfg_attr(feature = "defmt", derive(defmt::Format))]
413#[derive(Clone, Debug)]
414pub struct ReadByTypeIter<'d> {
415    item_len: usize,
416    cursor: ReadCursor<'d>,
417}
418
419impl<'d> ReadByTypeIter<'d> {
420    /// Get the next pair of attribute handle and attribute data
421    #[allow(clippy::should_implement_trait)]
422    pub fn next(&mut self) -> Option<Result<(u16, &'d [u8]), crate::Error>> {
423        if self.cursor.available() >= self.item_len {
424            let res = (|| {
425                let handle: u16 = self.cursor.read()?;
426                let item = self.cursor.slice(self.item_len - 2)?;
427                Ok((handle, item))
428            })();
429            Some(res)
430        } else {
431            None
432        }
433    }
434}
435
436#[cfg_attr(feature = "defmt", derive(defmt::Format))]
437#[derive(Debug, Copy, Clone)]
438enum FindInformationUuidFormat {
439    Uuid16 = 1,
440    Uuid128 = 2,
441}
442
443impl FindInformationUuidFormat {
444    fn num_bytes(self) -> usize {
445        match self {
446            Self::Uuid16 => 2,
447            Self::Uuid128 => 16,
448        }
449    }
450
451    fn from(format: u8) -> Result<Self, codec::Error> {
452        match format {
453            1 => Ok(Self::Uuid16),
454            2 => Ok(Self::Uuid128),
455            _ => Err(codec::Error::InvalidValue),
456        }
457    }
458}
459
460/// An Iterator-like type for iterating over the handle/UUID pairs in a Find Information Response
461#[cfg_attr(feature = "defmt", derive(defmt::Format))]
462#[derive(Clone, Debug)]
463pub struct FindInformationIter<'d> {
464    /// Format type: 1 = 16-bit UUIDs, 2 = 128-bit UUIDs
465    format: FindInformationUuidFormat,
466    cursor: ReadCursor<'d>,
467}
468
469impl<'d> FindInformationIter<'d> {
470    /// Get the next pair of attribute handle and UUID
471    #[allow(clippy::should_implement_trait)]
472    pub fn next(&mut self) -> Option<Result<(u16, Uuid), crate::Error>> {
473        let uuid_len = self.format.num_bytes();
474
475        if self.cursor.available() >= 2 + uuid_len {
476            let res = (|| {
477                let handle: u16 = self.cursor.read()?;
478                let uuid = Uuid::try_from(self.cursor.slice(uuid_len)?)?;
479                Ok((handle, uuid))
480            })();
481            Some(res)
482        } else {
483            None
484        }
485    }
486}
487
488impl<'d> AttServer<'d> {
489    fn size(&self) -> usize {
490        match self {
491            Self::Response(rsp) => rsp.size(),
492            Self::Unsolicited(uns) => uns.size(),
493        }
494    }
495
496    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
497        match self {
498            Self::Response(rsp) => rsp.encode(dest),
499            Self::Unsolicited(uns) => uns.encode(dest),
500        }
501    }
502
503    fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
504        let decoded = match opcode {
505            ATT_HANDLE_VALUE_NTF | ATT_HANDLE_VALUE_IND => Self::Unsolicited(AttUns::decode_with_opcode(opcode, r)?),
506            _ => Self::Response(AttRsp::decode_with_opcode(opcode, r)?),
507        };
508        Ok(decoded)
509    }
510}
511
512impl<'d> AttRsp<'d> {
513    fn size(&self) -> usize {
514        1 + match self {
515            Self::ExchangeMtu { mtu: u16 } => 2,
516            Self::FindByTypeValue { it } => it.cursor.len(),
517            Self::FindInformation { it } => 1 + it.cursor.len(), // 1 for format byte
518            Self::Error { .. } => 4,
519            Self::Read { data } => data.len(),
520            Self::ReadBlob { data } => data.len(),
521            Self::ReadByType { it } => it.cursor.len(),
522            Self::ReadByGroupType { it } => it.cursor.len(),
523            Self::Write => 0,
524        }
525    }
526
527    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
528        let mut w = WriteCursor::new(dest);
529        match self {
530            Self::ExchangeMtu { mtu } => {
531                w.write(ATT_EXCHANGE_MTU_RSP)?;
532                w.write(*mtu)?;
533            }
534            Self::FindByTypeValue { it } => {
535                w.write(ATT_FIND_BY_TYPE_VALUE_RSP)?;
536                let mut it = it.clone();
537                while let Some(Ok((start, end))) = it.next() {
538                    w.write(start)?;
539                    w.write(end)?;
540                }
541            }
542            Self::FindInformation { it } => {
543                w.write(ATT_FIND_INFORMATION_RSP)?;
544                w.write(it.format as u8)?;
545                let mut it = it.clone();
546                while let Some(Ok((handle, uuid))) = it.next() {
547                    w.write(handle)?;
548                    w.append(uuid.as_raw())?;
549                }
550            }
551            Self::Error { request, handle, code } => {
552                w.write(ATT_ERROR_RSP)?;
553                w.write(*request)?;
554                w.write(*handle)?;
555                w.write(*code)?;
556            }
557            Self::ReadByType { it } => {
558                w.write(ATT_READ_BY_TYPE_RSP)?;
559                w.write(it.item_len as u8)?;
560                let mut it = it.clone();
561                while let Some(Ok((handle, item))) = it.next() {
562                    w.write(handle)?;
563                    w.append(item)?;
564                }
565            }
566            Self::ReadByGroupType { it } => {
567                w.write(ATT_READ_BY_GROUP_TYPE_RSP)?;
568                w.write(it.item_len as u8)?;
569                let mut it = it.clone();
570                while let Some(Ok((handle, item))) = it.next() {
571                    w.write(handle)?;
572                    w.append(item)?;
573                }
574            }
575            Self::Read { data } => {
576                w.write(ATT_READ_RSP)?;
577                w.append(data)?;
578            }
579            Self::ReadBlob { data } => {
580                w.write(ATT_READ_BLOB_RSP)?;
581                w.append(data)?;
582            }
583            Self::Write => {
584                w.write(ATT_WRITE_RSP)?;
585            }
586        }
587        Ok(())
588    }
589
590    fn decode_with_opcode(opcode: u8, mut r: ReadCursor<'d>) -> Result<Self, codec::Error> {
591        match opcode {
592            ATT_FIND_BY_TYPE_VALUE_RSP => Ok(Self::FindByTypeValue {
593                it: FindByTypeValueIter { cursor: r },
594            }),
595            ATT_FIND_INFORMATION_RSP => Ok(Self::FindInformation {
596                it: FindInformationIter {
597                    format: FindInformationUuidFormat::from(r.read()?)?,
598                    cursor: r,
599                },
600            }),
601            ATT_EXCHANGE_MTU_RSP => {
602                let mtu: u16 = r.read()?;
603                Ok(Self::ExchangeMtu { mtu })
604            }
605            ATT_ERROR_RSP => {
606                let request = r.read()?;
607                let handle = r.read()?;
608                let code = r.read()?;
609                Ok(Self::Error { request, handle, code })
610            }
611            ATT_READ_RSP => Ok(Self::Read { data: r.remaining() }),
612            ATT_READ_BLOB_RSP => Ok(Self::ReadBlob { data: r.remaining() }),
613            ATT_READ_BY_TYPE_RSP => {
614                let item_len: u8 = r.read()?;
615                Ok(Self::ReadByType {
616                    it: ReadByTypeIter {
617                        item_len: item_len as usize,
618                        cursor: r,
619                    },
620                })
621            }
622            ATT_READ_BY_GROUP_TYPE_RSP => {
623                let item_len: u8 = r.read()?;
624                Ok(Self::ReadByGroupType {
625                    it: ReadByTypeIter {
626                        item_len: item_len as usize,
627                        cursor: r,
628                    },
629                })
630            }
631            ATT_WRITE_RSP => Ok(Self::Write),
632            _ => Err(codec::Error::InvalidValue),
633        }
634    }
635}
636
637impl<'d> AttUns<'d> {
638    fn size(&self) -> usize {
639        1 + match self {
640            Self::Notify { data, .. } => 2 + data.len(),
641            Self::Indicate { data, .. } => 2 + data.len(),
642        }
643    }
644
645    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
646        let mut w = WriteCursor::new(dest);
647        match self {
648            Self::Notify { handle, data } => {
649                w.write(ATT_HANDLE_VALUE_NTF)?;
650                w.write(*handle)?;
651                w.append(data)?;
652            }
653            Self::Indicate { handle, data } => {
654                w.write(ATT_HANDLE_VALUE_IND)?;
655                w.write(*handle)?;
656                w.append(data)?;
657            }
658        }
659        Ok(())
660    }
661
662    fn decode_with_opcode(opcode: u8, mut r: ReadCursor<'d>) -> Result<Self, codec::Error> {
663        match opcode {
664            ATT_HANDLE_VALUE_NTF => {
665                let handle = r.read()?;
666                Ok(Self::Notify {
667                    handle,
668                    data: r.remaining(),
669                })
670            }
671            ATT_HANDLE_VALUE_IND => {
672                let handle = r.read()?;
673                Ok(Self::Indicate {
674                    handle,
675                    data: r.remaining(),
676                })
677            }
678            _ => Err(codec::Error::InvalidValue),
679        }
680    }
681}
682
683impl<'d> AttClient<'d> {
684    fn size(&self) -> usize {
685        match self {
686            Self::Request(req) => req.size(),
687            Self::Command(cmd) => cmd.size(),
688            Self::Confirmation(cfm) => cfm.size(),
689        }
690    }
691
692    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
693        match self {
694            Self::Request(req) => req.encode(dest),
695            Self::Command(cmd) => cmd.encode(dest),
696            Self::Confirmation(cfm) => cfm.encode(dest),
697        }
698    }
699
700    fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
701        let decoded = match opcode {
702            ATT_WRITE_CMD => Self::Command(AttCmd::decode_with_opcode(opcode, r)?),
703            ATT_HANDLE_VALUE_CFM => Self::Confirmation(AttCfm::decode_with_opcode(opcode, r)?),
704            _ => Self::Request(AttReq::decode_with_opcode(opcode, r)?),
705        };
706        Ok(decoded)
707    }
708}
709
710impl<'d> AttReq<'d> {
711    fn size(&self) -> usize {
712        1 + match self {
713            Self::ExchangeMtu { .. } => 2,
714            Self::FindByTypeValue {
715                start_handle,
716                end_handle,
717                att_type,
718                att_value,
719            } => 6 + att_value.len(),
720            Self::FindInformation {
721                start_handle,
722                end_handle,
723            } => 4,
724            Self::ReadByType {
725                start,
726                end,
727                attribute_type,
728            } => 4 + attribute_type.as_raw().len(),
729            Self::ReadByGroupType { group_type, .. } => 4 + group_type.as_raw().len(),
730            Self::Read { .. } => 2,
731            Self::ReadBlob { .. } => 4, // handle (2 bytes) + offset (2 bytes)
732            Self::Write { handle, data } => 2 + data.len(),
733            _ => unimplemented!(),
734        }
735    }
736    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
737        let mut w = WriteCursor::new(dest);
738        match self {
739            Self::ExchangeMtu { mtu } => {
740                w.write(ATT_EXCHANGE_MTU_REQ)?;
741                w.write(*mtu)?;
742            }
743            Self::FindByTypeValue {
744                start_handle,
745                end_handle,
746                att_type,
747                att_value,
748            } => {
749                w.write(ATT_FIND_BY_TYPE_VALUE_REQ)?;
750                w.write(*start_handle)?;
751                w.write(*end_handle)?;
752                w.write(*att_type)?;
753                w.append(att_value)?;
754            }
755            Self::FindInformation {
756                start_handle,
757                end_handle,
758            } => {
759                w.write(ATT_FIND_INFORMATION_REQ)?;
760                w.write(*start_handle)?;
761                w.write(*end_handle)?;
762            }
763            Self::ReadByType {
764                start,
765                end,
766                attribute_type,
767            } => {
768                w.write(ATT_READ_BY_TYPE_REQ)?;
769                w.write(*start)?;
770                w.write(*end)?;
771                w.write_ref(attribute_type)?;
772            }
773            Self::ReadByGroupType { start, end, group_type } => {
774                w.write(ATT_READ_BY_GROUP_TYPE_REQ)?;
775                w.write(*start)?;
776                w.write(*end)?;
777                w.write_ref(group_type)?;
778            }
779            Self::Read { handle } => {
780                w.write(ATT_READ_REQ)?;
781                w.write(*handle)?;
782            }
783            Self::ReadBlob { handle, offset } => {
784                w.write(ATT_READ_BLOB_REQ)?;
785                w.write(*handle)?;
786                w.write(*offset)?;
787            }
788            Self::Write { handle, data } => {
789                w.write(ATT_WRITE_REQ)?;
790                w.write(*handle)?;
791                w.append(data)?;
792            }
793            _ => unimplemented!(),
794        }
795        Ok(())
796    }
797
798    fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
799        let payload = r.remaining();
800        match opcode {
801            ATT_READ_BY_GROUP_TYPE_REQ => {
802                let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
803                let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
804
805                let group_type = if payload.len() == 6 {
806                    Uuid::Uuid16([payload[4], payload[5]])
807                } else if payload.len() == 20 {
808                    let uuid = payload[4..21].try_into().map_err(|_| codec::Error::InvalidValue)?;
809                    Uuid::Uuid128(uuid)
810                } else {
811                    return Err(codec::Error::InvalidValue);
812                };
813
814                Ok(Self::ReadByGroupType {
815                    start: start_handle,
816                    end: end_handle,
817                    group_type,
818                })
819            }
820            ATT_READ_BY_TYPE_REQ => {
821                let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
822                let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
823
824                let attribute_type = if payload.len() == 6 {
825                    Uuid::Uuid16([payload[4], payload[5]])
826                } else if payload.len() == 20 {
827                    let uuid = payload[4..20].try_into().map_err(|_| codec::Error::InvalidValue)?;
828                    Uuid::Uuid128(uuid)
829                } else {
830                    return Err(codec::Error::InvalidValue);
831                };
832
833                Ok(Self::ReadByType {
834                    start: start_handle,
835                    end: end_handle,
836                    attribute_type,
837                })
838            }
839            ATT_READ_REQ => {
840                let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
841
842                Ok(Self::Read { handle })
843            }
844            ATT_WRITE_REQ => {
845                let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
846                let data = &payload[2..];
847
848                Ok(Self::Write { handle, data })
849            }
850            ATT_EXCHANGE_MTU_REQ => {
851                let mtu = (payload[0] as u16) + ((payload[1] as u16) << 8);
852                Ok(Self::ExchangeMtu { mtu })
853            }
854            ATT_FIND_BY_TYPE_VALUE_REQ => {
855                let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
856                let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
857                let att_type = (payload[4] as u16) + ((payload[5] as u16) << 8);
858                let att_value = &payload[6..];
859
860                Ok(Self::FindByTypeValue {
861                    start_handle,
862                    end_handle,
863                    att_type,
864                    att_value,
865                })
866            }
867            ATT_FIND_INFORMATION_REQ => {
868                let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
869                let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
870
871                Ok(Self::FindInformation {
872                    start_handle,
873                    end_handle,
874                })
875            }
876            ATT_PREPARE_WRITE_REQ => {
877                let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
878                let offset = (payload[2] as u16) + ((payload[3] as u16) << 8);
879                Ok(Self::PrepareWrite {
880                    handle,
881                    offset,
882                    value: &payload[4..],
883                })
884            }
885            ATT_EXECUTE_WRITE_REQ => {
886                let flags = payload[0];
887                Ok(Self::ExecuteWrite { flags })
888            }
889            ATT_READ_MULTIPLE_REQ => Ok(Self::ReadMultiple { handles: payload }),
890            ATT_READ_BLOB_REQ => {
891                let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
892                let offset = (payload[2] as u16) + ((payload[3] as u16) << 8);
893                Ok(Self::ReadBlob { handle, offset })
894            }
895            code => {
896                warn!("[att] unknown opcode {:x}", code);
897                Err(codec::Error::InvalidValue)
898            }
899        }
900    }
901}
902
903impl<'d> AttCmd<'d> {
904    fn size(&self) -> usize {
905        1 + match self {
906            Self::Write { handle, data } => 2 + data.len(),
907        }
908    }
909
910    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
911        let mut w = WriteCursor::new(dest);
912        match self {
913            Self::Write { handle, data } => {
914                w.write(ATT_WRITE_CMD)?;
915                w.write(*handle)?;
916                w.append(data)?;
917            }
918        }
919        Ok(())
920    }
921
922    fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
923        let payload = r.remaining();
924        match opcode {
925            ATT_WRITE_CMD => {
926                let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
927                let data = &payload[2..];
928
929                Ok(Self::Write { handle, data })
930            }
931            code => {
932                warn!("[att] unknown opcode {:x}", code);
933                Err(codec::Error::InvalidValue)
934            }
935        }
936    }
937}
938
939impl AttCfm {
940    fn size(&self) -> usize {
941        1
942    }
943
944    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
945        let mut w = WriteCursor::new(dest);
946        match self {
947            Self::ConfirmIndication => {
948                w.write(ATT_HANDLE_VALUE_CFM)?;
949            }
950        }
951        Ok(())
952    }
953
954    fn decode_with_opcode(opcode: u8, r: ReadCursor<'_>) -> Result<Self, codec::Error> {
955        let payload = r.remaining();
956        match opcode {
957            ATT_HANDLE_VALUE_CFM => Ok(Self::ConfirmIndication),
958            code => {
959                warn!("[att] unknown opcode {:x}", code);
960                Err(codec::Error::InvalidValue)
961            }
962        }
963    }
964}
965
966impl<'d> Att<'d> {
967    /// Get the wire-size of the ATT PDU
968    pub fn size(&self) -> usize {
969        match self {
970            Self::Client(client) => client.size(),
971            Self::Server(server) => server.size(),
972        }
973    }
974
975    /// Encode the ATT PDU into a byte buffer
976    pub fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
977        match self {
978            Self::Client(client) => client.encode(dest),
979            Self::Server(server) => server.encode(dest),
980        }
981    }
982
983    /// Decode an ATT PDU from a byte buffer
984    pub fn decode(data: &'d [u8]) -> Result<Att<'d>, codec::Error> {
985        let mut r = ReadCursor::new(data);
986        let opcode: u8 = r.read()?;
987        if opcode.is_multiple_of(2) {
988            let client = AttClient::decode_with_opcode(opcode, r)?;
989            Ok(Att::Client(client))
990        } else {
991            let server = AttServer::decode_with_opcode(opcode, r)?;
992            Ok(Att::Server(server))
993        }
994    }
995}
996
997impl From<codec::Error> for AttErrorCode {
998    fn from(e: codec::Error) -> Self {
999        AttErrorCode::INVALID_PDU
1000    }
1001}
1002
1003impl codec::Type for Att<'_> {
1004    fn size(&self) -> usize {
1005        Self::size(self)
1006    }
1007}
1008
1009impl codec::Encode for Att<'_> {
1010    fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
1011        Self::encode(self, dest)
1012    }
1013}
1014
1015impl<'d> codec::Decode<'d> for Att<'d> {
1016    fn decode(data: &'d [u8]) -> Result<Self, codec::Error> {
1017        Self::decode(data)
1018    }
1019}