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