1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
//! Pn532 Requests
/// Pn532 Request consisting of a [`Command`] and extra command data
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct Request<const N: usize> {
pub command: Command,
pub data: [u8; N],
}
/// Pn532 Request consisting of a [`Command`] and a reference to extra command data
pub struct BorrowedRequest<'a> {
pub command: Command,
pub data: &'a [u8],
}
impl<'a> BorrowedRequest<'a> {
#[inline]
pub const fn new(command: Command, data: &'a [u8]) -> Self {
Self {command, data}
}
}
impl<'a, const N: usize> Into<BorrowedRequest<'a>> for &'a Request<N> {
fn into(self) -> BorrowedRequest<'a> {
BorrowedRequest::new(self.command, &self.data)
}
}
impl<const N: usize> Request<N> {
#[inline]
pub const fn new(command: Command, data: [u8; N]) -> Self {
Request { command, data }
}
}
impl Request<0> {
pub const GET_FIRMWARE_VERSION: Request<0> = Request::new(Command::GetFirmwareVersion, []);
pub const INLIST_ONE_ISO_A_TARGET: Request<2> =
Request::new(Command::InListPassiveTarget, [1, CardType::IsoTypeA as u8]);
pub const SELECT_TAG_1: Request<1> = Request::new(Command::InSelect, [1]);
pub const SELECT_TAG_2: Request<1> = Request::new(Command::InSelect, [2]);
pub const DESELECT_TAG_1: Request<1> = Request::new(Command::InDeselect, [1]);
pub const DESELECT_TAG_2: Request<1> = Request::new(Command::InDeselect, [2]);
pub const RELEASE_TAG_1: Request<1> = Request::new(Command::InRelease, [1]);
pub const RELEASE_TAG_2: Request<1> = Request::new(Command::InRelease, [2]);
pub const fn sam_configuration(mode: SAMMode, use_irq_pin: bool) -> Request<3> {
// TODO use_irq_pin seems to not have any effect
let (mode, timeout) = match mode {
SAMMode::Normal => (1, 0),
SAMMode::VirtualCard { timeout } => (2, timeout),
SAMMode::WiredCard => (3, 0),
SAMMode::DualCard => (4, 0),
};
Request::new(
Command::SAMConfiguration,
[mode, timeout, use_irq_pin as u8],
)
}
pub const fn rf_regulation_test(tx_speed: TxSpeed, tx_framing: TxFraming) -> Request<1> {
Request::new(
Command::RFRegulationTest,
[tx_speed as u8 | tx_framing as u8],
)
}
pub const fn ntag_read(page: u8) -> Request<3> {
Request::new(
Command::InDataExchange,
[0x01, NTAGCommand::Read as u8, page],
)
}
pub const fn ntag_write(page: u8, bytes: &[u8; 4]) -> Request<7> {
Request::new(
Command::InDataExchange,
[
0x01,
NTAGCommand::Write as u8,
page,
bytes[0],
bytes[1],
bytes[2],
bytes[3],
],
)
}
pub const fn ntag_pwd_auth(bytes: &[u8; 4]) -> Request<5> {
Request::new(
Command::InCommunicateThru,
[
NTAGCommand::PwdAuth as u8,
bytes[0],
bytes[1],
bytes[2],
bytes[3],
],
)
}
}
/// Commands supported by the Pn532
///
/// These commands are fully described in the section 7 of the User Manual:
/// <https://www.nxp.com/docs/en/user-guide/141520.pdf>
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum Command {
/// This command is used for self-diagnosis. Processing time of this command varies depending
/// on the content of the processing.
///
/// For more information, see 7.2.1 Diagnose
Diagnose = 0x00,
/// This command is used to get the version of the embedded firmware from PN532.
///
/// For more information, see 7.2.2 GetFirmwareVersion
GetFirmwareVersion = 0x02,
/// This command allows the host controller to know at a given moment the complete situation of
/// the PN532.
///
/// For more information, see 7.2.3 GetGeneralStatus
GetGeneralStatus = 0x04,
/// This command is used to read the content of one or several internal registers of the PN532.
///
/// For more information, see 7.2.4 ReadRegister
ReadRegister = 0x06,
/// This command is used to overwrite the content of one or several internal registers of the
/// PN532.
///
/// For more information, see 7.2.5 WriteRegister
WriteRegister = 0x08,
/// Tells the PN532 to read the value for each GPIO port and return the information to the host
/// controller.
///
/// For more information, see 7.2.6 ReadGPIO
ReadGPIO = 0x0C,
/// Tells the PN532 to apply the value for each port specified by the host controller.
///
/// For more information, see 7.2.7 WriteGPIO
WriteGPIO = 0x0E,
/// Selects the baud rate on the serial link between the host controller and the PN532.
///
/// For more information, see 7.2.8 SetSerialBaudRate
SetSerialBaudRate = 0x10,
/// This command is used to set internal parameters of the PN532, and then to configure its
/// behavior regarding different cases.
///
/// For more information, see 7.2.9 SetParameters
SetParameters = 0x12,
/// This command is used to select the data flow path by configuring the internal serial data
/// switch.
///
/// For more information, see 7.2.10 SAMConfiguration
SAMConfiguration = 0x14,
/// This command can be used to put the PN532 into Power Down mode in order to save power
/// consumption.
///
/// For more information, see 7.2.11 PowerDown
PowerDown = 0x16,
/// This command is used to configure the different settings of the PN532.
///
/// For more information, see 7.3.1 RFConfiguration
RFConfiguration = 0x32,
/// This command is used for radio regulation test.
///
/// For more information, see 7.3.2 RFRegulationTest
RFRegulationTest = 0x58,
/// This command is used by a host controller to activate a target using either active or
/// passive communication mode during communication over DEP protocol.
///
/// For more information, see 7.3.3 InJumpForDEP
InJumpForDEP = 0x56,
/// This command is used by a host controller to activate a target using either active or
/// passive communication mode during communication over PSL or DEP protocols.
///
/// For more information, see 7.3.4 InJumpForPSL
InJumpForPSL = 0x46,
/// This command tells PN532 to detect as many targets as possible in passive mode.
///
/// For more information, see 7.3.5 InListPassiveTarget
InListPassiveTarget = 0x4A,
/// This command is used by a host controller to launch an activation of a target in case of
/// passive mode.
///
/// For more information, see 7.3.6 InATR
InATR = 0x50,
/// This command is used by a host controller to change the defined bit rates either with a TPE
/// target or with a ISO/IEC14443-4 target.
///
/// For more information, see 7.3.7 InPSL
InPSL = 0x4E,
/// This command is used to support protocol data exchanges between the PN532 as initiator and
/// a target.
///
/// For more information, see 7.3.8 InDataExchange
InDataExchange = 0x40,
/// This command is used to support basic data exchanges between the PN532 and a target.
///
/// For more information, see 7.3.9 InCommunicateThru
InCommunicateThru = 0x42,
/// Command to deselect specified targets(s).
///
/// For more information, see 7.3.10 InDeselect
InDeselect = 0x44,
/// Command to release the specified target(s).
///
/// For more information, see 7.3.11 InRelease
InRelease = 0x52,
/// Command to select the specified target.
///
/// For more information, see 7.3.12 InSelect
InSelect = 0x54,
/// This command is used to poll card(s) / target(s) of specified Type present in the RF field.
///
/// For more information, see 7.3.13 InAutoPoll
InAutoPoll = 0x60,
/// The host controller uses this command to configure the PN532 as target.
///
/// For more information, see 7.3.14 TgInitAsTarget
TgInitAsTarget = 0x8C,
/// This command is used to give General Bytes to the PN532.
///
/// For more information, see 7.3.15 TgSetGeneralBytes
TgSetGeneralBytes = 0x92,
/// This command allows the host controller to get back the data received by the PN532 from its
/// initiator.
///
/// For more information, see 7.3.16 TgGetData
TgGetData = 0x86,
/// This command allows the host controller to spully PN532 with teh data that it wants to send
/// back to teh initiator.
///
/// For more information, see 7.3.17 TgSetData
TgSetData = 0x8E,
/// This command is used if the overall amount of data to be sent cannot be transmitted in one
/// frame.
///
/// For more information, see 7.3.18 TgSetMetaData
TgSetMetaData = 0x94,
/// This command is used to get a packet of data from an initiator and to send it back to the
/// host controller.
///
/// For more information, see 7.3.19 TgGetInitiatorCommand
TgGetInitiatorCommand = 0x88,
/// This command is used to send a response packet of data to an initiator.
///
/// For more information, see 7.3.20 TgResponseToInitiator
TgResponseToInitiator = 0x90,
/// This command is used by the host controller to know what the current state of the PN532 is.
///
/// For more information, see 7.3.21 TgGetTargetStatus
TgGetTargetStatus = 0x8A,
}
/// SAM mode parameter to be used in [`Command::SAMConfiguration`]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum SAMMode {
/// The SAM is not used; this is the default mode
Normal,
/// The couple PN532+SAM is seen as only one contactless SAM card
/// from the external world
VirtualCard {
/// In multiples of 50ms
timeout: u8,
},
/// The host controller can access to the SAM with standard PCD commands
/// (InListPassiveTarget, InDataExchange, ...)
WiredCard,
/// Both the PN532 and the SAM are visible from the external world
/// as two separated targets
DualCard,
}
/// Card type parameter to be used in [`Command::InListPassiveTarget`]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum CardType {
/// 106 kbps type A (ISO/IEC14443 Type A)
IsoTypeA = 0x00,
/// 212 kbps (FeliCa polling)
FeliCa212kbps = 0x01,
/// 424 kbps (FeliCa polling)
FeliCa424kbps = 0x02,
/// 106 kbps type B (ISO/IEC14443-3B)
IsoTypeB = 0x03,
/// 106 kbps Innovision Jewel tag
Jewel = 0x04,
}
/// Bitrate to be used in [`Command::RFRegulationTest`]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum TxSpeed {
/// 106 kbps
Tx106kbps = 0b0000_0000,
/// 212 kbps
Tx212kbps = 0b0001_0000,
/// 424 kbps
Tx424kbps = 0b0010_0000,
/// 848 kbps
Tx848kbps = 0b0011_0000,
}
/// Type of modulation to be used in [`Command::RFRegulationTest`]
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum TxFraming {
Mifare = 0b0000_0000,
FeliCa = 0b0000_0010,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum NTAGCommand {
GetVersion = 0x60,
Read = 0x30,
FastRead = 0x3A,
Write = 0xA2,
CompWrite = 0xA0,
ReadCnt = 0x39,
PwdAuth = 0x1B,
ReadSig = 0x3C,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(u8)]
pub enum MifareCommand {
AuthenticationWithKeyA = 0x60,
AuthenticationWithKeyB = 0x61,
PersonalizeUIDUsage = 0x40,
SetModType = 0x43,
Read = 0x30,
Write = 0xA0,
Decrement = 0xC0,
Increment = 0xC1,
Restore = 0xC2,
Transfer = 0xB0,
}