nxprd

package module
v0.0.0-...-d13cc7c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 27, 2016 License: MIT Imports: 10 Imported by: 0

README

go-nxprd

go-nxprd is a very simple wrapper written in GO for NXP's NFC Reader Library (NxpRdLib) in order to interface with the NXP EXPLORE-NFC expansion board for the Raspberry Pi.

Right now only Mifare Ultralight cards are supported for reading and writing bytes. This may change in the future, but currently I only have the Ultralight card that was shipped with the NFC board.

This wrapper was heavily inspired by svvitale's nxppy python wrapper. I use a slightly modified version of his nice bash script (get_nxpRdLib.sh).

License

All files in this repository are distributed under the MIT license.

External components

This wrapper is heavily based on NXP's example code (mainly MIFAREClassic and BasicDiscoveryLoop). The example code was reorganized and adjusted to be used from a GO wrapper. NXP still retains full copyright and ownership of the example code and the NFC Reader Library. The license conditions that need to be accepted in order to use this project in conjunction with the NFC Reader Library can be found in the document NXP_Library_License.pdf.

Compatibility

Tested with GO 1.6.3 on Raspian Jessie.

Requirements

The EXPLORE-NFC board relies on SPI being enabled. Please enable SPI using raspi-config prior to using go-nxprd. You may follow this tutorial from raspberrypi-spy.

As go-nxprd is a GO wrapper for NXP's C based NFC Reader Library, you need to install and configure GO on your Raspberry Pi. Instructions can be found at https://golang.org/doc/install.

Installation

go-nxprd uses cgo to interface the NFC Reader Library, so before using the wrapper please make sure you have a working gcc and cmake (used for building the NFC Reader Library) installed.

The easiest way is to use the script get_nxpRdLib.sh in the repository. It will download the Reader Library sources from DropBox, extract them to the folder nxp and run cmake to build the library for the EXPLORE-NFC board. Beforehand it will check whether the debian packages build-essential and cmake are installed and if not, will install them. Therefore, the script should be run with root privileges.

cgo relies on the original folder structure of the Reader Library in the nxp folder, so better don't change it. You'll find the compiled NFC Reader Library in the nxp/build/linux folder.

If the NFC Reader Library was build successfully, you can try to build the GO based test application for Mifare Ultralight cards. It is located under cmd/gomful in the repository. As the NFC Reader Library will be statically linked to the wrapper, you need to pass some extra parameters to GO's build command:

go build --ldflags '-extldflags -static' .

This will build the test application in the current folder. You'll find the build command in the script build.sh in the gomful folder. After a successfull build you can start the application simply by using:

./gomful

The output may be similar to the following:

Mifare Ultralight Test

Place a card near the reader and press <Enter>


Card            : MifareUL
Tag type        : 2
Technology type : A
UID             : 0x04 0x90 0x98 0xC2 0x37 0x30 0x81
ATQ(A)          : 0x44 0x00
SAK             : 0x00

Trying to read memory pages 0-15:

Page 00: 0x04 0x90 0x98 0x84
Page 01: 0xC2 0x37 0x30 0x81
Page 02: 0x44 0x48 0x00 0x00
Page 03: 0x00 0x00 0x00 0x00
Page 04: 0x00 0x00 0x00 0x00
Page 05: 0x00 0x00 0x00 0x00
Page 06: 0x00 0x00 0x00 0x00
Page 07: 0x00 0x00 0x00 0x00
Page 08: 0x00 0x00 0x00 0x00
Page 09: 0x00 0x00 0x00 0x00
Page 10: 0x00 0x00 0x00 0x00
Page 11: 0x00 0x00 0x00 0x00
Page 12: 0x00 0x00 0x00 0x00
Page 13: 0x00 0x00 0x00 0x00
Page 14: 0x00 0x00 0x00 0x00
Page 15: 0x00 0x00 0x00 0x00

Usage

To use go-nxprd in your GO application simply use the following import statement:

import "github.com/hohlerde/go-nxprd"

The main package of the wrapper is nxprd. In order to detect and read a card/tag the wrapper and also the NFC Reader Library need to be initialized. This is done by calling nxprd.Init():

err := nxprd.Init()
if err != nil {
    // handle error
}

Now you are ready to select a card/tag by calling Discover(). Please note that the Discover function blocks the caller. It has an optional timeout parameter, which can be used to specify how long the function should try to detect a card/tag before returning. The default timeout is 1000ms.

dev, err := nxprd.Discover(5000) // timeout = 5s
if err != nil {
    // handle error
}

If a card/tag could be detected, it can be accessed through the Device structure returned by Discover().

Parameters of the card/tag can be simply accessed by the Params member.

// Prints the UID of the card/tag
fmt.Printf("%+v", dev.Params.UID)

And if we have a Mifare Ultralight card, we can even read and write data.

