Caenrfidd daemon

From CAEN RFID support

Jump to: navigation, search

The caenrfidd daemon implements the server side implementation of the CAENRFID protocol.

The daemon as been designed for Debian/Linux squeeze system but it should run "as is" on other GNU/Linux systems too. You are encouraged to download, run and test it. Then, please, provide a feedback to us if you like it or you just need some improvements!

Note: the code is distributed with the GNU/GPL version 2 license, so it is released as is without any warranty (unless you have brought our product equipped with this tool)! However you can ask for a software enhancement to our customers service.

Contents

Theory of operation

The caenrfidd daemon is very similar to the Llrpd daemon. It has two levels of operation:

  1. Protocol level
  2. Hardware (radios/IO ports) level

The first level manages the high level requests from the clients, while the second level manages the hardware: RFID radios and general purpose input output ports.

                   +-------------------------+
Protocol level     | CAENRFID network server |
                   +-------------------------+
                    ^           ^           ^
                    |           |           |
                    v           v           v
               +---------+ +---------+ +----------+
hardware level | radio 1 | | radio 2 | | ioport 0 |
               +---------+ +---------+ +----------+

Each radios/IO ports drive one or more antennae/GPIOs and they are managed with proper drivers (see paragraph Hardware drivers).

Logical entities into the daemon are:

  • antenna: which is the component who really manages RFID data by talking with tags.
  • radio: the component who manages one or more antennae. This entity is hidden to the clients.
  • reader: the component who send/receive data to/from a client by using one or more radios.
+--------------------------------------------------------------------------------------------------------+
| Reader FOO                                                                                             |
|                                                                                                        |
| +---------------------------+ +--------------+ +-----------------------------------------------------+ |
| | Radio0                    | | Radio1       | | Radio2                                              | |
| |                           | |              | |                                                     | |
| | +----------+ +----------+ | | +----------+ | | +----------+ +----------+ +----------+ +----------+ | |
| | | Antenna0 | | Antenna1 | | | | Antenna2 | | | | Antenna3 | | Antenna4 | | Antenna5 | | Antenna6 | | |
| | +----------+ +----------+ | | +----------+ | | +----------+ +----------+ +----------+ +----------+ | |
| +---------------------------+ +--------------+ +-----------------------------------------------------+ |
+--------------------------------------------------------------------------------------------------------+

Downloading the code

GIT repository

Latest code version is on our GIT repository. You can download the code by using the command:

git clone git://support.caenrfid.it/caenrfidd

After that you have the full code into the caenrfidd directory.

Note: a password is needed for cloning.

Then to compile it and getting a Debian package you can use the following commands:

$ cd caenrfidd
$ libtoolize && aclocal && autoheader && automake --foreign --add-missing --copy && autoreconf -i
$ fakeroot debian/rules binary

At the end, in the upper directory, you should find your new Debian package ready to install by using:

# dpkg -i ../caenrfidd_<version>_i386.deb

Debian APT repository

