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_CMF: 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
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#[cfg_attr(feature = "defmt", derive(defmt::Format))]
165#[derive(Debug)]
166pub enum AttClient<'d> {
167 Request(AttReq<'d>),
169 Command(AttCmd<'d>),
171 Confirmation(AttCfm),
173}
174
175#[cfg_attr(feature = "defmt", derive(defmt::Format))]
177#[derive(Debug)]
178pub enum AttReq<'d> {
179 ReadByGroupType {
181 start: u16,
183 end: u16,
185 group_type: Uuid,
187 },
188 ReadByType {
190 start: u16,
192 end: u16,
194 attribute_type: Uuid,
196 },
197 Read {
199 handle: u16,
201 },
202 Write {
204 handle: u16,
206 data: &'d [u8],
208 },
209 ExchangeMtu {
211 mtu: u16,
213 },
214 FindByTypeValue {
216 start_handle: u16,
218 end_handle: u16,
220 att_type: u16,
222 att_value: &'d [u8],
224 },
225 FindInformation {
227 start_handle: u16,
229 end_handle: u16,
231 },
232 PrepareWrite {
234 handle: u16,
236 offset: u16,
238 value: &'d [u8],
240 },
241 ExecuteWrite {
243 flags: u8,
245 },
246 ReadMultiple {
248 handles: &'d [u8],
250 },
251 ReadBlob {
253 handle: u16,
255 offset: u16,
257 },
258}
259
260#[cfg_attr(feature = "defmt", derive(defmt::Format))]
262#[derive(Debug)]
263pub enum AttCmd<'d> {
264 Write {
266 handle: u16,
268 data: &'d [u8],
270 },
271}
272
273#[cfg_attr(feature = "defmt", derive(defmt::Format))]
275#[derive(Debug)]
276pub enum AttCfm {
277 ConfirmIndication,
279}
280
281#[cfg_attr(feature = "defmt", derive(defmt::Format))]
283#[derive(Debug)]
284pub enum AttServer<'d> {
285 Response(AttRsp<'d>),
287 Unsolicited(AttUns<'d>),
289}
290
291#[cfg_attr(feature = "defmt", derive(defmt::Format))]
293#[derive(Debug)]
294pub enum AttRsp<'d> {
295 ExchangeMtu {
297 mtu: u16,
299 },
300 FindByTypeValue {
302 it: FindByTypeValueIter<'d>,
304 },
305 FindInformation {
307 it: FindInformationIter<'d>,
309 },
310 Error {
312 request: u8,
314 handle: u16,
316 code: AttErrorCode,
318 },
319 ReadByType {
321 it: ReadByTypeIter<'d>,
323 },
324 Read {
326 data: &'d [u8],
328 },
329 ReadBlob {
331 data: &'d [u8],
333 },
334 Write,
336}
337
338#[cfg_attr(feature = "defmt", derive(defmt::Format))]
340#[derive(Debug)]
341pub enum AttUns<'d> {
342 Notify {
344 handle: u16,
346 data: &'d [u8],
348 },
349 Indicate {
351 handle: u16,
353 data: &'d [u8],
355 },
356}
357
358#[cfg_attr(feature = "defmt", derive(defmt::Format))]
360#[derive(Debug)]
361pub enum Att<'d> {
362 Client(AttClient<'d>),
366 Server(AttServer<'d>),
370}
371
372#[cfg_attr(feature = "defmt", derive(defmt::Format))]
374#[derive(Clone, Debug)]
375pub struct FindByTypeValueIter<'d> {
376 cursor: ReadCursor<'d>,
377}
378
379impl FindByTypeValueIter<'_> {
380 #[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#[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 #[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#[cfg_attr(feature = "defmt", derive(defmt::Format))]
447#[derive(Clone, Debug)]
448pub struct FindInformationIter<'d> {
449 format: FindInformationUuidFormat,
451 cursor: ReadCursor<'d>,
452}
453
454impl<'d> FindInformationIter<'d> {
455 #[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(), 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, 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 pub fn size(&self) -> usize {
928 match self {
929 Self::Client(client) => client.size(),
930 Self::Server(server) => server.size(),
931 }
932 }
933
934 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 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}