// Right now only Mifare Ultralight cards are supported
if dev.Params.DevType == MifareUL {
    // Read all bytes (4) of page/block 10
    buffer, err := dev.Reader.ReadBlock(10)
    if err != nil {
        // handle error
    }

    buffer[0] = 66 // Change the first byte of page/block 10

    // and write it back to page 10.
    err = dev.Writer.WriteBlock(10, buffer)
    if err != nil {
        // handle error
    }
}

At the end we need to cleanup the wrapper and the NFC Reader Library by calling DeInit().

nxprd.DeInit()

As an example you also may want to take a look at the test application.

Feedback

Feedback and PRs are always welcome!

Documentation

Overview

Package nxprd is the main package of the GO wrapper for NXP's reader library. All NFC functionality is included in this package.

Index

Constants

View Source
const (
	LangEn Language = "en"
	LangDe          = "de"
	LangIt          = "it"
	LangNl          = "nl"
	LangFr          = "fr"
	LangRu          = "ru"
	LangKr          = "kr"
	LangCn          = "cn"
	LangUk          = "uk"
	LangCa          = "ca"
	LangEs          = "es"
)
View Source
const (
	// MifareULBlockLength defines the block length in bytes of a Mifare
	// Ultralight card, i.e. a block (page) of a Mifare Ultralight contains 4
	// bytes.
	MifareULBlockLength = 4
)

Variables

This section is empty.

Functions

func DeInit

func DeInit()

DeInit cleans up the C library and should be called if the wrapper is not used anymore, e.g. at the end of the application.

func Init

func Init() error

Init initializes the C library. It must be called once before other functions of this wrapper are used. A NxpError is returned in case of an error, otherwise nil is returned.

Types

type Device

type Device struct {
	// Params holds general nfc parameters of the card/tag, such as SAK or UID.
	Params DeviceParams
	// Reader reads bytes from the card/tag. Can be nil if no specific
	// implementation exists for the card/tag.
	Reader Reader
	// Writer writes bytes to the card/tag. Can be nil if no specific
	// implementation exists for the card/tag.
	Writer Writer
}

Device identifies a card/tag and contains parameters, such as the tag type or technology and Reader/Writer implementations for reading and writing bytes. Please note that Reader or Writer can be nil. This happens if an card/tag is identified for which no Reader/Writer implementation exists. Params will never be nil.

func Discover

func Discover(args ...interface{}) (*Device, error)

Discover selects a card/tag that is in the range of the breakout board and returns a pointer to a Device structure. If an error occurred while detecting and activating the card/tag, a NxpError along with a nil value for the Device is returned. Please note that not all cards/tags may be supported and thus the Reader or Writer variables within the Device struct may be nil. However, if a card/tag is found and no error occurred you'll always get a Device struct containing the card's/tag's parameters. Discover has an optional timeout parameter. The default value is 1000, which means Discover waits up to 1000ms to discover/detect a card/tag. During that time the caller will be blocked. The timeout value has to be of type int and will be interpreted as ms. So, if you want to give some more time for card/tag discovery, for instance 20s, you can call Discover(20000).

type DeviceParams

type DeviceParams struct {
	// Select AcKnowledge. Can be -1 if not available.
	SAK int
	// Holds ATQA for Tech Type A and ATQB for Tech Type B
	// ATQA = Answer To reQuest for Type A
	// ATQB = Answer To reQuest for Type B
	// ATQ can be nil, if not available
	ATQ []byte
	// Unified IDentifier of the card/tag. Can be nil, if not available.
	UID []byte
	// TechType identifies the technology type, e.g. A, B, P2P, etc.
	TechType TechType
	// TagType identifies the tag type, i.e. 1, 2, etc.
	TagType TagType
	// DevType
	DevType DeviceType
}

DeviceParams holds various parameters of a nfc card/tag.

type DeviceType

type DeviceType int

DeviceType defines manufacturer specific cards/tags which are supported by this wrapper.

const (
	// Mifare Ultralight card
	MifareUL DeviceType = 1 + iota
	Unknown
)

All cards/tags which are supported by this wrapper.

func (DeviceType) String

func (dt DeviceType) String() string

String returns the name of a DeviceType (emulating an enum).

type ExtendedErrorCode

type ExtendedErrorCode int

ExtendedErrorCode defines errors of the wrapper. The C library has its own error codes.

const (
	// TimeoutErr is used if a timeout occurred when using Discover().
	TimeoutErr ExtendedErrorCode = 1 + iota
	// NoErr is used if no error occurred.
	NoErr
)

All extended error codes of the wrapper.

func (ExtendedErrorCode) String

func (ec ExtendedErrorCode) String() string

String returns the name of an ExtendedErrorCode (emulating an enum).

type Language

type Language string

New type to represent Language if the payload type is "T"(text).

type MifareULReader

type MifareULReader struct {
}

MifareULReader implements the Reader interface for the Mifare Ultralight card.

