1use 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#[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 pub const INVALID_HANDLE: Self = Self { value: 0x01 };
51 pub const READ_NOT_PERMITTED: Self = Self { value: 0x02 };
53 pub const WRITE_NOT_PERMITTED: Self = Self { value: 0x03 };
55 pub const INVALID_PDU: Self = Self { value: 0x04 };
57 pub const INSUFFICIENT_AUTHENTICATION: Self = Self { value: 0x05 };
59 pub const REQUEST_NOT_SUPPORTED: Self = Self { value: 0x06 };
61 pub const INVALID_OFFSET: Self = Self { value: 0x07 };
63 pub const INSUFFICIENT_AUTHORISATION: Self = Self { value: 0x08 };
65 pub const PREPARE_QUEUE_FULL: Self = Self { value: 0x09 };
67 pub const ATTRIBUTE_NOT_FOUND: Self = Self { value: 0x0a };
69 pub const ATTRIBUTE_NOT_LONG: Self = Self { value: 0x0b };
71 pub const INSUFFICIENT_ENCRYPTION_KEY_SIZE: Self = Self { value: 0x0c };
73 pub const INVALID_ATTRIBUTE_VALUE_LENGTH: Self = Self { value: 0x0d };
75 pub const UNLIKELY_ERROR: Self = Self { value: 0x0e };
77 pub const INSUFFICIENT_ENCRYPTION: Self = Self { value: 0x0f };
79 pub const UNSUPPORTED_GROUP_TYPE: Self = Self { value: 0x10 };
81 pub const INSUFFICIENT_RESOURCES: Self = Self { value: 0x11 };
83 pub const DATABASE_OUT_OF_SYNC: Self = Self { value: 0x12 };
85 pub const VALUE_NOT_ALLOWED: Self = Self { value: 0x13 };
87
88 pub const WRITE_REQUEST_REJECTED: Self = Self { value: 0xFC };
91 pub const CCCD_IMPROPERLY_CONFIGURED: Self = Self { value: 0xFD };
93 pub const PROCEDURE_ALREADY_IN_PROGRESS: Self = Self { value: 0xFE };
95 pub const OUT_OF_RANGE: Self = Self { value: 0xFF };
97
98 pub const fn new(value: u8) -> Self {
100 Self { value }
101 }
102
103 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#[cfg_attr(feature = "defmt", derive(defmt::Format))]
175#[derive(Debug)]
176pub enum AttClient<'d> {
177 Request(AttReq<'d>),
179 Command(AttCmd<'d>),
181 Confirmation(AttCfm),
183}
184
185#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187#[derive(Debug)]
188pub enum AttReq<'d> {
189 ReadByGroupType {
191 start: u16,
193 end: u16,
195 group_type: Uuid,
197 },
198 ReadByType {
200 start: u16,
202 end: u16,
204 attribute_type: Uuid,
206 },
207 Read {
209 handle: u16,
211 },
212 Write {
214 handle: u16,
216 data: &'d [u8],
218 },
219 ExchangeMtu {
221 mtu: u16,
223 },
224 FindByTypeValue {
226 start_handle: u16,
228 end_handle: u16,
230 att_type: u16,
232 att_value: &'d [u8],
234 },
235 FindInformation {
237 start_handle: u16,
239 end_handle: u16,
241 },
242 PrepareWrite {
244 handle: u16,
246 offset: u16,
248 value: &'d [u8],
250 },
251 ExecuteWrite {
253 flags: u8,
255 },
256 ReadMultiple {
258 handles: &'d [u8],
260 },
261 ReadBlob {
263 handle: u16,
265 offset: u16,
267 },
268}
269
270#[cfg_attr(feature = "defmt", derive(defmt::Format))]
272#[derive(Debug)]
273pub enum AttCmd<'d> {
274 Write {
276 handle: u16,
278 data: &'d [u8],
280 },
281}
282
283#[cfg_attr(feature = "defmt", derive(defmt::Format))]
285#[derive(Debug)]
286pub enum AttCfm {
287 ConfirmIndication,
289}
290
291#[cfg_attr(feature = "defmt", derive(defmt::Format))]
293#[derive(Debug)]
294pub enum AttServer<'d> {
295 Response(AttRsp<'d>),
297 Unsolicited(AttUns<'d>),
299}
300
301#[cfg_attr(feature = "defmt", derive(defmt::Format))]
303#[derive(Debug)]
304pub enum AttRsp<'d> {
305 ExchangeMtu {
307 mtu: u16,
309 },
310 FindByTypeValue {
312 it: FindByTypeValueIter<'d>,
314 },
315 FindInformation {
317 it: FindInformationIter<'d>,
319 },
320 Error {
322 request: u8,
324 handle: u16,
326 code: AttErrorCode,
328 },
329 ReadByType {
331 it: ReadByTypeIter<'d>,
333 },
334 ReadByGroupType {
336 it: ReadByTypeIter<'d>,
338 },
339 Read {
341 data: &'d [u8],
343 },
344 ReadBlob {
346 data: &'d [u8],
348 },
349 Write,
351}
352
353#[cfg_attr(feature = "defmt", derive(defmt::Format))]
355#[derive(Debug)]
356pub enum AttUns<'d> {
357 Notify {
359 handle: u16,
361 data: &'d [u8],
363 },
364 Indicate {
366 handle: u16,
368 data: &'d [u8],
370 },
371}
372
373#[cfg_attr(feature = "defmt", derive(defmt::Format))]
375#[derive(Debug)]
376pub enum Att<'d> {
377 Client(AttClient<'d>),
381 Server(AttServer<'d>),
385}
386
387#[cfg_attr(feature = "defmt", derive(defmt::Format))]
389#[derive(Clone, Debug)]
390pub struct FindByTypeValueIter<'d> {
391 cursor: ReadCursor<'d>,
392}
393
394impl FindByTypeValueIter<'_> {
395 #[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#[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 #[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#[cfg_attr(feature = "defmt", derive(defmt::Format))]
462#[derive(Clone, Debug)]
463pub struct FindInformationIter<'d> {
464 format: FindInformationUuidFormat,
466 cursor: ReadCursor<'d>,
467}
468
469impl<'d> FindInformationIter<'d> {
470 #[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(), 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, 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 pub fn size(&self) -> usize {
969 match self {
970 Self::Client(client) => client.size(),
971 Self::Server(server) => server.size(),
972 }
973 }
974
975 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 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}