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 {}: check the most recent bluetooth spec", other),
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 Error {
307 request: u8,
309 handle: u16,
311 code: AttErrorCode,
313 },
314 ReadByType {
316 it: ReadByTypeIter<'d>,
318 },
319 Read {
321 data: &'d [u8],
323 },
324 Write,
326}
327
328#[cfg_attr(feature = "defmt", derive(defmt::Format))]
330#[derive(Debug)]
331pub enum AttUns<'d> {
332 Notify {
334 handle: u16,
336 data: &'d [u8],
338 },
339 Indicate {
341 handle: u16,
343 data: &'d [u8],
345 },
346}
347
348#[cfg_attr(feature = "defmt", derive(defmt::Format))]
350#[derive(Debug)]
351pub enum Att<'d> {
352 Client(AttClient<'d>),
356 Server(AttServer<'d>),
360}
361
362#[cfg_attr(feature = "defmt", derive(defmt::Format))]
364#[derive(Clone, Debug)]
365pub struct FindByTypeValueIter<'d> {
366 cursor: ReadCursor<'d>,
367}
368
369impl FindByTypeValueIter<'_> {
370 #[allow(clippy::should_implement_trait)]
372 pub fn next(&mut self) -> Option<Result<(u16, u16), crate::Error>> {
373 if self.cursor.available() >= 4 {
374 let res = (|| {
375 let handle: u16 = self.cursor.read()?;
376 let end: u16 = self.cursor.read()?;
377 Ok((handle, end))
378 })();
379 Some(res)
380 } else {
381 None
382 }
383 }
384}
385
386#[cfg_attr(feature = "defmt", derive(defmt::Format))]
388#[derive(Clone, Debug)]
389pub struct ReadByTypeIter<'d> {
390 item_len: usize,
391 cursor: ReadCursor<'d>,
392}
393
394impl<'d> ReadByTypeIter<'d> {
395 #[allow(clippy::should_implement_trait)]
397 pub fn next(&mut self) -> Option<Result<(u16, &'d [u8]), crate::Error>> {
398 if self.cursor.available() >= self.item_len {
399 let res = (|| {
400 let handle: u16 = self.cursor.read()?;
401 let item = self.cursor.slice(self.item_len - 2)?;
402 Ok((handle, item))
403 })();
404 Some(res)
405 } else {
406 None
407 }
408 }
409}
410
411impl<'d> AttServer<'d> {
412 fn size(&self) -> usize {
413 match self {
414 Self::Response(rsp) => rsp.size(),
415 Self::Unsolicited(uns) => uns.size(),
416 }
417 }
418
419 fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
420 match self {
421 Self::Response(rsp) => rsp.encode(dest),
422 Self::Unsolicited(uns) => uns.encode(dest),
423 }
424 }
425
426 fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
427 let decoded = match opcode {
428 ATT_HANDLE_VALUE_NTF | ATT_HANDLE_VALUE_IND => Self::Unsolicited(AttUns::decode_with_opcode(opcode, r)?),
429 _ => Self::Response(AttRsp::decode_with_opcode(opcode, r)?),
430 };
431 Ok(decoded)
432 }
433}
434
435impl<'d> AttRsp<'d> {
436 fn size(&self) -> usize {
437 1 + match self {
438 Self::ExchangeMtu { mtu: u16 } => 2,
439 Self::FindByTypeValue { it } => it.cursor.len(),
440 Self::Error { .. } => 4,
441 Self::Read { data } => data.len(),
442 Self::ReadByType { it } => it.cursor.len(),
443 Self::Write => 0,
444 }
445 }
446
447 fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
448 let mut w = WriteCursor::new(dest);
449 match self {
450 Self::ExchangeMtu { mtu } => {
451 w.write(ATT_EXCHANGE_MTU_RSP)?;
452 w.write(*mtu)?;
453 }
454 Self::FindByTypeValue { it } => {
455 w.write(ATT_FIND_BY_TYPE_VALUE_RSP)?;
456 let mut it = it.clone();
457 while let Some(Ok((start, end))) = it.next() {
458 w.write(start)?;
459 w.write(end)?;
460 }
461 }
462 Self::Error { request, handle, code } => {
463 w.write(ATT_ERROR_RSP)?;
464 w.write(*request)?;
465 w.write(*handle)?;
466 w.write(*code)?;
467 }
468 Self::ReadByType { it } => {
469 w.write(ATT_READ_BY_TYPE_RSP)?;
470 w.write(it.item_len as u8)?;
471 let mut it = it.clone();
472 while let Some(Ok((handle, item))) = it.next() {
473 w.write(handle)?;
474 w.append(item)?;
475 }
476 }
477 Self::Read { data } => {
478 w.write(ATT_READ_RSP)?;
479 w.append(data)?;
480 }
481 Self::Write => {
482 w.write(ATT_WRITE_RSP)?;
483 }
484 }
485 Ok(())
486 }
487
488 fn decode_with_opcode(opcode: u8, mut r: ReadCursor<'d>) -> Result<Self, codec::Error> {
489 match opcode {
490 ATT_FIND_BY_TYPE_VALUE_RSP => Ok(Self::FindByTypeValue {
491 it: FindByTypeValueIter { cursor: r },
492 }),
493 ATT_EXCHANGE_MTU_RSP => {
494 let mtu: u16 = r.read()?;
495 Ok(Self::ExchangeMtu { mtu })
496 }
497 ATT_ERROR_RSP => {
498 let request = r.read()?;
499 let handle = r.read()?;
500 let code = r.read()?;
501 Ok(Self::Error { request, handle, code })
502 }
503 ATT_READ_RSP => Ok(Self::Read { data: r.remaining() }),
504 ATT_READ_BY_TYPE_RSP => {
505 let item_len: u8 = r.read()?;
506 Ok(Self::ReadByType {
507 it: ReadByTypeIter {
508 item_len: item_len as usize,
509 cursor: r,
510 },
511 })
512 }
513 ATT_WRITE_RSP => Ok(Self::Write),
514 _ => Err(codec::Error::InvalidValue),
515 }
516 }
517}
518
519impl<'d> AttUns<'d> {
520 fn size(&self) -> usize {
521 1 + match self {
522 Self::Notify { data, .. } => 2 + data.len(),
523 Self::Indicate { data, .. } => 2 + data.len(),
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::Notify { handle, data } => {
531 w.write(ATT_HANDLE_VALUE_NTF)?;
532 w.write(*handle)?;
533 w.append(data)?;
534 }
535 Self::Indicate { handle, data } => {
536 w.write(ATT_HANDLE_VALUE_IND)?;
537 w.write(*handle)?;
538 w.append(data)?;
539 }
540 }
541 Ok(())
542 }
543
544 fn decode_with_opcode(opcode: u8, mut r: ReadCursor<'d>) -> Result<Self, codec::Error> {
545 match opcode {
546 ATT_HANDLE_VALUE_NTF => {
547 let handle = r.read()?;
548 Ok(Self::Notify {
549 handle,
550 data: r.remaining(),
551 })
552 }
553 ATT_HANDLE_VALUE_IND => {
554 let handle = r.read()?;
555 Ok(Self::Indicate {
556 handle,
557 data: r.remaining(),
558 })
559 }
560 _ => Err(codec::Error::InvalidValue),
561 }
562 }
563}
564
565impl<'d> AttClient<'d> {
566 fn size(&self) -> usize {
567 match self {
568 Self::Request(req) => req.size(),
569 Self::Command(cmd) => cmd.size(),
570 Self::Confirmation(cfm) => cfm.size(),
571 }
572 }
573
574 fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
575 match self {
576 Self::Request(req) => req.encode(dest),
577 Self::Command(cmd) => cmd.encode(dest),
578 Self::Confirmation(cfm) => cfm.encode(dest),
579 }
580 }
581
582 fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
583 let decoded = match opcode {
584 ATT_WRITE_CMD => Self::Command(AttCmd::decode_with_opcode(opcode, r)?),
585 ATT_HANDLE_VALUE_CMF => Self::Confirmation(AttCfm::decode_with_opcode(opcode, r)?),
586 _ => Self::Request(AttReq::decode_with_opcode(opcode, r)?),
587 };
588 Ok(decoded)
589 }
590}
591
592impl<'d> AttReq<'d> {
593 fn size(&self) -> usize {
594 1 + match self {
595 Self::ExchangeMtu { .. } => 2,
596 Self::FindByTypeValue {
597 start_handle,
598 end_handle,
599 att_type,
600 att_value,
601 } => 6 + att_value.len(),
602 Self::ReadByType {
603 start,
604 end,
605 attribute_type,
606 } => 4 + attribute_type.as_raw().len(),
607 Self::Read { .. } => 2,
608 Self::Write { handle, data } => 2 + data.len(),
609 _ => unimplemented!(),
610 }
611 }
612 fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
613 let mut w = WriteCursor::new(dest);
614 match self {
615 Self::ExchangeMtu { mtu } => {
616 w.write(ATT_EXCHANGE_MTU_REQ)?;
617 w.write(*mtu)?;
618 }
619 Self::FindByTypeValue {
620 start_handle,
621 end_handle,
622 att_type,
623 att_value,
624 } => {
625 w.write(ATT_FIND_BY_TYPE_VALUE_REQ)?;
626 w.write(*start_handle)?;
627 w.write(*end_handle)?;
628 w.write(*att_type)?;
629 w.append(att_value)?;
630 }
631 Self::ReadByType {
632 start,
633 end,
634 attribute_type,
635 } => {
636 w.write(ATT_READ_BY_TYPE_REQ)?;
637 w.write(*start)?;
638 w.write(*end)?;
639 w.write_ref(attribute_type)?;
640 }
641 Self::Read { handle } => {
642 w.write(ATT_READ_REQ)?;
643 w.write(*handle)?;
644 }
645 Self::Write { handle, data } => {
646 w.write(ATT_WRITE_REQ)?;
647 w.write(*handle)?;
648 w.append(data)?;
649 }
650 _ => unimplemented!(),
651 }
652 Ok(())
653 }
654
655 fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
656 let payload = r.remaining();
657 match opcode {
658 ATT_READ_BY_GROUP_TYPE_REQ => {
659 let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
660 let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
661
662 let group_type = if payload.len() == 6 {
663 Uuid::Uuid16([payload[4], payload[5]])
664 } else if payload.len() == 20 {
665 let uuid = payload[4..21].try_into().map_err(|_| codec::Error::InvalidValue)?;
666 Uuid::Uuid128(uuid)
667 } else {
668 return Err(codec::Error::InvalidValue);
669 };
670
671 Ok(Self::ReadByGroupType {
672 start: start_handle,
673 end: end_handle,
674 group_type,
675 })
676 }
677 ATT_READ_BY_TYPE_REQ => {
678 let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
679 let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
680
681 let attribute_type = if payload.len() == 6 {
682 Uuid::Uuid16([payload[4], payload[5]])
683 } else if payload.len() == 20 {
684 let uuid = payload[4..20].try_into().map_err(|_| codec::Error::InvalidValue)?;
685 Uuid::Uuid128(uuid)
686 } else {
687 return Err(codec::Error::InvalidValue);
688 };
689
690 Ok(Self::ReadByType {
691 start: start_handle,
692 end: end_handle,
693 attribute_type,
694 })
695 }
696 ATT_READ_REQ => {
697 let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
698
699 Ok(Self::Read { handle })
700 }
701 ATT_WRITE_REQ => {
702 let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
703 let data = &payload[2..];
704
705 Ok(Self::Write { handle, data })
706 }
707 ATT_EXCHANGE_MTU_REQ => {
708 let mtu = (payload[0] as u16) + ((payload[1] as u16) << 8);
709 Ok(Self::ExchangeMtu { mtu })
710 }
711 ATT_FIND_BY_TYPE_VALUE_REQ => {
712 let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
713 let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
714 let att_type = (payload[4] as u16) + ((payload[5] as u16) << 8);
715 let att_value = &payload[6..];
716
717 Ok(Self::FindByTypeValue {
718 start_handle,
719 end_handle,
720 att_type,
721 att_value,
722 })
723 }
724 ATT_FIND_INFORMATION_REQ => {
725 let start_handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
726 let end_handle = (payload[2] as u16) + ((payload[3] as u16) << 8);
727
728 Ok(Self::FindInformation {
729 start_handle,
730 end_handle,
731 })
732 }
733 ATT_PREPARE_WRITE_REQ => {
734 let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
735 let offset = (payload[2] as u16) + ((payload[3] as u16) << 8);
736 Ok(Self::PrepareWrite {
737 handle,
738 offset,
739 value: &payload[4..],
740 })
741 }
742 ATT_EXECUTE_WRITE_REQ => {
743 let flags = payload[0];
744 Ok(Self::ExecuteWrite { flags })
745 }
746 ATT_READ_MULTIPLE_REQ => Ok(Self::ReadMultiple { handles: payload }),
747 ATT_READ_BLOB_REQ => {
748 let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
749 let offset = (payload[2] as u16) + ((payload[3] as u16) << 8);
750 Ok(Self::ReadBlob { handle, offset })
751 }
752 code => {
753 warn!("[att] unknown opcode {:x}", code);
754 Err(codec::Error::InvalidValue)
755 }
756 }
757 }
758}
759
760impl<'d> AttCmd<'d> {
761 fn size(&self) -> usize {
762 1 + match self {
763 Self::Write { handle, data } => 2 + data.len(),
764 }
765 }
766
767 fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
768 let mut w = WriteCursor::new(dest);
769 match self {
770 Self::Write { handle, data } => {
771 w.write(ATT_WRITE_CMD)?;
772 w.write(*handle)?;
773 w.append(data)?;
774 }
775 }
776 Ok(())
777 }
778
779 fn decode_with_opcode(opcode: u8, r: ReadCursor<'d>) -> Result<Self, codec::Error> {
780 let payload = r.remaining();
781 match opcode {
782 ATT_WRITE_CMD => {
783 let handle = (payload[0] as u16) + ((payload[1] as u16) << 8);
784 let data = &payload[2..];
785
786 Ok(Self::Write { handle, data })
787 }
788 code => {
789 warn!("[att] unknown opcode {:x}", code);
790 Err(codec::Error::InvalidValue)
791 }
792 }
793 }
794}
795
796impl AttCfm {
797 fn size(&self) -> usize {
798 1
799 }
800
801 fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
802 let mut w = WriteCursor::new(dest);
803 match self {
804 Self::ConfirmIndication => {
805 w.write(ATT_HANDLE_VALUE_CMF)?;
806 }
807 }
808 Ok(())
809 }
810
811 fn decode_with_opcode(opcode: u8, r: ReadCursor<'_>) -> Result<Self, codec::Error> {
812 let payload = r.remaining();
813 match opcode {
814 ATT_HANDLE_VALUE_CMF => Ok(Self::ConfirmIndication),
815 code => {
816 warn!("[att] unknown opcode {:x}", code);
817 Err(codec::Error::InvalidValue)
818 }
819 }
820 }
821}
822
823impl<'d> Att<'d> {
824 pub fn size(&self) -> usize {
826 match self {
827 Self::Client(client) => client.size(),
828 Self::Server(server) => server.size(),
829 }
830 }
831
832 pub fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
834 match self {
835 Self::Client(client) => client.encode(dest),
836 Self::Server(server) => server.encode(dest),
837 }
838 }
839
840 pub fn decode(data: &'d [u8]) -> Result<Att<'d>, codec::Error> {
842 let mut r = ReadCursor::new(data);
843 let opcode: u8 = r.read()?;
844 if opcode % 2 == 0 {
845 let client = AttClient::decode_with_opcode(opcode, r)?;
846 Ok(Att::Client(client))
847 } else {
848 let server = AttServer::decode_with_opcode(opcode, r)?;
849 Ok(Att::Server(server))
850 }
851 }
852}
853
854impl From<codec::Error> for AttErrorCode {
855 fn from(e: codec::Error) -> Self {
856 AttErrorCode::INVALID_PDU
857 }
858}
859
860impl codec::Type for Att<'_> {
861 fn size(&self) -> usize {
862 Self::size(self)
863 }
864}
865
866impl codec::Encode for Att<'_> {
867 fn encode(&self, dest: &mut [u8]) -> Result<(), codec::Error> {
868 Self::encode(self, dest)
869 }
870}
871
872impl<'d> codec::Decode<'d> for Att<'d> {
873 fn decode(data: &'d [u8]) -> Result<Self, codec::Error> {
874 Self::decode(data)
875 }
876}