func (*MifareULReader) ReadBlock

func (r *MifareULReader) ReadBlock(idx int) ([]byte, error)

ReadBlock implements reading a block of bytes for a Mifare Ultralight card. idx defines the block to be read. See also the Reader interface.

func (*MifareULReader) ReadNdef

func (r *MifareULReader) ReadNdef() (*Ndef, error)

This function reads the data from the card using the ReadBlock method and converts the read bytes into a NDEF struct.

type MifareULWriter

type MifareULWriter struct {
}

MifareULWriter implements the Writer interface for the Mifare Ultralight card.

func (*MifareULWriter) WriteBlock

func (w *MifareULWriter) WriteBlock(idx int, data []byte) error

WriteBlock implements writing a block of bytes for the Mifare Ultralight card. idx defines the memory position / block number. See also the Writer interface.

func (*MifareULWriter) WriteNdef

func (w *MifareULWriter) WriteNdef(ndef *Ndef) error

WriteNdef accepts a NDEF struct and converts the struct into bytes and writes it to a NFC tag or card

func (*MifareULWriter) WriteString

func (w *MifareULWriter) WriteString(payload string, language Language) error

WriteString accepts a string and the language of the string and converts the string to a NDEF struct and writes it to the card

type Ndef

type Ndef struct {
	MaxSize            int
	IsReadOnly         bool
	TotalMessageLength int
	NdefData           []NdefRecord
}

A struct which represents the NDEF message

type NdefRecord

type NdefRecord struct {
	IsStartRecord          bool
	IsEndRecord            bool
	ChunkFlag              bool
	IsShortRecord          bool
	IsIdLengthFieldPresent bool
	PayloadLength          int
	Payload                []byte
	Tnf                    Tnf
	Type                   string
	RecordNumber           int
	TypeLength             int
	IdLength               int
	Id                     string
	Language               Language
}

A struct which represents each NDEF message

type NxpError

type NxpError struct {
	// Comp defines the component of the C library where the error occurred.
	// 0 stands for "no error".
	Comp int
	// Code defines the actual error that occurred in the C library.
	// 0 stands for "no error".
	Code int
	// ExtCode defines the extended error code of the wrapper. ExtCode will have
	// the NoErr value, if no extended error occurred.
	ExtCode ExtendedErrorCode
	// Msg describes the error.
	Msg string
}

NxpError defines the error struct that is used to indicate an error of the C library or the GO wrapper.

func (*NxpError) Error

func (e *NxpError) Error() string

Error returns the error information as a human readable string.

type Reader

type Reader interface {
	// ReadBlock reads a block of bytes from a nfc card/tag. idx defines the
	// block number or index. The memory layout, i.e. the number and the size of
	// blocks may differ between the various tags and cards.
	// If data can't be read, a NxpError is returned along with a nil slice.
	// If data could be read, error will be always nil.
	ReadBlock(idx int) ([]byte, error)
	//Returns the entire contents of a card or tag as a NDEF struct
	ReadNdef() (*Ndef, error)
}

Reader defines an interface for reading data from a nfc capable card/tag.

type TagType

type TagType int

TagType defines the nfc tag type, such as 1, 2, 3, 4A etc.

const (
	TagType1 TagType = 1 + iota
	TagType2
	TagType3
	TagType4A
	TagTypeP2P
	TagTypeNFCDEP4A
	TagTypeUndefined
)

Tag types which are supported by this wrapper.

func (TagType) String

func (tt TagType) String() string

String returns the name of a TagType (emulating an enum).

type TechType

type TechType int

TechType defines the technology of the card/tag, e.g. A, B, etc..

const (
	TechA TechType = 1 + iota
	TechB
	TechF
	TechV15693T5T
	Tech18000p3m3EPCGen2
	TechUndefined
)

Technology types which are supported by this wrapper.

func (TechType) String

func (tt TechType) String() string

String returns the name of a TechType (emulating an enum).

type Tnf

type Tnf int

New type to represent tnf.

const (
	TnfEmpty Tnf = iota
	TnfNfcrtd
	TnfRfc2046
	TnfRfc3986
	TnfNfcrtdexternal
	TnfUnknown
	TnfUnchanged
	TnfReserved
)

func (Tnf) String

func (tn Tnf) String() string

type Writer

type Writer interface {
	// WriteBlock writes a block (slice) of bytes to a nfc card/tag.
	// The position of the block is defined by idx and may vary between
	// different cards and tags. Also the length of the data slice depends on
	// the card/tag being used.
	// If the data can't be written, a NxpError is returned. If no error occurred,
	// nil is returned.
	WriteBlock(idx int, data []byte) error
	//Writes the NDEF struct to the tag or card
	WriteNdef(ndef *Ndef) error
	//Writes the string of a particular language to the card or tag
	WriteString(payload string, language Language) error
}

Writer defines an interface for writing data to a nfc capable card/tag.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL