Documentation
¶
Index ¶
- Constants
- Variables
- func AssertCapabilitiesConsistent(tag Tag) error
- func BuildAPDU(cla, ins, p1, p2 byte, data []byte, le *byte) []byte
- func BytesToHex(data []byte) string
- func BytesToUint16(b []byte) uint16
- func CanTagLock(tag Tag) bool
- func CanTagRead(tag Tag) bool
- func CanTagTransceive(tag Tag) bool
- func CanTagWrite(tag Tag) bool
- func DESFireAdditionalFrameAPDU(data []byte) []byte
- func DESFireAuthAPDU(keyNo byte, authType byte) []byte
- func DESFireGetAppIDsAPDU() []byte
- func DESFireGetFileIDsAPDU() []byte
- func DESFireReadDataAPDU(fileNo byte, offset uint32, length uint32) []byte
- func DESFireSelectAppAPDU(aid []byte) []byte
- func DESFireWrapAPDU(cmd byte, data []byte) []byte
- func DESFireWriteDataAPDU(fileNo byte, offset uint32, writeData []byte) []byte
- func DirectTransmitAPDU(cmd []byte) []byte
- func EncodeNdefMessageWithTextRecord(text string, langCodeStr string) []byte
- func GetAllCardTypes() []string
- func GetLengthFieldSize(length int) int
- func GetUIDAPDU() []byte
- func GetVersionAPDU() []byte
- func HexToBytes(hex string) ([]byte, error)
- func IsACR122Error(err error) bool
- func IsAuthError(err error) bool
- func IsCapacityExceededError(err error) bool
- func IsCardRemovedError(err error) bool
- func IsDeviceClosedError(err error) bool
- func IsDeviceConfigError(err error) bool
- func IsIOError(err error) bool
- func IsNoCardError(err error) bool
- func IsNotSupportedError(err error) bool
- func IsReadOnlyError(err error) bool
- func IsRemoteDevice(m Manager, devicePath string) bool
- func IsTagRemovedError(err error) bool
- func IsTimeoutError(err error) bool
- func IsUnsupportedTagError(err error) bool
- func IsWriteError(err error) bool
- func ListReaders(m Manager) ([]string, error)
- func LoadKeyAPDU(keySlot byte, key []byte) []byte
- func MIFAREAuthAPDU(block byte, keyType byte, keySlot byte) []byte
- func MakeTextRecordPayload(text string, langCodeStr string) []byte
- func MakeURIRecordPayload(uri string) []byte
- func NewCardRemovedError(cause error) error
- func NewUnsupportedTagError(atr string) error
- func ParseNdefMessageForTextRecord(ndefMessage []byte) (string, error)
- func ParseNdefMessageForURIRecord(ndefMessage []byte) (string, error)
- func ParseTLVBlock(data []byte) map[byte][]byte
- func ReadBinaryAPDU(offset byte, length byte) []byte
- func ReadBinaryExtAPDU(offset uint16, length byte) []byte
- func SelectFileAPDU(fid []byte) []byte
- func SelectFileByAIDAPDU(aid []byte) []byte
- func TLVDecode(data []byte) (value []byte, tlvType byte)
- func TLVEncode(data []byte, tlvType byte) []byte
- func TLVFindNDEF(data []byte) ([]byte, bool)
- func TLVGetLength(data []byte) int
- func TLVRecordLength(data []byte) (fls, fvs int)
- func Uint16ToBytes(v uint16) []byte
- func UltralightReadAPDU(page byte) []byte
- func UltralightWriteAPDU(page byte, data []byte) []byte
- func UpdateBinaryAPDU(offset byte, data []byte) []byte
- func UpdateBinaryExtAPDU(offset uint16, data []byte) []byte
- func WireError(err error) protocol.ErrorPayload
- type APDUResponse
- type AdvancedWriter
- type BaseTag
- type Card
- func (c *Card) Capabilities() TagCapabilities
- func (c *Card) Close() error
- func (c *Card) Flush() error
- func (c *Card) GetUnderlyingTag() Tag
- func (c *Card) Read(p []byte) (n int, err error)
- func (c *Card) ReadMessage() (Message, error)
- func (c *Card) Reset()
- func (c *Card) String() string
- func (c *Card) Write(p []byte) (n int, err error)
- func (c *Card) WriteMessage(msg Message) error
- type CardTransport
- type ClassicTag
- type Clock
- type DetectedTagType
- type Device
- type DeviceCapabilities
- type DeviceChangeNotifier
- type DeviceEvent
- type DeviceEventEmitter
- type DeviceEventType
- type DeviceHealthChecker
- type DeviceInfoProvider
- type DeviceManager
- func (dm *DeviceManager) Close()
- func (dm *DeviceManager) CooldownChannel() <-chan time.Time
- func (dm *DeviceManager) Device() Device
- func (dm *DeviceManager) DevicePath() string
- func (dm *DeviceManager) EndCooldown(stopChan <-chan struct{})
- func (dm *DeviceManager) EnsureConnected(stopChan <-chan struct{}) error
- func (dm *DeviceManager) Events() <-chan DeviceEvent
- func (dm *DeviceManager) ForceReconnect(stopChan <-chan struct{}) error
- func (dm *DeviceManager) HandleError(err error, stopChan <-chan struct{}) (needsCooldown bool)
- func (dm *DeviceManager) HasDevice() bool
- func (dm *DeviceManager) InCooldown() bool
- func (dm *DeviceManager) Manager() Manager
- func (dm *DeviceManager) Reconnect(stopChan <-chan struct{}) error
- func (dm *DeviceManager) SetDevicePath(path string)
- func (dm *DeviceManager) TryConnect() error
- type DeviceStatus
- type DeviceTransceiver
- type ErrorCode
- type FakeClock
- type LockResult
- type Manager
- type Message
- type MockClassicTag
- func (m *MockClassicTag) GetBlockData(sector, block uint8) ([]byte, bool)
- func (m *MockClassicTag) Read(sector, block uint8, key []byte, keyType int) ([]byte, error)
- func (m *MockClassicTag) SetBlockData(sector, block uint8, data []byte)
- func (m *MockClassicTag) Write(sector, block uint8, data []byte, key []byte, keyType int) error
- type MockDevice
- func (m *MockDevice) AddTag(tag Tag)
- func (m *MockDevice) ClearCallLog()
- func (m *MockDevice) ClearTags()
- func (m *MockDevice) Close() error
- func (m *MockDevice) Connection() string
- func (m *MockDevice) DeviceType() string
- func (m *MockDevice) GetCallLog() []string
- func (m *MockDevice) GetTags() ([]Tag, error)
- func (m *MockDevice) IsHealthy() error
- func (m *MockDevice) SetTags(tags []Tag)
- func (m *MockDevice) String() string
- func (m *MockDevice) SupportedTagTypes() []string
- func (m *MockDevice) SupportsEvents() bool
- func (m *MockDevice) Transceive(txData []byte) ([]byte, error)
- type MockISO14443Tag
- type MockManager
- type MockNtagTag
- type MockTag
- func (m *MockTag) CanMakeReadOnly() (bool, error)
- func (m *MockTag) Capabilities() TagCapabilities
- func (m *MockTag) ClearCallLog()
- func (m *MockTag) Connect() error
- func (m *MockTag) Disconnect() error
- func (m *MockTag) GetCallLog() []string
- func (m *MockTag) IsWritable() (bool, error)
- func (m *MockTag) MakeReadOnly() error
- func (m *MockTag) NumericType() int
- func (m *MockTag) ReadData() ([]byte, error)
- func (m *MockTag) Transceive(data []byte) ([]byte, error)
- func (m *MockTag) Type() string
- func (m *MockTag) UID() string
- func (m *MockTag) WriteData(data []byte) error
- type NDEFEmpty
- type NDEFExternal
- type NDEFMIME
- type NDEFMessage
- func (m *NDEFMessage) AddRecord(record NDEFRecord) *NDEFMessage
- func (m *NDEFMessage) AddText(text, langCode string) *NDEFMessage
- func (m *NDEFMessage) AddURI(uri string) *NDEFMessage
- func (m *NDEFMessage) Encode() ([]byte, error)
- func (m *NDEFMessage) GetText() (string, error)
- func (m *NDEFMessage) GetURI() (string, error)
- func (m *NDEFMessage) Records() []NDEFRecord
- func (m *NDEFMessage) ToBuilder() *NDEFMessageBuilder
- func (m *NDEFMessage) ToJSONMap() map[string]interface{}
- func (m *NDEFMessage) ToPayload() *NDEFMessagePayload
- func (m *NDEFMessage) Type() string
- type NDEFMessageBuilder
- type NDEFMessagePayload
- type NDEFRaw
- type NDEFRecord
- type NDEFRecordBuilder
- type NDEFRecordPayload
- type NDEFSmartPoster
- type NDEFText
- type NDEFURI
- type NFCData
- type NFCError
- func Errorf(code ErrorCode, op, format string, args ...any) *NFCError
- func NewAuthError(op, tagUID string, cause error) *NFCError
- func NewCapacityExceededError(op, tagUID string, needed, available int) *NFCError
- func NewNotSupportedError(op string) *NFCError
- func NewReadError(op string, cause error) *NFCError
- func NewReadOnlyError(op, tagUID string, cause error) *NFCError
- func NewTagRemovedError(op string, cause error) *NFCError
- func NewTransceiveError(op string, cause error) *NFCError
- func NewWriteError(op string, cause error) *NFCError
- func WrapError(code ErrorCode, op, message string, cause error) *NFCError
- type NFCReader
- func (r *NFCReader) Close()
- func (r *NFCReader) Data() <-chan NFCData
- func (r *NFCReader) DevicePath() string
- func (r *NFCReader) EraseCard() (*WriteResult, error)
- func (r *NFCReader) GetCapabilities() (*TagCapabilities, error)
- func (r *NFCReader) GetDeviceStatus() DeviceStatus
- func (r *NFCReader) GetLastScannedData() string
- func (r *NFCReader) GetMode() ReaderMode
- func (r *NFCReader) GetTags() ([]Tag, error)
- func (r *NFCReader) LockCard() (*LockResult, error)
- func (r *NFCReader) LogDeviceInfo()
- func (r *NFCReader) RemoveCardPassword(password []byte) (*PasswordResult, error)
- func (r *NFCReader) SetCardPassword(password []byte, opts PasswordOptions) (*PasswordResult, error)
- func (r *NFCReader) SetClassicKeys(keys [][]byte)
- func (r *NFCReader) SetMode(mode ReaderMode)
- func (r *NFCReader) Start()
- func (r *NFCReader) StatusUpdates() <-chan DeviceStatus
- func (r *NFCReader) Stop()
- func (r *NFCReader) Transceive(data []byte) ([]byte, error)
- func (r *NFCReader) WriteCardData(text string) error
- func (r *NFCReader) WriteMessageWithOptions(msg *NDEFMessage, opts WriteOptions) error
- func (r *NFCReader) WriteMessageWithResult(msg *NDEFMessage, opts WriteOptions) (*WriteResult, error)
- type PasswordOptions
- type PasswordResult
- type ReaderLister
- type ReaderMode
- type RealClock
- type RemoteDeviceChecker
- type RemoteManager
- type Tag
- type TagCache
- type TagCapabilities
- type TagCapabilityProvider
- type TagConnection
- type TagIdentifier
- type TagLocker
- type TagReader
- type TagTransceiver
- type TagType
- type TagWriteOptions
- type TagWriter
- type TextMessage
- type Ticker
- type Timer
- type WriteOptions
- type WriteResult
Constants ¶
const ( SW1Success = 0x90 SW2Success = 0x00 SW1MoreData = 0x61 // More data available SW1WrongLength = 0x6C // Wrong Le field )
APDU status words
const ( CLAStandard = 0x00 // Standard ISO7816-4 CLAPCSC = 0xFF // PC/SC pseudo-APDU (reader commands) CLADESFire = 0x90 // DESFire native command wrapper CLAProprietry = 0x80 // Proprietary commands )
Common APDU command classes
const ( INSGetUID = 0xCA // Get UID INSLoadKey = 0x82 // Load authentication key INSAuth = 0x86 // General authenticate INSReadBinary = 0xB0 // Read binary INSUpdateBin = 0xD6 // Update binary INSDirectCmd = 0x00 // Direct transmit (for wrapped commands) INSSelectFile = 0xA4 // Select file )
PC/SC pseudo-APDU instructions
const ( MIFAREKeyA = 0x60 MIFAREKeyB = 0x61 )
MIFARE key types
const ( DFCmdSelectApplication = 0x5A DFCmdGetApplicationIDs = 0x6A DFCmdGetFileIDs = 0x6F DFCmdReadData = 0xBD DFCmdWriteData = 0x3D DFCmdAuthenticate = 0x0A // Legacy DES auth DFCmdAuthenticateISO = 0x1A // 3DES auth DFCmdAuthenticateAES = 0xAA // AES auth DFCmdGetVersion = 0x60 DFCmdAdditionalFrame = 0xAF )
DESFire native command codes
const ( MaxRetries = 5 BaseDelay = 500 * time.Millisecond MaxReconnectTries = 10 ReconnectDelay = time.Second * 2 DeviceCheckInterval = time.Second * 2 // Interval to check for new devices DeviceEnumRetries = 3 // Number of retries for device enumeration )
Constants for NFC operations
const ( ManagerTypeHardware = "hardware" ManagerTypeSmartphone = "smartphone" )
Manager type constants for identifying different manager implementations
const ( CardTypeMifareClassic1K = "MIFARE Classic 1K" CardTypeMifareClassic4K = "MIFARE Classic 4K" CardTypeMifareUltralight = "MIFARE Ultralight" CardTypeNtag213 = "NTAG213" CardTypeNtag215 = "NTAG215" CardTypeNtag216 = "NTAG216" CardTypeDesfire = "DESFire" CardTypeType4 = "Type4" )
Card type constants for card type identification and filtering
const ( // KeyTypeA is used for MIFARE Classic Key A authentication KeyTypeA = 0x60 // KeyTypeB is used for MIFARE Classic Key B authentication KeyTypeB = 0x61 )
MIFARE Classic key type constants for authentication
const ( DefaultPollingInterval = 100 * time.Millisecond DeviceIdleCheckInterval = 200 * time.Millisecond WriteCheckInterval = 50 * time.Millisecond CardCheckTickerInterval = 250 * time.Millisecond DeviceResetWaitTime = 3 * time.Second DeviceErrorCooldownPeriod = 10 * time.Second MaxRetriesCooldownPeriod = 30 * time.Second PostErrorPauseTime = 1 * time.Second UnhandledErrorRetryInterval = 1 * time.Second )
Polling intervals
const ( // DefaultMaxWriteAttempts is the number of write+verify attempts made on a // single write operation before giving up, when WriteOptions.MaxWriteAttempts // is not set. DefaultMaxWriteAttempts = 3 // WriteRetryBackoff is the base delay between write retries. The delay grows // linearly with the attempt number (backoff, 2*backoff, ...). WriteRetryBackoff = 50 * time.Millisecond )
Write reliability defaults.
const ( TLVNull = 0x00 // Null TLV TLVLockCtrl = 0x01 // Lock Control TLV TLVMemCtrl = 0x02 // Memory Control TLV TLVNDEF = 0x03 // NDEF Message TLV TLVProprietary = 0xFD // Proprietary TLV TLVTerminator = 0xFE // Terminator TLV )
TLV types for NDEF
Variables ¶
var ( // ErrTimeout indicates a timeout occurred during device communication ErrTimeout = errors.New("device operation timed out") // ErrDeviceClosed indicates the device connection was closed ErrDeviceClosed = errors.New("device closed") // ErrIO indicates an input/output error with the device ErrIO = errors.New("device I/O error") // ErrDeviceConfig indicates a device configuration error ErrDeviceConfig = errors.New("device configuration error") // ErrCooldownRequired indicates the device needs a cooldown period ErrCooldownRequired = errors.New("device cooldown required") // ErrACR122Specific indicates an ACR122-specific error requiring cooldown ErrACR122Specific = errors.New("ACR122 device error") )
Sentinel errors for device operations
var ( // KeyDefault is the factory default key (all 0xFF) KeyDefault = []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} // KeyNFCForum is the NFC Forum public key for NDEF KeyNFCForum = []byte{0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7} // KeyMAD is the MAD (MIFARE Application Directory) key KeyMAD = []byte{0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5} )
Common MIFARE Classic keys
var DefaultKeyA = [6]byte{0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}
DefaultKeyA is the MIFARE Application default key A.
var DefaultKeyB = [6]byte{0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}
DefaultKeyB is the NFC Forum default key B.
var DefaultKeys = [][6]byte{
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
{0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7},
{0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5},
{0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5},
{0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd},
{0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a},
{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
}
DefaultKeys is a list of common MIFARE keys to try for authentication.
var FactoryKey = [6]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
FactoryKey is the MIFARE Classic factory default key.
var PublicKey = DefaultKeyB
PublicKey is a common public key for NDEF applications, often the same as DefaultKeyB.
Functions ¶
func AssertCapabilitiesConsistent ¶ added in v1.0.3
AssertCapabilitiesConsistent verifies that a tag's declared TagCapabilities agree with the tag's query methods, returning a descriptive error on the first mismatch (nil if consistent). It is intended for implementers' unit tests to catch capability drift between Capabilities() and behavior.
It performs ONLY non-mutating (read-only) checks and never calls WriteData, Transceive, or MakeReadOnly, since those may perform real or irreversible I/O on hardware. Specifically it checks:
- Capabilities().CanLock matches CanMakeReadOnly()
- When Capabilities().IsReadOnly is true, IsWritable() reports false
Supported write/transceive/lock behavior cannot be auto-verified without device I/O; cover those directly in your own tests.
func BytesToHex ¶
BytesToHex converts bytes to uppercase hex string
func BytesToUint16 ¶
BytesToUint16 converts big-endian bytes to uint16
func CanTagRead ¶
CanTagRead checks if a tag supports read operations.
func CanTagTransceive ¶
CanTagTransceive checks if a tag supports raw transceive operations.
func CanTagWrite ¶
CanTagWrite checks if a tag supports write operations.
func DESFireAdditionalFrameAPDU ¶
DESFireAdditionalFrameAPDU returns APDU for sending additional frame data
func DESFireAuthAPDU ¶
DESFireAuthAPDU returns APDU for authentication
func DESFireGetAppIDsAPDU ¶
func DESFireGetAppIDsAPDU() []byte
DESFireGetAppIDsAPDU returns APDU for listing application IDs
func DESFireGetFileIDsAPDU ¶
func DESFireGetFileIDsAPDU() []byte
DESFireGetFileIDsAPDU returns APDU for listing file IDs
func DESFireReadDataAPDU ¶
DESFireReadDataAPDU returns APDU for reading file data
func DESFireSelectAppAPDU ¶
DESFireSelectAppAPDU returns APDU for selecting a DESFire application
func DESFireWrapAPDU ¶
DESFireWrapAPDU wraps a DESFire native command in ISO7816 APDU
func DESFireWriteDataAPDU ¶
DESFireWriteDataAPDU returns APDU for writing file data
func DirectTransmitAPDU ¶
DirectTransmitAPDU wraps a command for direct transmission to the card Used for native commands (e.g., Ultralight READ, WRITE)
func EncodeNdefMessageWithTextRecord ¶
EncodeNdefMessageWithTextRecord creates an NDEF message containing a single Text Record.
func GetAllCardTypes ¶
func GetAllCardTypes() []string
GetAllCardTypes returns all supported card type constants
func GetLengthFieldSize ¶
GetLengthFieldSize returns the size of the TLV length field.
func GetVersionAPDU ¶
func GetVersionAPDU() []byte
GetVersionAPDU returns the APDU for getting NTAG/Ultralight version This is wrapped in a direct transmit command
func HexToBytes ¶
HexToBytes converts a hex string to bytes
func IsACR122Error ¶
func IsAuthError ¶
IsAuthError checks if an error indicates authentication failure.
func IsCapacityExceededError ¶ added in v1.0.3
IsCapacityExceededError checks if an error indicates the data exceeded the tag's usable NDEF capacity.
func IsCardRemovedError ¶
IsCardRemovedError checks if an error indicates the card was removed during operation. This requires device reconnection to detect new cards. All card removal errors are created via NewCardRemovedError() at the device layer.
func IsDeviceClosedError ¶
func IsDeviceConfigError ¶
func IsNoCardError ¶
IsNoCardError checks if an error indicates no card is present in the reader. This is a normal condition and should not be logged as a device error.
func IsNotSupportedError ¶
IsNotSupportedError checks if an error indicates an unsupported operation.
func IsReadOnlyError ¶ added in v1.0.3
IsReadOnlyError checks if an error indicates the tag is read-only.
func IsRemoteDevice ¶ added in v1.1.3
IsRemoteDevice reports whether a device path names a phone rather than a reader. A pinned path that does can never be opened as a reader, so it is worth recognizing before it becomes a connection retried forever.
func IsTagRemovedError ¶
IsTagRemovedError checks if an error indicates the tag was removed.
func IsTimeoutError ¶
func IsUnsupportedTagError ¶
IsUnsupportedTagError checks if an error indicates the tag type is not supported.
func IsWriteError ¶ added in v1.0.3
IsWriteError checks if an error indicates a write failure.
func ListReaders ¶ added in v1.1.3
ListReaders returns the devices that can serve as this agent's reader, falling back to every device a manager knows for one that draws no distinction.
func LoadKeyAPDU ¶
LoadKeyAPDU returns the APDU for loading a key into reader memory keySlot: 0x00-0x1F for volatile, 0x20+ for non-volatile
func MIFAREAuthAPDU ¶
MIFAREAuthAPDU returns the APDU for MIFARE authentication block: block number to authenticate keyType: MIFAREKeyA (0x60) or MIFAREKeyB (0x61) keySlot: slot where key was loaded
func MakeTextRecordPayload ¶
MakeTextRecordPayload creates an NDEF Text Record payload with the specified text and language code.
func MakeURIRecordPayload ¶
MakeURIRecordPayload creates the payload for an NDEF URI record. It selects the longest matching NFC Forum abbreviation prefix to minimize the bytes written to the tag (URI capacity is scarce on small tags).
func NewCardRemovedError ¶
NewCardRemovedError creates a card removed error.
func NewUnsupportedTagError ¶
NewUnsupportedTagError creates an unsupported tag error.
func ParseNdefMessageForTextRecord ¶
ParseNdefMessageForTextRecord parses an NDEF message and returns the text from the first Text Record. This is a convenience function that uses the record-based parsing internally.
func ParseNdefMessageForURIRecord ¶
ParseNdefMessageForURIRecord parses an NDEF message and returns the URI from the first URI Record. This is a convenience function that uses the record-based parsing internally.
func ParseTLVBlock ¶
ParseTLVBlock parses all TLVs in a block and returns a map of type -> value Useful for parsing Capability Container TLVs
func ReadBinaryAPDU ¶
ReadBinaryAPDU returns the APDU for reading binary data For MIFARE: block/page number in P2, length in Le
func ReadBinaryExtAPDU ¶
ReadBinaryExtAPDU returns an extended APDU for reading with 2-byte offset
func SelectFileAPDU ¶
SelectFileAPDU returns the APDU for selecting a file by ID
func SelectFileByAIDAPDU ¶
SelectFileByAIDAPDU returns the APDU for selecting application by AID
func TLVDecode ¶
TLVDecode decodes a TLV structure and returns the value and type It skips Null TLVs and stops at the first non-null TLV or Terminator
func TLVEncode ¶
TLVEncode encodes data into TLV format For NDEF, use type = 0x03 (TLVNDEF) Returns: [Type][Length][Value][Terminator (0xFE)]
func TLVFindNDEF ¶
TLVFindNDEF finds the NDEF Message TLV in a TLV block Returns the NDEF message data and true if found, nil and false otherwise
func TLVGetLength ¶
TLVGetLength extracts the length from a TLV record data should start at the type byte
func TLVRecordLength ¶
TLVRecordLength returns the field length start offset and field value start offset relative to the start of the TLV record (including type byte) fls: offset where length field starts (1 for type byte) fvs: offset where value starts Returns (0, 0) if the TLV is malformed
func Uint16ToBytes ¶
Uint16ToBytes converts uint16 to big-endian bytes
func UltralightReadAPDU ¶
UltralightReadAPDU returns the native Ultralight READ command (wrapped) Reads 4 pages (16 bytes) starting from the specified page
func UltralightWriteAPDU ¶
UltralightWriteAPDU returns the native Ultralight WRITE command (wrapped) Writes 4 bytes to the specified page
func UpdateBinaryAPDU ¶
UpdateBinaryAPDU returns the APDU for writing binary data For MIFARE: block/page number in P2
func UpdateBinaryExtAPDU ¶
UpdateBinaryExtAPDU returns an extended APDU for writing with 2-byte offset
func WireError ¶ added in v1.1.0
func WireError(err error) protocol.ErrorPayload
WireError projects an error onto the wire taxonomy. An NFCError carries its code, operation, and tag through; anything else lands on UNKNOWN_ERROR, which is not retryable — an error we cannot classify is not one we should encourage a device to repeat.
Types ¶
type APDUResponse ¶
APDUResponse represents a parsed APDU response
func ParseAPDUResponse ¶
func ParseAPDUResponse(raw []byte) (APDUResponse, error)
ParseAPDUResponse parses a raw response into APDUResponse
func (APDUResponse) Error ¶
func (r APDUResponse) Error() error
Error returns an error if the response is not successful
func (APDUResponse) HasMoreData ¶
func (r APDUResponse) HasMoreData() bool
HasMoreData returns true if more data is available (SW1=61)
func (APDUResponse) IsSuccess ¶
func (r APDUResponse) IsSuccess() bool
IsSuccess returns true if the response indicates success (SW1=90, SW2=00)
func (APDUResponse) StatusWord ¶
func (r APDUResponse) StatusWord() uint16
StatusWord returns the 2-byte status word as uint16
type AdvancedWriter ¶
type AdvancedWriter interface {
WriteDataWithOptions(data []byte, opts TagWriteOptions) error
}
AdvancedWriter is an optional interface that tags can implement to support write operations with options. If a tag implements this interface, the reader will use WriteDataWithOptions instead of WriteData when options are provided.
type BaseTag ¶ added in v1.0.3
type BaseTag struct{}
BaseTag provides default implementations of the optional Tag behaviors so custom tag types only need to implement the parts they actually support.
Embed BaseTag in your tag struct and override the methods your tag supports. The defaults are safe: connection management is a no-op, and write/transceive/lock operations report "not supported". You still must implement the universally-required identity and read methods yourself, since no sensible default exists for them:
- UID() string
- Type() string
- NumericType() int
- ReadData() ([]byte, error)
This mirrors the capability-based philosophy: advertise what you support via Capabilities() (implementing TagCapabilityProvider) and only override the methods backing those capabilities.
Example — a read-only tag needs four methods, not eleven:
type MyTag struct {
nfc.BaseTag
uid string
data []byte
}
func (t *MyTag) UID() string { return t.uid }
func (t *MyTag) Type() string { return "MyTag" }
func (t *MyTag) NumericType() int { return 0 }
func (t *MyTag) ReadData() ([]byte, error) { return t.data, nil }
// Connect/Disconnect/WriteData/Transceive/IsWritable/CanMakeReadOnly/
// MakeReadOnly are inherited from BaseTag.
func (BaseTag) CanMakeReadOnly ¶ added in v1.0.3
func (BaseTag) Disconnect ¶ added in v1.0.3
func (BaseTag) IsWritable ¶ added in v1.0.3
func (BaseTag) MakeReadOnly ¶ added in v1.0.3
type Card ¶
type Card struct {
// Metadata about the card
UID string `json:"uid"` // Unique identifier of the card
Type string `json:"type"` // Human-readable type (e.g., "MIFARE Classic 1K", "Type4")
Technology string `json:"technology"` // Technology family (e.g., "ISO14443A", "ISO14443B")
ScannedAt time.Time `json:"scanned_at"` // When the card was detected
LastAccessed time.Time `json:"last_accessed"` // Last read/write operation time
MessageData Message `json:"message_data,omitempty"` // Cached message data, if any
// contains filtered or unexported fields
}
Card represents a detected NFC card with its metadata and provides io.Reader and io.Writer interfaces for reading and writing NDEF data.
Example usage:
card, err := reader.Scan()
if err != nil {
log.Fatal(err)
}
// Read data
data, _ := io.ReadAll(card)
fmt.Printf("Card UID: %s, Type: %s, Data: %s\n", card.UID, card.Type, data)
// Write data
card.Reset()
io.WriteString(card, "Hello NFC!")
card.Close()
func NewCard ¶
NewCard creates an Card from a Tag. This is an internal constructor used by the reader/manager.
func (*Card) Capabilities ¶ added in v1.0.3
func (c *Card) Capabilities() TagCapabilities
Capabilities reports what operations the card's tag supports (memory, writability, lock/password support, read-only state). When the underlying tag is available it is queried directly; otherwise capabilities are inferred from the tag type string.
func (*Card) Flush ¶
Flush writes the buffered data to the card immediately without closing. The buffer is cleared after a successful write.
func (*Card) GetUnderlyingTag ¶
GetUnderlyingTag returns the underlying Tag for advanced operations. Use this only when you need tag-specific functionality not available through the standard io.Reader/Writer interface.
Example for MIFARE Classic specific operations:
if classicTag, ok := card.GetUnderlyingTag().(ClassicTag); ok {
data, err := classicTag.Read(1, 0, key, keyType)
}
func (*Card) Read ¶
Read implements io.Reader. Reads NDEF message data from the card. The first call to Read() fetches the entire NDEF message from the card. Subsequent calls stream from the cached data.
Example:
data, err := io.ReadAll(card)
if err != nil {
log.Fatal(err)
}
func (*Card) ReadMessage ¶
ReadMessage reads and decodes a message from the card. It attempts to parse as NDEF first, falling back to TextMessage (raw bytes) if that fails.
Example:
msg, err := card.ReadMessage()
switch m := msg.(type) {
case *nfc.NDEFMessage:
text, _ := m.GetText()
case *nfc.TextMessage:
raw := m.Data
}
func (*Card) Reset ¶
func (c *Card) Reset()
Reset clears the read cache, allowing fresh data to be read from the card. Useful if you want to re-read after writing or if the card's data may have changed.
func (*Card) Write ¶
Write implements io.Writer. Buffers data to be written to the card. The actual write to the card happens on Close() or Flush().
Example:
n, err := card.Write([]byte("Hello World"))
// or
io.WriteString(card, "Hello World")
func (*Card) WriteMessage ¶
WriteMessage encodes and writes a message to the card.
Example:
msg := nfc.NewTextMessage("Hello!", "en")
err := card.WriteMessage(msg)
type CardTransport ¶ added in v1.0.3
CardTransport is the hardware boundary every PC/SC tag talks through: it sends an APDU and reports card presence. *pcscDevice satisfies it in production; an in-memory emulator satisfies it in tests (see package nfctest), letting the real tag I/O logic (page math, lock bytes, TLV) run against emulated silicon without hardware. Wrap one in a driver with NewEmulatedTag.
type ClassicTag ¶
type ClassicTag interface {
Tag
// Read reads a 16-byte block from the specified sector using the provided key.
// sector: sector number (0-15 for 1K, 0-39 for 4K)
// block: block within sector (0-2 for data blocks, 3 is sector trailer)
// key: 6-byte authentication key
// keyType: KeyTypeA or KeyTypeB
Read(sector, block uint8, key []byte, keyType int) ([]byte, error)
// Write writes 16 bytes to the specified block using the provided key.
// sector: sector number (0-15 for 1K, 0-39 for 4K)
// block: block within sector (0-2 for data blocks, 3 is sector trailer)
// data: exactly 16 bytes to write
// key: 6-byte authentication key
// keyType: KeyTypeA or KeyTypeB
Write(sector, block uint8, data []byte, key []byte, keyType int) error
}
ClassicTag provides MIFARE Classic specific operations. This interface extends Tag with sector/block-level access using authentication keys.
MIFARE Classic tags have a sector-based memory structure:
- Classic 1K: 16 sectors × 4 blocks (64 blocks total)
- Classic 4K: 32 sectors × 4 blocks + 8 sectors × 16 blocks (256 blocks total)
Each sector has a trailer block containing keys and access conditions. Blocks are 16 bytes each.
Example:
if classic, ok := tag.(nfc.ClassicTag); ok {
key := []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
data, err := classic.Read(1, 0, key, nfc.KeyTypeA)
if err != nil {
log.Fatal(err)
}
}
type Clock ¶
type Clock interface {
// Now returns the current time
Now() time.Time
// Sleep pauses execution for the given duration
Sleep(d time.Duration)
// NewTicker creates a new ticker that will send on its channel
// at intervals specified by the duration
NewTicker(d time.Duration) Ticker
// NewTimer creates a new timer that will send on its channel
// after the specified duration
NewTimer(d time.Duration) Timer
// After returns a channel that will receive a value after the duration
After(d time.Duration) <-chan time.Time
}
Clock provides an abstraction over time operations to enable testing without real time delays.
type DetectedTagType ¶
type DetectedTagType int
DetectedTagType represents detected tag type from ATR/commands
const ( DetectedUnknown DetectedTagType = iota DetectedClassic1K DetectedClassic4K DetectedMini DetectedUltralight DetectedUltralightC DetectedUltralightEV1 DetectedNTAG213 DetectedNTAG215 DetectedNTAG216 DetectedDESFire DetectedDESFireEV1 DetectedDESFireEV2 DetectedISO14443_4 DetectedPlus2K DetectedPlus4K )
Detected tag type constants for PC/SC detection
type Device ¶
type Device interface {
Close() error
String() string
Connection() string
Transceive(txData []byte) ([]byte, error)
GetTags() ([]Tag, error)
}
Device represents an NFC reader/writer hardware device.
A Device is obtained from a Manager and provides low-level access to NFC communication capabilities. Devices are returned ready-to-use from Manager.OpenDevice() - no additional initialization is required.
Example:
manager := nfc.NewManager()
device, err := manager.OpenDevice("")
defer device.Close()
type DeviceCapabilities ¶
type DeviceCapabilities struct {
// Communication capabilities
CanTransceive bool `json:"canTransceive"`
CanPoll bool `json:"canPoll"`
// Supported tag types
SupportedTagTypes []string `json:"supportedTagTypes,omitempty"`
// Hardware info
DeviceType string `json:"deviceType"` // "libnfc", "smartphone", etc.
MaxBaudRate int `json:"maxBaudRate,omitempty"` // Max baud rate in bps
// Event capabilities
SupportsEvents bool `json:"supportsEvents"` // Tag arrival/removal events
}
DeviceCapabilities describes what operations a device supports.
func BuildDeviceCapabilities ¶
func BuildDeviceCapabilities(device Device) DeviceCapabilities
BuildDeviceCapabilities constructs a DeviceCapabilities struct by checking which interfaces the device implements.
func GetDeviceCapabilities ¶
func GetDeviceCapabilities(device Device) DeviceCapabilities
GetDeviceCapabilities returns capabilities for any Device. Capabilities are built by checking which interfaces the device implements.
type DeviceChangeNotifier ¶
type DeviceChangeNotifier interface {
// DeviceChanges returns a channel that signals when devices are added or removed.
DeviceChanges() <-chan struct{}
}
DeviceChangeNotifier is optionally implemented by Managers that support notifying when devices are added or removed.
type DeviceEvent ¶
type DeviceEvent struct {
Type DeviceEventType
Timestamp time.Time
Device Device // nil if disconnected
Message string // Human-readable description
Err error // Associated error, if any
}
DeviceEvent represents a device lifecycle event
type DeviceEventEmitter ¶
type DeviceEventEmitter interface {
SupportsEvents() bool
}
DeviceEventEmitter is a marker interface for devices that emit tag events (e.g., tag arrival/removal) rather than requiring polling.
type DeviceEventType ¶
type DeviceEventType int
DeviceEventType categorizes device lifecycle events
const ( // DeviceConnected indicates successful device connection DeviceConnected DeviceEventType = iota // DeviceDisconnected indicates device was disconnected DeviceDisconnected // DeviceReconnecting indicates an automatic reconnection attempt is starting DeviceReconnecting // DeviceReconnectFailed indicates a reconnection attempt failed DeviceReconnectFailed // CooldownStarted indicates device entered cooldown period CooldownStarted // CooldownEnded indicates cooldown period completed CooldownEnded // DeviceError indicates a recoverable device error occurred DeviceError )
func (DeviceEventType) String ¶
func (et DeviceEventType) String() string
String returns the event type as a string
type DeviceHealthChecker ¶
type DeviceHealthChecker interface {
IsHealthy() error
}
DeviceHealthChecker is an optional interface for devices that support health/connectivity checks. Use type assertion to check if a device implements this interface.
Example:
if checker, ok := device.(DeviceHealthChecker); ok {
if err := checker.IsHealthy(); err != nil {
// Device is not responding, handle reconnection
}
}
type DeviceInfoProvider ¶
DeviceInfoProvider provides device metadata for capability building. Implement this interface to provide device-specific information.
type DeviceManager ¶
type DeviceManager struct {
// contains filtered or unexported fields
}
DeviceManager handles device lifecycle, connection management, and reconnection logic. It maintains a connection to a single NFC device and handles recovery from errors.
func NewDeviceManager ¶
func NewDeviceManager(manager Manager, devicePath string, clock Clock) *DeviceManager
NewDeviceManager creates a new DeviceManager for managing an NFC device connection. If clock is nil, a RealClock is used by default.
func (*DeviceManager) Close ¶
func (dm *DeviceManager) Close()
Close closes the current device connection.
func (*DeviceManager) CooldownChannel ¶
func (dm *DeviceManager) CooldownChannel() <-chan time.Time
CooldownChannel returns the cooldown timer channel for select statements.
func (*DeviceManager) Device ¶
func (dm *DeviceManager) Device() Device
Device returns the current active device, or nil if not connected.
func (*DeviceManager) DevicePath ¶
func (dm *DeviceManager) DevicePath() string
DevicePath returns the path of the device being managed.
func (*DeviceManager) EndCooldown ¶
func (dm *DeviceManager) EndCooldown(stopChan <-chan struct{})
EndCooldown ends the current cooldown period and attempts to reconnect.
func (*DeviceManager) EnsureConnected ¶
func (dm *DeviceManager) EnsureConnected(stopChan <-chan struct{}) error
EnsureConnected ensures the device is connected and responsive. If not connected, attempts to connect. If in cooldown, returns an error. This method manages internal retry state for the device manager.
func (*DeviceManager) Events ¶
func (dm *DeviceManager) Events() <-chan DeviceEvent
Events returns a read-only channel for device lifecycle events.
func (*DeviceManager) ForceReconnect ¶
func (dm *DeviceManager) ForceReconnect(stopChan <-chan struct{}) error
ForceReconnect attempts to force reconnect with device reset wait time.
func (*DeviceManager) HandleError ¶
func (dm *DeviceManager) HandleError(err error, stopChan <-chan struct{}) (needsCooldown bool)
HandleError processes device errors and determines the appropriate recovery action. Returns whether a cooldown was initiated. Retry state is now managed internally.
func (*DeviceManager) HasDevice ¶
func (dm *DeviceManager) HasDevice() bool
HasDevice returns true if a device is currently connected.
func (*DeviceManager) InCooldown ¶
func (dm *DeviceManager) InCooldown() bool
InCooldown returns true if the device manager is in a cooldown period.
func (*DeviceManager) Manager ¶ added in v1.0.1
func (dm *DeviceManager) Manager() Manager
Manager returns the underlying NFC manager for device discovery.
func (*DeviceManager) Reconnect ¶
func (dm *DeviceManager) Reconnect(stopChan <-chan struct{}) error
Reconnect attempts to reconnect to the device with exponential backoff.
func (*DeviceManager) SetDevicePath ¶ added in v1.0.1
func (dm *DeviceManager) SetDevicePath(path string)
SetDevicePath sets the device path to use for connections.
func (*DeviceManager) TryConnect ¶
func (dm *DeviceManager) TryConnect() error
TryConnect attempts to connect to the device. If the device is already connected and responsive, it returns nil. Otherwise, it attempts to open and initialize the device.
type DeviceStatus ¶
DeviceStatus represents the status of the NFC device. This type might be used by the main application to display status.
type DeviceTransceiver ¶ added in v1.0.3
type DeviceTransceiver interface {
SupportsTransceive() bool
}
DeviceTransceiver is an optional interface that lets a device declare whether it actually supports raw Transceive. Devices that do not implement it default to CanTransceive=true (the common case for polling hardware readers). Implement this to report false when your device's Transceive returns a NotSupported error, so GetDeviceCapabilities reflects reality.
type ErrorCode ¶
type ErrorCode int
ErrorCode represents a specific type of NFC error for programmatic handling.
func GetErrorCode ¶
GetErrorCode extracts the ErrorCode from an error if it's an NFCError. Returns 0 if the error is not an NFCError.
func InternalErrorCode ¶ added in v1.1.0
InternalErrorCode maps a wire code back to an internal one, for outcomes reported by a remote device. Codes with no internal equivalent — protocol faults, or a device sending something we do not know — fall back to the caller's own notion of what failed.
type FakeClock ¶
type FakeClock struct {
// contains filtered or unexported fields
}
FakeClock implements Clock for testing with controllable time
func NewFakeClock ¶
NewFakeClock creates a new FakeClock starting at the given time
type LockResult ¶ added in v1.0.3
type LockResult struct {
// UID of the tag that was locked.
UID string `json:"uid"`
// TagType is the human-readable tag type string.
TagType string `json:"tagType"`
// Locked is true when the tag was made permanently read-only.
Locked bool `json:"locked"`
}
LockResult describes the outcome of a make-read-only (lock) operation.
type Manager ¶
type Manager interface {
OpenDevice(deviceStr string) (Device, error)
ListDevices() ([]string, error)
}
Manager handles NFC device discovery.
Manager provides methods to list available NFC readers and open connections to devices.
Example:
manager := nfc.NewManager() devices, _ := manager.ListDevices() device, _ := manager.OpenDevice(devices[0]) tags, _ := device.GetTags()
func NewManager ¶
func NewManager() Manager
NewManager creates a new Manager using the PC/SC implementation.
Example:
manager := nfc.NewManager()
type Message ¶
type Message interface {
// Encode converts the message to bytes for writing to card
Encode() ([]byte, error)
// Type returns the message type for debugging
Type() string
}
Message represents data that can be written to/read from a card. Different implementations handle different encoding schemes.
type MockClassicTag ¶
type MockClassicTag struct {
*MockTag
// BlockData stores data for each sector/block combination
// Key format: "sector:block" (e.g., "1:0")
BlockData map[string][]byte
// ReadError, if set, will be returned by Read()
ReadError error
// WriteError, if set, will be returned by Write()
WriteError error
// contains filtered or unexported fields
}
MockClassicTag is a test implementation of ClassicTag for MIFARE Classic tags.
func NewMockClassicTag ¶
func NewMockClassicTag(uid string) *MockClassicTag
NewMockClassicTag creates a new MockClassicTag with default values.
func (*MockClassicTag) GetBlockData ¶
func (m *MockClassicTag) GetBlockData(sector, block uint8) ([]byte, bool)
GetBlockData retrieves the data for a specific sector/block combination.
func (*MockClassicTag) SetBlockData ¶
func (m *MockClassicTag) SetBlockData(sector, block uint8, data []byte)
SetBlockData sets the data for a specific sector/block combination.
type MockDevice ¶
type MockDevice struct {
// DeviceName is the simulated device name returned by String()
DeviceName string
// DeviceConnection is the simulated connection string returned by Connection()
DeviceConnection string
// IsOpen tracks whether the device is currently open
IsOpen bool
// InitError, if set, will be returned by IsHealthy()
InitError error
// CloseError, if set, will be returned by Close()
CloseError error
// TransceiveFunc allows custom transceive behavior for testing
// If nil, returns TransceiveResponse or TransceiveError
TransceiveFunc func([]byte) ([]byte, error)
// TransceiveResponse is the default response for Transceive calls
TransceiveResponse []byte
// TransceiveError, if set, will be returned by Transceive()
TransceiveError error
// GetTagsFunc allows custom GetTags behavior for testing
// If nil, returns Tags or GetTagsError
GetTagsFunc func() ([]Tag, error)
// Tags is the list of tags returned by GetTags()
Tags []Tag
// GetTagsError, if set, will be returned by GetTags()
GetTagsError error
// CallLog tracks all method calls for verification in tests
CallLog []string
// MockDeviceType allows overriding the device type (default: "mock")
MockDeviceType string
// MockSupportedTagTypes allows overriding supported tag types
MockSupportedTagTypes []string
// MockSupportsEvents makes the device report as event-based (like smartphone)
MockSupportsEvents bool
// contains filtered or unexported fields
}
MockDevice is a test implementation of Device that simulates NFC hardware.
MockDevice allows testing NFC functionality without physical hardware by simulating device behavior, connection states, and data transmission. It also implements DeviceHealthChecker for health check simulation.
Example:
mock := &MockDevice{
DeviceName: "Mock NFC Reader",
DeviceConnection: "mock:usb:001",
}
tags, err := mock.GetTags()
func NewMockDevice ¶
func NewMockDevice() *MockDevice
NewMockDevice creates a new MockDevice with default values.
func (*MockDevice) AddTag ¶
func (m *MockDevice) AddTag(tag Tag)
AddTag adds a tag to the list returned by GetTags().
func (*MockDevice) ClearCallLog ¶
func (m *MockDevice) ClearCallLog()
ClearCallLog clears the call log.
func (*MockDevice) ClearTags ¶
func (m *MockDevice) ClearTags()
ClearTags removes all tags from the list returned by GetTags().
func (*MockDevice) Connection ¶
func (m *MockDevice) Connection() string
Connection returns the simulated connection string.
func (*MockDevice) DeviceType ¶
func (m *MockDevice) DeviceType() string
DeviceType returns the device type (implements DeviceInfoProvider).
func (*MockDevice) GetCallLog ¶
func (m *MockDevice) GetCallLog() []string
GetCallLog returns a copy of the call log for verification.
func (*MockDevice) GetTags ¶
func (m *MockDevice) GetTags() ([]Tag, error)
GetTags simulates detecting tags on the device.
func (*MockDevice) IsHealthy ¶
func (m *MockDevice) IsHealthy() error
IsHealthy checks if the mock device is healthy (implements DeviceHealthChecker).
func (*MockDevice) SetTags ¶
func (m *MockDevice) SetTags(tags []Tag)
SetTags sets the tags that will be returned by GetTags().
func (*MockDevice) String ¶
func (m *MockDevice) String() string
String returns the simulated device name.
func (*MockDevice) SupportedTagTypes ¶
func (m *MockDevice) SupportedTagTypes() []string
SupportedTagTypes returns the supported tag types (implements DeviceInfoProvider).
func (*MockDevice) SupportsEvents ¶
func (m *MockDevice) SupportsEvents() bool
SupportsEvents returns whether this device emits events (implements DeviceEventEmitter).
func (*MockDevice) Transceive ¶
func (m *MockDevice) Transceive(txData []byte) ([]byte, error)
Transceive simulates data transmission with the device.
type MockISO14443Tag ¶
type MockISO14443Tag struct {
*MockTag
}
MockISO14443Tag is a test implementation of ISO14443Tag for Type 4 tags.
func NewMockISO14443Tag ¶
func NewMockISO14443Tag(uid string) *MockISO14443Tag
NewMockISO14443Tag creates a new MockISO14443Tag with default values.
type MockManager ¶
type MockManager struct {
// DevicesList is the list of device strings returned by ListDevices()
DevicesList []string
// ListDevicesError, if set, will be returned by ListDevices()
ListDevicesError error
// MockDevice is the device returned by OpenDevice()
// If nil, a new MockDevice will be created
MockDevice *MockDevice
// OpenDeviceError, if set, will be returned by OpenDevice()
OpenDeviceError error
// CallLog tracks all method calls for verification in tests
CallLog []string
// contains filtered or unexported fields
}
MockManager is a test implementation of Manager that simulates NFC device management.
MockManager allows testing device discovery and tag detection without physical hardware by providing configurable mock responses.
Example:
manager := &MockManager{
DevicesList: []string{"mock:usb:001", "mock:usb:002"},
MockDevice: NewMockDevice(),
}
devices, _ := manager.ListDevices()
func NewMockManager ¶
func NewMockManager() *MockManager
NewMockManager creates a new MockManager with default values.
func (*MockManager) ClearCallLog ¶
func (m *MockManager) ClearCallLog()
ClearCallLog clears the call log.
func (*MockManager) GetCallLog ¶
func (m *MockManager) GetCallLog() []string
GetCallLog returns a copy of the call log for verification.
func (*MockManager) ListDevices ¶
func (m *MockManager) ListDevices() ([]string, error)
ListDevices simulates listing available NFC devices.
func (*MockManager) OpenDevice ¶
func (m *MockManager) OpenDevice(deviceStr string) (Device, error)
OpenDevice simulates opening an NFC device.
type MockNtagTag ¶
type MockNtagTag struct {
*MockTag
// PageData stores data for each page (0-134 for NTAG215)
PageData map[byte][4]byte
// ReadPageError, if set, will be returned by ReadPage()
ReadPageError error
// WritePageError, if set, will be returned by WritePage()
WritePageError error
// MaxPages defines the maximum page number (default 135 for NTAG215)
MaxPages byte
// contains filtered or unexported fields
}
MockNtagTag is a test implementation of NtagTag for NTAG21x tags.
MockNtagTag simulates page-based memory operations for NTAG213/215/216 tags.
Example:
tag := NewMockNtagTag("04112233445566")
tag.Connect()
tag.WritePage(4, [4]byte{0x03, 0x04, 0xD1, 0x01})
data, _ := tag.ReadPage(4)
func NewMockNtagTag ¶
func NewMockNtagTag(uid string) *MockNtagTag
NewMockNtagTag creates a new MockNtagTag with NTAG215 defaults.
func (*MockNtagTag) ClearPageData ¶
func (m *MockNtagTag) ClearPageData()
ClearPageData clears all page data.
func (*MockNtagTag) GetPageData ¶
func (m *MockNtagTag) GetPageData(page byte) ([4]byte, bool)
GetPageData retrieves the data for a specific page.
func (*MockNtagTag) ReadPage ¶
func (m *MockNtagTag) ReadPage(page byte) ([4]byte, error)
ReadPage simulates reading a 4-byte page from the NTAG tag.
func (*MockNtagTag) SetPageData ¶
func (m *MockNtagTag) SetPageData(page byte, data [4]byte)
SetPageData sets the data for a specific page (bypasses write protection for testing).
type MockTag ¶
type MockTag struct {
// TagUID is the UID returned by UID()
TagUID string
// TagType is the type string returned by Type()
TagType string
// TagNumericType is the numeric type returned by NumericType()
TagNumericType int
// Data is the data returned by ReadData()
Data []byte
// ReadDataFunc allows custom ReadData behavior (e.g. simulating a verification
// mismatch or a transient read error). If nil, ReadData returns Data or
// ReadDataError. Called with the mock's lock held; must not re-enter the mock.
ReadDataFunc func() ([]byte, error)
// WriteDataFunc allows custom WriteData behavior (e.g. failing a fixed number
// of times before succeeding). If it returns nil, the data is still stored so
// a subsequent ReadData reflects the write. If nil, WriteData stores Data or
// returns WriteDataError. Called with the mock's lock held.
WriteDataFunc func([]byte) error
// ReadDataError, if set, will be returned by ReadData()
ReadDataError error
// WriteDataError, if set, will be returned by WriteData()
WriteDataError error
// TransceiveFunc allows custom transceive behavior
// If nil, returns TransceiveResponse or TransceiveError
TransceiveFunc func([]byte) ([]byte, error)
// TransceiveResponse is the default response for Transceive calls
TransceiveResponse []byte
// TransceiveError, if set, will be returned by Transceive()
TransceiveError error
// ConnectError, if set, will be returned by Connect()
ConnectError error
// DisconnectError, if set, will be returned by Disconnect()
DisconnectError error
// IsConnected tracks whether the tag is currently connected
IsConnected bool
// IsReadOnly tracks whether the tag is in read-only mode
IsReadOnly bool
// IsWritableFunc allows custom IsWritable behavior
// If nil, returns !IsReadOnly and IsWritableError
IsWritableFunc func() (bool, error)
// IsWritableError, if set, will be returned by IsWritable()
IsWritableError error
// MakeReadOnlyFunc allows custom MakeReadOnly behavior
// If nil, sets IsReadOnly to true or returns MakeReadOnlyError
MakeReadOnlyFunc func() error
// MakeReadOnlyError, if set, will be returned by MakeReadOnly()
MakeReadOnlyError error
// CanMakeReadOnlyFunc allows custom CanMakeReadOnly behavior
// If nil, returns !IsReadOnly and CanMakeReadOnlyError
CanMakeReadOnlyFunc func() (bool, error)
// CanMakeReadOnlyError, if set, will be returned by CanMakeReadOnly()
CanMakeReadOnlyError error
// CallLog tracks all method calls for verification in tests
CallLog []string
// MockCapabilities allows overriding the default capabilities
// If nil, capabilities are inferred from TagType
MockCapabilities *TagCapabilities
// contains filtered or unexported fields
}
MockTag is a test implementation of Tag that simulates NFC tag behavior.
MockTag allows testing tag operations without physical tags by providing configurable mock responses for read/write operations.
Example:
tag := &MockTag{
TagUID: "04A1B2C3",
TagType: "MIFARE Classic 1K",
Data: []byte{0x00, 0x01, 0x02},
}
data, _ := tag.ReadData()
func NewMockTag ¶
NewMockTag creates a new MockTag with default values.
func (*MockTag) CanMakeReadOnly ¶
CanMakeReadOnly simulates checking if the tag can be made read-only.
func (*MockTag) Capabilities ¶
func (m *MockTag) Capabilities() TagCapabilities
Capabilities returns the tag's capabilities. If MockCapabilities is set, returns that; otherwise infers from TagType.
func (*MockTag) Disconnect ¶
Disconnect simulates disconnecting from the tag.
func (*MockTag) GetCallLog ¶
GetCallLog returns a copy of the call log for verification.
func (*MockTag) IsWritable ¶
IsWritable simulates checking if the tag is writable.
func (*MockTag) MakeReadOnly ¶
MakeReadOnly simulates making the tag read-only.
func (*MockTag) NumericType ¶
NumericType returns the tag's numeric type.
func (*MockTag) Transceive ¶
Transceive simulates data exchange with the tag.
type NDEFEmpty ¶
type NDEFEmpty struct{}
NDEFEmpty represents a high-level empty record.
func (*NDEFEmpty) ToRecord ¶
func (e *NDEFEmpty) ToRecord() NDEFRecord
ToRecord converts NDEFEmpty to NDEFRecord.
type NDEFExternal ¶
NDEFExternal represents a high-level external type record.
func (*NDEFExternal) ToRecord ¶
func (e *NDEFExternal) ToRecord() NDEFRecord
ToRecord converts NDEFExternal to NDEFRecord.
type NDEFMIME ¶
NDEFMIME represents a high-level MIME type record.
func (*NDEFMIME) ToRecord ¶
func (m *NDEFMIME) ToRecord() NDEFRecord
ToRecord converts NDEFMIME to NDEFRecord.
type NDEFMessage ¶
type NDEFMessage struct {
// contains filtered or unexported fields
}
NDEFMessage represents a structured NDEF message with multiple records. This allows complex messages with multiple record types (text, URI, MIME, etc.)
func ConvertNDEFInput ¶
func ConvertNDEFInput(data *protocol.NDEFMessageInput) (*NDEFMessage, error)
ConvertNDEFInput converts protocol NDEF format to internal NDEFMessage.
func DecodeNDEF ¶
func DecodeNDEF(data []byte) (*NDEFMessage, error)
DecodeNDEF parses raw bytes into an NDEFMessage. Returns error if the data is not valid NDEF format.
func NewNDEFMessage ¶
func NewNDEFMessage() *NDEFMessage
NewNDEFMessage creates a new empty NDEF message.
func (*NDEFMessage) AddRecord ¶
func (m *NDEFMessage) AddRecord(record NDEFRecord) *NDEFMessage
AddRecord adds a raw NDEF record to the message.
func (*NDEFMessage) AddText ¶
func (m *NDEFMessage) AddText(text, langCode string) *NDEFMessage
AddText adds an NDEF Text Record to the message.
func (*NDEFMessage) AddURI ¶
func (m *NDEFMessage) AddURI(uri string) *NDEFMessage
AddURI adds an NDEF URI Record to the message.
func (*NDEFMessage) Encode ¶
func (m *NDEFMessage) Encode() ([]byte, error)
Encode converts the NDEF message to bytes.
func (*NDEFMessage) GetText ¶
func (m *NDEFMessage) GetText() (string, error)
GetText returns the text content from the first Text Record in the message.
func (*NDEFMessage) GetURI ¶
func (m *NDEFMessage) GetURI() (string, error)
GetURI returns the URI from the first URI Record in the message.
func (*NDEFMessage) Records ¶
func (m *NDEFMessage) Records() []NDEFRecord
Records returns the list of NDEF records in this message.
func (*NDEFMessage) ToBuilder ¶
func (m *NDEFMessage) ToBuilder() *NDEFMessageBuilder
ToBuilder converts a low-level NDEFMessage into a high-level NDEFMessageBuilder. This allows editing existing messages in a declarative way.
Example:
// Read existing message
msg, _ := card.ReadMessage()
ndefMsg := msg.(*nfc.NDEFMessage)
// Convert to builder for editing
builder := ndefMsg.ToBuilder()
builder.Records = append(builder.Records, &nfc.NDEFText{Content: "New text"})
// Build and write back
updated := builder.MustBuild()
card.WriteMessage(updated)
func (*NDEFMessage) ToJSONMap ¶
func (m *NDEFMessage) ToJSONMap() map[string]interface{}
ToJSONMap converts an NDEFMessage to a map suitable for JSON serialization. This is useful for building WebSocket/API responses.
func (*NDEFMessage) ToPayload ¶
func (m *NDEFMessage) ToPayload() *NDEFMessagePayload
ToPayload converts an NDEFMessage to a JSON-friendly payload structure. This method extracts human-readable content (text, URI) from each record and returns a structure suitable for WebSocket/API responses.
type NDEFMessageBuilder ¶
type NDEFMessageBuilder struct {
Records []NDEFRecordBuilder
}
NDEFMessageBuilder provides a declarative way to construct NDEF messages.
Example:
msg := &nfc.NDEFMessageBuilder{
Records: []nfc.NDEFRecordBuilder{
&nfc.NDEFText{Content: "Hello World", Language: "en"},
&nfc.NDEFURI{Content: "https://example.com"},
},
}.Build()
func (*NDEFMessageBuilder) Build ¶
func (b *NDEFMessageBuilder) Build() (*NDEFMessage, error)
Build transforms the high-level records into a low-level NDEFMessage.
func (*NDEFMessageBuilder) Encode ¶
func (b *NDEFMessageBuilder) Encode() ([]byte, error)
func (*NDEFMessageBuilder) MustBuild ¶
func (b *NDEFMessageBuilder) MustBuild() *NDEFMessage
MustBuild is like Build but panics on error.
func (*NDEFMessageBuilder) Type ¶
func (b *NDEFMessageBuilder) Type() string
type NDEFMessagePayload ¶
type NDEFMessagePayload struct {
Type string `json:"type"` // Message type: "ndef"
Records []NDEFRecordPayload `json:"records"` // Array of NDEF records
}
NDEFMessagePayload represents an NDEF message in JSON-friendly format.
type NDEFRaw ¶ added in v1.0.3
NDEFRaw represents a fully specified NDEF record for advanced or custom use cases where the caller provides the TNF, type, optional ID, and payload directly (e.g. proprietary external types or non-NDEF-Forum records).
func (*NDEFRaw) ToRecord ¶ added in v1.0.3
func (r *NDEFRaw) ToRecord() NDEFRecord
ToRecord converts NDEFRaw to NDEFRecord. The TNF is masked to its valid 3-bit range.
type NDEFRecord ¶
type NDEFRecord struct {
TNF byte // Type Name Format (0x00-0x07)
Type []byte // Record type (e.g., "T" for text, "U" for URI)
ID []byte // Optional record ID
Payload []byte // Record payload data
}
NDEFRecord represents a single NDEF record within a message.
func ConvertNDEFRecordInput ¶
func ConvertNDEFRecordInput(data protocol.NDEFRecordInput) (*NDEFRecord, error)
ConvertNDEFRecordInput converts protocol NDEF record to internal NDEFRecord.
func (*NDEFRecord) GetText ¶
func (r *NDEFRecord) GetText() (string, bool)
GetText extracts text from a Text Record (TNF=0x01, Type='T'). Returns (text, true) if this is a text record, or ("", false) otherwise.
func (*NDEFRecord) GetURI ¶
func (r *NDEFRecord) GetURI() (string, bool)
GetURI extracts URI from a URI Record (TNF=0x01, Type='U'). Returns (uri, true) if this is a URI record, or ("", false) otherwise.
func (*NDEFRecord) IsTextRecord ¶
func (r *NDEFRecord) IsTextRecord() bool
IsTextRecord returns true if this is a Text Record.
func (*NDEFRecord) IsURIRecord ¶
func (r *NDEFRecord) IsURIRecord() bool
IsURIRecord returns true if this is a URI Record.
type NDEFRecordBuilder ¶
type NDEFRecordBuilder interface {
ToRecord() NDEFRecord
}
NDEFRecordBuilder is an interface that can be converted to NDEFRecord.
type NDEFRecordPayload ¶
type NDEFRecordPayload struct {
Type string `json:"type"` // Record type: "text", "uri", etc. (human-readable)
Content string `json:"content,omitempty"` // Decoded content (text or URI)
Language string `json:"language,omitempty"` // Language code for text records
TNF uint8 `json:"tnf"` // Type Name Format (technical detail)
ID string `json:"id,omitempty"` // Record ID (optional)
Payload []byte `json:"payload"` // Raw payload data
}
NDEFRecordPayload represents an NDEF record in JSON-friendly format. This structure is used for serialization to WebSocket clients and API responses.
type NDEFSmartPoster ¶ added in v1.0.3
type NDEFSmartPoster struct {
URI string
Title string // Optional display title
Language string // Optional, defaults to "en" when Title is set
}
NDEFSmartPoster represents a high-level Smart Poster record: a URI with an optional human-readable title. It encodes as a Well Known "Sp" record whose payload is a nested NDEF message containing an optional Title (Text) record and a mandatory URI record. This is the most common "tap to open <label>" tag and is widely understood by phones.
func (*NDEFSmartPoster) ToRecord ¶ added in v1.0.3
func (s *NDEFSmartPoster) ToRecord() NDEFRecord
ToRecord converts NDEFSmartPoster to NDEFRecord.
type NDEFText ¶
NDEFText represents a high-level text record.
Example:
msg := &nfc.NDEFMessageBuilder{
Records: []nfc.NDEFRecordBuilder{
&nfc.NDEFText{Content: "Hello World", Language: "en"},
&nfc.NDEFURI{Content: "https://example.com"},
},
}
func (*NDEFText) ToRecord ¶
func (t *NDEFText) ToRecord() NDEFRecord
ToRecord converts NDEFText to NDEFRecord.
type NDEFURI ¶
type NDEFURI struct {
Content string
}
NDEFURI represents a high-level URI record.
func (*NDEFURI) ToRecord ¶
func (u *NDEFURI) ToRecord() NDEFRecord
ToRecord converts NDEFURI to NDEFRecord.
type NFCData ¶
type NFCData struct {
Card *Card // The detected card, nil if no card is present
Err error // Error that occurred during detection/reading
}
NFCData represents the data read from an NFC tag including any potential errors.
type NFCError ¶
type NFCError struct {
Code ErrorCode
Op string // Operation that failed (e.g., "ReadData", "Transceive")
TagUID string // Optional: UID of tag involved
Message string // Human-readable message
Cause error // Underlying error
}
NFCError provides structured error information for programmatic handling.
func NewAuthError ¶
NewAuthError creates an error for authentication failures.
func NewCapacityExceededError ¶ added in v1.0.3
NewCapacityExceededError creates an error for when the data to write is larger than the tag's usable NDEF capacity.
func NewNotSupportedError ¶
NewNotSupportedError creates an error for unsupported operations.
func NewReadError ¶
NewReadError creates an error for read failures.
func NewReadOnlyError ¶ added in v1.0.3
NewReadOnlyError creates an error for write attempts on a read-only tag.
func NewTagRemovedError ¶
NewTagRemovedError creates an error for when a tag is removed mid-operation.
func NewTransceiveError ¶
NewTransceiveError creates an error for transceive failures.
func NewWriteError ¶
NewWriteError creates an error for write failures.
type NFCReader ¶
type NFCReader struct {
// contains filtered or unexported fields
}
NFCReader manages NFC device interactions and broadcasts tag data.
func NewNFCReader ¶
NewNFCReader creates and initializes a new NFCReader instance with default ModeReadWrite.
func NewNFCReaderWithClock ¶
func NewNFCReaderWithClock(deviceStr string, manager Manager, opTimeout time.Duration, clock Clock) (*NFCReader, error)
NewNFCReaderWithClock creates and initializes a new NFCReader with a custom clock. If clock is nil, uses RealClock.
func (*NFCReader) Close ¶
func (r *NFCReader) Close()
Close releases resources. Does not stop the worker, use Stop() for that.
func (*NFCReader) DevicePath ¶
func (*NFCReader) EraseCard ¶ added in v1.0.3
func (r *NFCReader) EraseCard() (*WriteResult, error)
EraseCard overwrites the presented tag with an empty NDEF message, making it read as blank. This is reversible — the tag can be rewritten afterward. The write is verified like any other write.
func (*NFCReader) GetCapabilities ¶ added in v1.0.3
func (r *NFCReader) GetCapabilities() (*TagCapabilities, error)
GetCapabilities reports the capabilities of the tag currently presented to the reader — memory size, writability, lock and password support, and read-only state. It requires exactly one tag to be present, performs no write, and works regardless of reader mode (including read-only). This lets clients query what a tag supports before attempting a write or lock.
func (*NFCReader) GetDeviceStatus ¶
func (r *NFCReader) GetDeviceStatus() DeviceStatus
GetDeviceStatus returns the current device status by querying live state.
func (*NFCReader) GetLastScannedData ¶
GetLastScannedData retrieves the last scanned UID from the cache.
func (*NFCReader) GetMode ¶
func (r *NFCReader) GetMode() ReaderMode
GetMode returns the current reader mode.
func (*NFCReader) LockCard ¶ added in v1.0.3
func (r *NFCReader) LockCard() (*LockResult, error)
LockCard makes the currently presented tag permanently read-only. This is irreversible. Only tags that support locking (e.g. NTAG, Ultralight) succeed; others return a not-supported error.
func (*NFCReader) LogDeviceInfo ¶
func (r *NFCReader) LogDeviceInfo()
LogDeviceInfo logs information about the connected NFC device.
func (*NFCReader) RemoveCardPassword ¶ added in v1.0.3
func (r *NFCReader) RemoveCardPassword(password []byte) (*PasswordResult, error)
RemoveCardPassword clears password protection from the presented tag.
Like SetCardPassword, this is gated off pending hardware validation and currently returns a not-supported error.
func (*NFCReader) SetCardPassword ¶ added in v1.0.3
func (r *NFCReader) SetCardPassword(password []byte, opts PasswordOptions) (*PasswordResult, error)
SetCardPassword configures password protection on the presented tag.
NOTE: password protection is NOT yet enabled in this build. The per-tag capability is reported (TagCapabilities.SupportsPassword) and this API contract is fixed, but the destructive configuration-page writes (PWD, PACK, AUTH0, ACCESS) are intentionally gated off pending validation on real hardware — a wrong AUTH0/ACCESS configuration can permanently lock a tag. This method currently returns a not-supported error for all tags.
func (*NFCReader) SetClassicKeys ¶ added in v1.0.3
SetClassicKeys configures additional 6-byte MIFARE Classic authentication keys to try when reading or writing Classic cards that don't use default keys. Keys are applied to each Classic tag the reader encounters, tried before the built-in defaults. Pass nil to clear.
func (*NFCReader) SetMode ¶
func (r *NFCReader) SetMode(mode ReaderMode)
SetMode changes the reader's access mode at runtime.
func (*NFCReader) Start ¶
func (r *NFCReader) Start()
Start begins the NFC reading process in a separate goroutine.
func (*NFCReader) StatusUpdates ¶
func (r *NFCReader) StatusUpdates() <-chan DeviceStatus
StatusUpdates returns a channel that provides DeviceStatus updates.
func (*NFCReader) Stop ¶
func (r *NFCReader) Stop()
Stop gracefully shuts down the NFCReader worker and waits for it to complete.
func (*NFCReader) Transceive ¶ added in v1.1.0
Transceive exchanges raw bytes with the tag currently on the reader.
Deliberately not gated on ReaderMode here: the caller decides. A raw exchange is neither a read nor a write as far as this layer can tell — the same interface carries a SELECT and a write to a config page — so the policy call belongs where the request enters, not here.
func (*NFCReader) WriteCardData ¶
WriteCardData attempts to write data to a detected NFC card using default options (overwrite mode).
func (*NFCReader) WriteMessageWithOptions ¶
func (r *NFCReader) WriteMessageWithOptions(msg *NDEFMessage, opts WriteOptions) error
WriteMessageWithOptions writes an NDEF message to a detected NFC card with options for record manipulation. It performs a pre-flight capacity check, retries on transient failures, and (unless disabled) verifies the write by reading the data back. Use WriteMessageWithResult to obtain the WriteResult.
func (*NFCReader) WriteMessageWithResult ¶ added in v1.0.3
func (r *NFCReader) WriteMessageWithResult(msg *NDEFMessage, opts WriteOptions) (*WriteResult, error)
WriteMessageWithResult is like WriteMessageWithOptions but returns a WriteResult describing the outcome (verification status, attempts, and bytes written) so callers can surface real write confidence to the user.
type PasswordOptions ¶ added in v1.0.3
type PasswordOptions struct {
// Pack is the 2-byte password acknowledge (PACK) returned by the tag on a
// successful authentication. If empty, the implementation chooses a default.
Pack []byte
// ProtectRead, when true, requires the password for reads as well as
// writes. When false (the default), only writes are password-protected.
ProtectRead bool
// StartPage is the first tag page protected by the password (NTAG AUTH0).
// Implementations enforce a floor so the tag's own configuration pages can
// never be locked out of reach, which would brick the tag.
StartPage int
}
PasswordOptions configures how password protection is applied to a tag.
These fields define the contract the hardware implementation will honor. Password protection is currently gated off pending validation on real hardware (see SetCardPassword), so they are not yet acted upon.
type PasswordResult ¶ added in v1.0.3
type PasswordResult struct {
// UID of the tag the operation targeted.
UID string `json:"uid"`
// TagType is the human-readable tag type string.
TagType string `json:"tagType"`
// Protected reports whether the tag is password-protected after the
// operation (true after a successful set, false after a successful remove).
Protected bool `json:"protected"`
}
PasswordResult describes the outcome of a password operation.
type ReaderLister ¶ added in v1.1.3
ReaderLister is implemented by a manager that holds others, so it can list only the devices eligible to be this agent's reader.
Optional: a manager that does not implement it lists readers from ListDevices.
type ReaderMode ¶
type ReaderMode int
ReaderMode defines the access mode for the NFC reader.
const ( // ModeReadWrite allows both read and write operations (default). ModeReadWrite ReaderMode = iota // ModeReadOnly allows only read operations. ModeReadOnly // ModeWriteOnly allows only write operations. ModeWriteOnly )
type RemoteDeviceChecker ¶ added in v1.1.3
RemoteDeviceChecker is implemented by a manager that can recognize a device path as naming a remote device without connecting to it.
Optional: a manager that does not implement it is asked whether all of its devices are remote instead.
type RemoteManager ¶ added in v1.1.3
type RemoteManager interface {
RemoteDevices() bool
}
RemoteManager is implemented by a manager whose devices are not readers attached to this machine. A phone reports the tags it scans over the device bridge, so it is never opened and polled the way a reader is — offering one as the agent's reader only produces a device that can never be connected.
Optional: a manager that does not implement it manages local readers.
type Tag ¶
type Tag interface {
TagIdentifier
TagConnection
TagReader
TagWriter
TagTransceiver
TagLocker
}
Tag represents an NFC tag at the hardware protocol level.
Tag provides a unified interface for reading and writing NDEF data regardless of the underlying tag technology (MIFARE Classic, ISO14443-4, etc.).
Not all tags support all operations. Use GetTagCapabilities(tag) to check what operations a specific tag supports before calling methods that may return "not supported" errors.
For most use cases, prefer using Card which provides a higher-level, io.Reader/Writer compatible API.
Example:
tags, _ := manager.GetTags(device)
for _, tag := range tags {
caps := nfc.GetTagCapabilities(tag)
if caps.CanRead {
data, _ := tag.ReadData()
}
}
func NewEmulatedTag ¶ added in v1.0.3
func NewEmulatedTag(transport CardTransport, uid string, kind DetectedTagType) Tag
NewEmulatedTag wraps a CardTransport in the production tag driver for the given tag kind, so a custom or in-memory transport is driven by the real tag I/O (page/block/APDU logic, TLV framing, lock bytes) rather than a stand-in.
This is the bridge that lets the nfctest emulators run production driver code without hardware: build an emulator (a CardTransport), wrap it here, and the returned Tag behaves as if it were a real card on a reader.
type TagCache ¶
type TagCache struct {
// contains filtered or unexported fields
}
TagCache provides thread-safe caching of the last scanned NFC tag UID.
func NewTagCache ¶
func NewTagCache() *TagCache
NewTagCache creates and initializes a new TagCache instance.
func (*TagCache) GetLastScanned ¶
GetLastScanned returns the UID of the last successfully scanned tag.
func (*TagCache) HasChanged ¶
HasChanged checks if the given UID is new or different from the last scanned card. It returns true if this is a new card (different UID from last scan).
func (*TagCache) IsCardPresent ¶
IsCardPresent checks if a card is still present based on the last seen time.
func (*TagCache) UpdateLastSeenTime ¶
UpdateLastSeenTime updates the global last seen time in the cache, indicating recent card activity. The uid parameter is currently not used for specific per-tag timestamping with the current cache structure but is retained from the original intended signature of ForceSeen.
type TagCapabilities ¶
type TagCapabilities = protocol.TagCapabilities
TagCapabilities describes what operations a tag supports. Defined in the protocol package so external tools can consume it without pulling in this one.
func GetTagCapabilities ¶
func GetTagCapabilities(tag Tag) TagCapabilities
GetTagCapabilities returns capabilities for any Tag. If the tag implements TagCapabilityProvider, it uses that. Otherwise, it infers capabilities from the tag type string.
func InferTagCapabilities ¶
func InferTagCapabilities(tagType string) TagCapabilities
InferTagCapabilities infers capabilities from a tag type string. This is used as a fallback when the tag doesn't implement TagCapabilityProvider.
type TagCapabilityProvider ¶
type TagCapabilityProvider interface {
Capabilities() TagCapabilities
}
TagCapabilityProvider is an optional interface for tags to report their capabilities.
type TagConnection ¶
type TagConnection interface {
// Connect establishes a connection to the tag.
Connect() error
// Disconnect closes the connection to the tag.
Disconnect() error
}
TagConnection manages the connection lifecycle to a tag. Tags that require explicit connection management implement this interface.
type TagIdentifier ¶
type TagIdentifier interface {
// UID returns the unique identifier of the tag.
UID() string
// Type returns a human-readable string describing the tag type.
Type() string
// NumericType returns a numeric type identifier (implementation-specific).
NumericType() int
}
TagIdentifier provides basic tag identification. All tags implement this interface.
type TagLocker ¶
type TagLocker interface {
// IsWritable checks if the tag can be written to.
IsWritable() (bool, error)
// CanMakeReadOnly checks if the tag supports being made read-only.
CanMakeReadOnly() (bool, error)
// MakeReadOnly permanently locks the tag to prevent further writes.
MakeReadOnly() error
}
TagLocker provides read-only locking capability. Tags that can be made permanently read-only implement this interface. Use GetTagCapabilities(tag).CanLock to check if a tag supports this.
type TagReader ¶
TagReader provides read capability for NDEF data. Tags that support reading implement this interface.
type TagTransceiver ¶
type TagTransceiver interface {
// Transceive sends raw data to the tag and returns the response.
Transceive(data []byte) ([]byte, error)
}
TagTransceiver provides raw data exchange with the tag. Only some tag types (e.g., Type 4) support this. Use GetTagCapabilities(tag).CanTransceive to check if a tag supports this.
type TagWriteOptions ¶
type TagWriteOptions struct {
// ForceInitialize forces reinitialization of the tag even if it contains existing data.
// WARNING: This will erase all existing data on the tag.
// Only use this if you explicitly want to wipe and reinitialize the tag.
ForceInitialize bool
}
TagWriteOptions defines options for tag write operations.
type TagWriter ¶
TagWriter provides write capability for NDEF data. Tags that support writing implement this interface. Use GetTagCapabilities(tag).CanWrite to check if a tag supports this.
type TextMessage ¶
type TextMessage struct {
Data []byte // Raw bytes from the card
Text string // Decoded text representation
}
TextMessage represents raw bytes from cards that don't support NDEF. This is a fallback message type that stores both the raw data and decoded text.
func DecodeText ¶
func DecodeText(data []byte) *TextMessage
DecodeText creates a TextMessage from raw bytes (no parsing). This is used for cards that don't support NDEF.
func NewTextMessage ¶
func NewTextMessage(data []byte) *TextMessage
NewTextMessage creates a new text message from raw bytes. It automatically decodes the bytes to a string.
func NewTextMessageFromString ¶
func NewTextMessageFromString(text string) *TextMessage
NewTextMessageFromString creates a new text message from a string.
func (*TextMessage) Encode ¶
func (t *TextMessage) Encode() ([]byte, error)
Encode returns the raw bytes as-is (no encoding).
type Ticker ¶
type Ticker interface {
// C returns the channel on which ticks are delivered
C() <-chan time.Time
// Stop turns off the ticker
Stop()
// Reset stops a ticker and resets its period to the specified duration
Reset(d time.Duration)
}
Ticker is an interface for time.Ticker to enable testing
type Timer ¶
type Timer interface {
// C returns the channel on which the timer value will be sent
C() <-chan time.Time
// Stop prevents the timer from firing
Stop() bool
// Reset changes the timer to expire after duration d
Reset(d time.Duration) bool
}
Timer is an interface for time.Timer to enable testing
type WriteOptions ¶
type WriteOptions struct {
// Overwrite completely replaces card data. If false, performs partial update.
// Partial updates only work if the card already contains valid NDEF data.
Overwrite bool
// Index specifies which record to update (for NDEF partial updates).
// -1 means append, >= 0 means replace at that index.
// Ignored if Overwrite is true or card doesn't support NDEF.
Index int
// ForceInitialize forces reinitialization of MIFARE Classic cards even if they
// contain existing data. WARNING: This will erase all existing data on the card.
// Only set this to true if you explicitly want to wipe and reinitialize the card.
ForceInitialize bool
// SkipVerify disables read-after-write verification. By default (false), the
// reader re-reads the card after writing and confirms the data matches what
// was written, retrying on mismatch.
SkipVerify bool
// MaxWriteAttempts caps the number of write+verify attempts on transient
// failures (write error, verification mismatch, or transient read error).
// If <= 0, DefaultMaxWriteAttempts is used. Permanent failures such as card
// removal, read-only tags, and capacity overflow are never retried.
MaxWriteAttempts int
// SkipCapacityCheck disables the pre-flight check that the encoded NDEF
// message fits within the tag's reported NDEF capacity.
SkipCapacityCheck bool
// Lock, when true, makes the tag permanently read-only after a successful
// verified write. Only tags that support locking (e.g. NTAG, Ultralight)
// honor this; others return an error. WARNING: locking is irreversible.
Lock bool
}
WriteOptions controls how data is written to NFC cards at the reader level.
type WriteResult ¶ added in v1.0.3
type WriteResult struct {
// UID of the tag that was written.
UID string `json:"uid"`
// TagType is the human-readable tag type string.
TagType string `json:"tagType"`
// BytesWritten is the size of the encoded NDEF message written to the tag.
BytesWritten int `json:"bytesWritten"`
// Verified is true when the write was confirmed by reading the data back and
// comparing it to what was written.
Verified bool `json:"verified"`
// Attempts is the number of write attempts made before success.
Attempts int `json:"attempts"`
// Locked is true when the tag was made permanently read-only as part of the
// write (see WriteOptions.Lock).
Locked bool `json:"locked,omitempty"`
}
WriteResult describes the outcome of a successful write operation. It gives callers (and ultimately the frontend) the same confidence for writes that the read path already provides: confirmation that the bytes actually landed.
Source Files
¶
- apdu.go
- cache.go
- capabilities.go
- card.go
- clock.go
- common.go
- constants.go
- convert.go
- device.go
- device_manager.go
- device_mock.go
- device_pcsc.go
- emulated_tag.go
- errors.go
- errors_wire.go
- keys.go
- manager.go
- manager_mock.go
- manager_pcsc.go
- message.go
- ndef.go
- ndef_dto.go
- password.go
- reader.go
- tag.go
- tag_base.go
- tag_base_default.go
- tag_classic.go
- tag_classic_format.go
- tag_desfire.go
- tag_iso14443.go
- tag_mock.go
- tag_ntag.go
- tag_ultralight.go
- tagdetect.go
- tlv.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package multimanager provides a multi-manager that aggregates multiple NFC Manager implementations.
|
Package multimanager provides a multi-manager that aggregates multiple NFC Manager implementations. |
|
Package nfctest provides in-memory NFC tag emulators and a high-level façade for testing NFC code without hardware.
|
Package nfctest provides in-memory NFC tag emulators and a high-level façade for testing NFC code without hardware. |