use std::fmt::Debug;
use crate::hci;
use super::*;
pub(crate) const MAX_VAL_LEN: usize = 512;
#[derive(
Clone, Copy, Debug, Eq, PartialEq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive,
)]
#[non_exhaustive]
#[repr(u8)]
pub enum Opcode {
ErrorRsp = 0x01,
ExchangeMtuReq = 0x02,
ExchangeMtuRsp = 0x03,
FindInformationReq = 0x04,
FindInformationRsp = 0x05,
FindByTypeValueReq = 0x06,
FindByTypeValueRsp = 0x07,
ReadByTypeReq = 0x08,
ReadByTypeRsp = 0x09,
ReadReq = 0x0A,
ReadRsp = 0x0B,
ReadBlobReq = 0x0C,
ReadBlobRsp = 0x0D,
ReadMultipleReq = 0x0E,
ReadMultipleRsp = 0x0F,
ReadByGroupTypeReq = 0x10,
ReadByGroupTypeRsp = 0x11,
WriteReq = 0x12,
WriteRsp = 0x13,
WriteCmd = 0x52,
PrepareWriteReq = 0x16,
PrepareWriteRsp = 0x17,
ExecuteWriteReq = 0x18,
ExecuteWriteRsp = 0x19,
ReadMultipleVariableReq = 0x20,
ReadMultipleVariableRsp = 0x21,
MultipleHandleValueNtf = 0x23,
HandleValueNtf = 0x1B,
HandleValueInd = 0x1D,
HandleValueCfm = 0x1E,
SignedWriteCmd = 0xD2,
}
impl Opcode {
#[inline]
#[must_use]
pub const fn is_cmd(op: u8) -> bool {
op & (1 << 6) != 0
}
#[inline]
#[must_use]
pub const fn is_signed(self) -> bool {
self as u8 & (1 << 7) != 0
}
#[inline]
pub(crate) fn request(self, sec: hci::ConnSec) -> Request {
let ac = (self.access_type().expect("not a read/write request")).copy(sec);
Request { op: self, ac }
}
#[inline]
pub const fn err<R>(self, err: ErrorCode) -> RspResult<R> {
Err(ErrorRsp::new(self as _, None, err))
}
#[inline]
pub const fn hdl_err<R>(self, err: ErrorCode, hdl: Handle) -> RspResult<R> {
Err(ErrorRsp::new(self as _, Some(hdl), err))
}
pub(crate) const fn typ(self) -> PduType {
use {Opcode::*, PduType::*};
#[allow(clippy::match_same_arms)]
match self {
ErrorRsp => Rsp,
ExchangeMtuReq => Req,
ExchangeMtuRsp => Rsp,
FindInformationReq => Req,
FindInformationRsp => Rsp,
FindByTypeValueReq => Req,
FindByTypeValueRsp => Rsp,
ReadByTypeReq => Req,
ReadByTypeRsp => Rsp,
ReadReq => Req,
ReadRsp => Rsp,
ReadBlobReq => Req,
ReadBlobRsp => Rsp,
ReadMultipleReq => Req,
ReadMultipleRsp => Rsp,
ReadByGroupTypeReq => Req,
ReadByGroupTypeRsp => Rsp,
WriteReq => Req,
WriteRsp => Rsp,
WriteCmd => Cmd,
PrepareWriteReq => Req,
PrepareWriteRsp => Rsp,
ExecuteWriteReq => Req,
ExecuteWriteRsp => Rsp,
ReadMultipleVariableReq => Req,
ReadMultipleVariableRsp => Rsp,
MultipleHandleValueNtf => Ntf,
HandleValueNtf => Ntf,
HandleValueInd => Ind,
HandleValueCfm => Cfm,
SignedWriteCmd => Cmd,
}
}
pub(crate) const fn access_type(self) -> Option<Access> {
use Opcode::*;
const READ: Option<Access> = Some(Access::READ);
const WRITE: Option<Access> = Some(Access::WRITE);
#[allow(clippy::match_same_arms)]
match self {
ErrorRsp => None,
ExchangeMtuReq => None,
ExchangeMtuRsp => None,
FindInformationReq => None,
FindInformationRsp => None,
FindByTypeValueReq => None,
FindByTypeValueRsp => None,
ReadByTypeReq => READ,
ReadByTypeRsp => None,
ReadReq => READ,
ReadRsp => None,
ReadBlobReq => READ,
ReadBlobRsp => None,
ReadMultipleReq => READ,
ReadMultipleRsp => None,
ReadByGroupTypeReq => READ,
ReadByGroupTypeRsp => None,
WriteReq => WRITE,
WriteRsp => None,
WriteCmd => WRITE,
PrepareWriteReq => WRITE,
PrepareWriteRsp => None,
ExecuteWriteReq => None,
ExecuteWriteRsp => None,
ReadMultipleVariableReq => READ,
ReadMultipleVariableRsp => None,
MultipleHandleValueNtf => None,
HandleValueNtf => None,
HandleValueInd => None,
HandleValueCfm => None,
SignedWriteCmd => WRITE,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum PduType {
Cmd,
Req,
Rsp,
Ntf,
Ind,
Cfm,
}
#[derive(
Clone,
Copy,
Debug,
Eq,
PartialEq,
num_enum::IntoPrimitive,
num_enum::TryFromPrimitive,
thiserror::Error,
)]
#[non_exhaustive]
#[repr(u8)]
pub enum ErrorCode {
InvalidHandle = 0x01,
ReadNotPermitted = 0x02,
WriteNotPermitted = 0x03,
InvalidPdu = 0x04,
InsufficientAuthentication = 0x05,
RequestNotSupported = 0x06,
InvalidOffset = 0x07,
InsufficientAuthorization = 0x08,
PrepareQueueFull = 0x09,
AttributeNotFound = 0x0A,
AttributeNotLong = 0x0B,
EncryptionKeySizeTooShort = 0x0C,
InvalidAttributeValueLength = 0x0D,
UnlikelyError = 0x0E,
InsufficientEncryption = 0x0F,
UnsupportedGroupType = 0x10,
InsufficientResources = 0x11,
DatabaseOutOfSync = 0x12,
ValueNotAllowed = 0x13,
WriteRequestRejected = 0xFC,
CccdImproperlyConfigured = 0xFD,
ProcedureAlreadyInProgress = 0xFE,
OutOfRange = 0xFF,
}
crate::impl_display_via_debug! { Opcode, ErrorCode }