If you are just interested in running the daemon you can use the default Debian packaging tools to download it and run on your Debian based systems (please refer to your specific Linux distribution's manual if you are running a different Linux distribution).

Just add the following two lines to the file /etc/apt/sources.list:

deb http://support.caenrfid.it/ unstable main

then run the commands:

# aptitude update
# aptitude install caenrfidd

the system should start installing the package.

Getting help

We published a proper mail list regarding the caenrfidd daemon usage and development where you can see for help in managing the software, however your are encouraged to check the caenrfidd FAQs page before asking something...

If you are a CAENRFID's customer you can also try our customers' support.

Configuring the daemon

The caenrfidd daemon can be configured by modifying its configurations files. After editing the configurations files you should restart the daemon in order the new settings to take effect:

# /etc/init.d/caenrfidd restart

The system wide configuration file

The caenrfidd daemon uses file /etc/defaults/caenrfidd as system wide configuration file. Here the default content of file such on the ION:

# Default settings for caenrfidd server. This file is sourced by /bin/sh from
# /etc/init.d/caenrfidd.

# Enable/disable the deamon.
# Use "yes" to enable.
CAENRFIDD_ENABLE=yes

# Set the default reader's name
READER_NAME=ion

# Enable debugging mode
#DEBUG=yes

The variable CAENRFIDD_ENABLE can be used to enable/disable the daemon at startup while READER_NAME defines the default reader's name (ion, in this example).

The DEBUG variable enable/disable debugging messages into system log facility. You can see debugging messages into file /var/log/syslog (use command tail -f /var/log/syslog to log all data on your terminal).

The main configuration file

Main configuration file is /etc/caenrfidd/caenrfidd.conf and it defines basic daemon configurations. Here the default content of file such on the ION:

# Package generated configuration file

# System configuration directory
#
# Set the default system configuration directory.
#
# Default:
#       config_dir = "/etc/caenrfidd"

# Loggin level
#
# Set the default log level.
#
# Valid values are: debug, error and info.
#
# Default:
#       log_level = error

# Log to stderr
#
# Enable logging to standard error too.
#
# Default:
#       log_to_stderr = false

# Lock file
#
# Set the lock file's name.
#
# Default:
#       lock_file = "/var/lock/caenrfidd"

# PID file
#
# Set the PID file's name. You can kill the program by using the command:
#       $ kill 
#
# Default:
#       pid_file = "/var/run/caenrfidd.pid"

# Run as user
#
# If executed as root the server will drop privileges to the specified
# user.
#
# Note: the selected user shold be able to read/write USB devices!
#
# Default:
#       user = "daemon"
user = "root"

# Listening port
#
# Change the default listening port.
# 
# CAENRFID default is 1000 so you need setting:
#
#    user = "root"
#
# in order to bind to the default CAENRFID port or the server will refuse
# to start.
#
# Default:
#       port = 1000

# Radios directory
#
# Set the default radios' searching directory.
#
# Default:
#       radios_dir = "/usr/lib/caenrfidd/radios"

# IO ports directory
#
# Set the default IO ports' searching directory.
#
# Default:
#       ioports_dir = "/usr/lib/caenrfidd/ioports"

All settings are self explanatory and they defines general daemons settings.

The reader configuration file

By using the READER_NAME above variable the daemon will load the reader configuration file named /etc/caenrfidd/READER_NAME.conf; so, in our example, the daemon will read file /etc/caenrfidd/ion.conf to set specific reader settings.

Here a list of currently supported reader:

The CAENRFID ION

The ION reader configuration file is by default:

# Package generated configuration file
# See the caenrfidd(8) manpage for details

#
# CAENRFID (read only) configuration settings
#

# Reader Manufacturer
#
# Define custom reader's manufacturer ID.
#
# Default:
#       vendor = 21336  # CAEN

# Reader Model
#
# Define custom reader's model ID.
#
# Default:
#       model = "(null)"
model = "R4300P"	# ION

# Reader's radios list
#
# Define which radios are connected to the reader and each per radio
# configuration data.
#
# Note:
#     * antennae ID numbering starts from 0.
#     * invalid antenna IDs are simply discarted.
#     * no radios and/or no antennae is an error!
#
# radio dummy {
#       antennae_enabled = { 0 }
# }
# radio impinj {
#       antennae_enabled = { 0, 1 }
# }
radio impinj {
	antennae_enabled = { 0, 1, 2, 3 }
}

# Reader's IO ports list
#
# Define which IO ports are connected to the reader.
#
# Default:
#       ioports = { }
ioports = { ion }

#
# CAENRFID (client writable) configuration settings
#

# Read cycles during continuos inventory (Ver. 3.1)
#
# Define how many rounds the reader should execute during continuos
# inventories.
#
# Default:
#       read_cycles = 1

# Regional settings
#
# Define the default region to use.
#
# Allowed values are: ETSI302208, ETSI300220, FCCUS, MALAYSIA, JAPAN,
#                       KOREA, AUSTRALIA, CHINA, TAIWAN and SINGAPORE
#
# Default:
#       region = "ETSI302208"

# Frequency hopping
#
# Define if the reader has the frequency hopping enabled or not.
#
# Default:
#       frequency_hopping = on

# RF channel
#
# Define the default RF channel.
#
# Default:
#       rf_channel = 4

# RF Power
#
# Define the default RF power in mW.
#
# Default:
#       rf_power = 680

# Q value
#
# Define the default Q value for the inventory algorithm.
#
# Allowed values are in 0..15 range.
#
# Default
#       q = 3

# Session
#
# Define the default session for the query algorithm.
#
# Allowed values are: S0, S1, S2 and S3
#
# Default
#       session = "S0"

The settings are self explanatory.

Hardware drivers

Each hardware object (radio/ioport) is managed by a proper driver which is responsible to register into the daemon its managed hardware so the daemon itself can export it to the clients.

Radios and antennae

A radio is composed by one ore more antennae and it is transparent to the clients, that is it is know only inside the caenrfidd daemon, the clients just see the antennae managed by the daemon.

In order to register a new antenna into the system a radio driver just calls the register_antenna() function as described into the dummy radio driver radios/dummy.c:

static struct antenna_data ant = {
        .name = "dummy0",
        .ops = {
                .fhopping_set = dummy_fhopping_set,
                .algo_set = dummy_algo_set,
                .algo_get = dummy_algo_get,
                .proto_set = dummy_proto_set,
                .proto_get = dummy_proto_get,
                .inventory_begin = dummy_inventory_begin,
                .inventory_get = dummy_inventory_get,
                .inventory_end = dummy_inventory_end,
                .init = dummy_init,
        },
};

int dummy_probe(struct radio_cfg *cfg)
{
        int ret;

        info("dummy radio - ver. %s", VERSION);
        info("Copyright 2009 Rodolfo Giometti <giometti@linux.it>");
        info("Copyright 2009 CAEN <info@caen.it>");
        dbg("name=%s", ant.name);

        /* Set dummy's serial number and firmware version */
        cfg->serialnum = "123456";
        cfg->fw_release = "0000.1111.2222";
          
        ret = register_antenna(&ant);
        if (ret) {
                err("unable to register antenna %s", ant.name);
                return 0;
        }

        return 1;               /* dummy radio has only one antenna */
}

module_init(dummy_probe);

By using module_init() function we define the function dummy_probe() as the one to be run at start up. It has the rule to reset and initialize all antennae into the radios and then register them into the daemon, also it set up the struct radio_cfg's fields named serialnum and fw_release whose describe the radio's serial number and radio's firmware release.

IO ports and GPIOs

An IO port can manage one or more GPIOs pins so, as the radios above, a ioport drivers has the rule to reset and initialise all its GPIOs pins and then registers them into the daemon by using the function register_gpio(). See the dummy ioport driver in ioports/dummy.c:

struct gpio_ops dummy_ops = {
        .reset          = dummy_reset,
        .wait_event     = dummy_wait_event,
        .read           = dummy_read,
        .write          = dummy_write,
};

static struct gpio_data gpio[8] = {
        {
                .name   = "dummy0",
                .type   = GPIO_TYPE_OUTPUT,
        },
        {
                .name   = "dummy1",
                .type   = GPIO_TYPE_OUTPUT,
        },
        {
                .name   = "dummy2",
                .type   = GPIO_TYPE_OUTPUT,
        },
        {
                .name   = "dummy3",
                .type   = GPIO_TYPE_OUTPUT,
        },
        {
                .name   = "dummy4",
                .type   = GPIO_TYPE_OUTPUT,
        },
        {
                .name   = "dummy5",
                .type   = GPIO_TYPE_OUTPUT,
        },
        {
                .name   = "dummy6",
                .type   = GPIO_TYPE_OUTPUT,
        },
        {
                .name   = "dummy7",
                .type   = GPIO_TYPE_OUTPUT,
        },
};

/*
 * Public data/functions
 */

int dummy_probe(void)
{
        int i, num, ret;

        info("dummy ioports - ver. %s", VERSION);
        info("Copyright 2009 Rodolfo Giometti <giometti@linux.it>");
        info("Copyright 2009 CAEN <info@caen.it>");

        num = 0;
        for (i = 0; i < 8; i++) {
                /* Before registering GPIOs setup their methods and
                 * other info
                 */
                gpio[i].ops = dummy_ops;
                gpio[i].private_data = &gpio_status[i];

                ret = register_gpio(&gpio[i]);
                if (ret) {
                        err("unable to register gpio %s! Skipped",
                                        gpio[i].name);
                        continue;
                }
                num++;
        }

        return num;
}

module_init(dummy_probe);

Using the serial port

The daemon has been designed to exchange data over the network but you can do it over the serial port too by using the program socat.

First of all install it by using the command:

# aptitude install socat

then you need to disable the serial console as reported in the ION main page in order to not overlap caenrfidd's messages with the serial console's ones.

Now you can redirect all caenrfidd's network messages to the serial port by using:

# socat TCP:localhost:1000 /dev/ttyS0,raw,echo=0
Personal tools