Added the new ethercat comman-line tool with lsec functionality.

This commit is contained in:
Florian Pose
2008-05-29 15:11:26 +00:00
parent 9f0555ee26
commit 3b4cae9626
17 changed files with 763 additions and 12 deletions

View File

@@ -31,9 +31,20 @@
#
#------------------------------------------------------------------------------
SUBDIRS = master devices script include
SUBDIRS = \
devices \
include \
master \
script \
tools
DIST_SUBDIRS = master devices script include examples
DIST_SUBDIRS = \
devices \
examples \
include \
master \
script \
tools
EXTRA_DIST = \
Doxyfile \

3
NEWS
View File

@@ -49,6 +49,8 @@ Changes in version 1.4.0:
- Exported ecrt_slave_config_sdo(), the generic Sdo configuration
function.
- Removed the bus_state and bus_tainted flags from ec_master_state_t.
* Replaces the Sysfs interface with a new 'ethercat' command-line tool. See
'ethercat --help'.
* Removed include/ecdb.h.
* Sdo dictionaries will now also be fetched in operation mode.
* SII write requests will now also be processed in operation mode.
@@ -58,6 +60,7 @@ Changes in version 1.4.0:
* Network driver news:
- Added 8139too driver for kernel 2.6.22, thanks to Erwin Burgstaller.
- Added 8139too driver for kernel 2.6.23, thanks to Richard Hacker.
- Added 8139too driver for kernel 2.6.24.
- Added e1000 driver for kernel 2.6.22.
- Added e1000 driver for kernel 2.6.24, thanks to Matthias Luescher.
- Added alpha support for the Reaktek r8169 chipset, thanks to Scott

3
TODO
View File

@@ -8,8 +8,7 @@ $Id$
Version 1.4.0:
* Replace Sysfs interface with cdev and a user space program
to replace lsec; move a few sysfs attributes to proc.
* Replace all Sysfs files via the new ethercat tool.
* Remove the end state of the master state machine.
* Supply new ec_master_state_t.
* Implement ecrt_slave_config_state().

View File

@@ -19,6 +19,8 @@ branch=trunk
AC_DEFINE_UNQUOTED(BRANCH, ["$branch"], [Subversion branch])
AC_SUBST(BRANCH, [$branch])
AC_PROG_CXX
#------------------------------------------------------------------------------
# Linux sources
#------------------------------------------------------------------------------
@@ -510,6 +512,7 @@ AC_CONFIG_FILES([
script/Makefile
script/init.d/Makefile
script/sysconfig/Makefile
tools/Makefile
])
AC_OUTPUT

View File

@@ -36,6 +36,7 @@
obj-m := ec_master.o
ec_master-objs := \
cdev.o \
datagram.o \
device.o \
domain.o \

View File

@@ -33,6 +33,7 @@
EXTRA_DIST = \
Kbuild.in \
cdev.c cdev.h \
datagram.c datagram.h \
debug.c debug.h \
device.c device.h \
@@ -50,6 +51,7 @@ EXTRA_DIST = \
fsm_slave_config.c fsm_slave_config.h \
fsm_slave_scan.c fsm_slave_scan.h \
globals.h \
ioctl.h \
mailbox.c mailbox.h \
master.c master.h \
module.c \

204
master/cdev.c Normal file
View File

@@ -0,0 +1,204 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The IgH EtherCAT Master is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The right to use EtherCAT Technology is granted and comes free of
* charge under condition of compatibility of product made by
* Licensee. People intending to distribute/sell products based on the
* code, have to sign an agreement to guarantee that products using
* software based on IgH EtherCAT master stay compatible with the actual
* EtherCAT specification (which are released themselves as an open
* standard) as the (only) precondition to have the right to use EtherCAT
* Technology, IP and trade marks.
*
*****************************************************************************/
/**
\file
EtherCAT master character device.
*/
/*****************************************************************************/
#include <linux/module.h>
#include "cdev.h"
#include "master.h"
#include "ioctl.h"
/*****************************************************************************/
/** \cond */
int eccdev_open(struct inode *, struct file *);
int eccdev_release(struct inode *, struct file *);
ssize_t eccdev_read(struct file *, char __user *, size_t, loff_t *);
ssize_t eccdev_write(struct file *, const char __user *, size_t, loff_t *);
int eccdev_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
/*****************************************************************************/
static struct file_operations eccdev_fops = {
.owner = THIS_MODULE,
.open = eccdev_open,
.release = eccdev_release,
.ioctl = eccdev_ioctl
};
/** \endcond */
/*****************************************************************************/
/** Constructor.
*
* \return 0 in case of success, else < 0
*/
int ec_cdev_init(
ec_cdev_t *cdev, /**< EtherCAT master character device. */
ec_master_t *master, /**< Parent master. */
dev_t dev_num /**< Device number. */
)
{
cdev->master = master;
cdev_init(&cdev->cdev, &eccdev_fops);
cdev->cdev.owner = THIS_MODULE;
if (cdev_add(&cdev->cdev,
MKDEV(MAJOR(dev_num), master->index), 1)) {
EC_ERR("Failed to add character device!\n");
return -1;
}
return 0;
}
/*****************************************************************************/
/** Destructor.
*/
void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML device */)
{
cdev_del(&cdev->cdev);
}
/******************************************************************************
* File operations
*****************************************************************************/
int eccdev_open(struct inode *inode, struct file *filp)
{
ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
filp->private_data = cdev;
EC_DBG("File opened.\n");
return 0;
}
/*****************************************************************************/
int eccdev_release(struct inode *inode, struct file *filp)
{
//ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
EC_DBG("File closed.\n");
return 0;
}
/*****************************************************************************/
int eccdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
ec_master_t *master = cdev->master;
if (master->debug_level)
EC_DBG("ioctl(inode = %x, filp = %x, cmd = %u, arg = %u)\n",
(u32) inode, (u32) filp, (u32) cmd, (u32) arg);
switch (cmd) {
case EC_IOCTL_SLAVE_COUNT:
{
unsigned int slave_count = master->slave_count;
EC_INFO("EC_IOCTL_SLAVE_COUNT\n");
if (!arg)
return -EFAULT;
if (copy_to_user((void __user *) arg, &slave_count,
sizeof(unsigned int)))
return -EFAULT;
return 0;
}
case EC_IOCTL_SLAVE_INFO:
{
struct ec_ioctl_slave_info *infos, *info;
unsigned int slave_count = master->slave_count;
const ec_slave_t *slave;
unsigned int i = 0;
if (master->debug_level)
EC_DBG("EC_IOCTL_SLAVE_INFOS\n");
if (!slave_count)
return 0;
if (!arg)
return -EFAULT;
if (!(infos = kmalloc(slave_count *
sizeof(struct ec_ioctl_slave_info),
GFP_KERNEL)))
return -ENOMEM;
list_for_each_entry(slave, &master->slaves, list) {
info = &infos[i++];
info->vendor_id = slave->sii.vendor_id;
info->product_code = slave->sii.product_code;
info->alias = slave->sii.alias;
info->ring_position = slave->ring_position;
info->state = slave->current_state;
if (slave->sii.name) {
strncpy(info->description, slave->sii.name,
EC_IOCTL_SLAVE_INFO_DESC_SIZE);
info->description[EC_IOCTL_SLAVE_INFO_DESC_SIZE - 1]
= 0;
} else {
info->description[0] = 0;
}
}
if (copy_to_user((void __user *) arg, infos, slave_count *
sizeof(struct ec_ioctl_slave_info))) {
kfree(infos);
return -EFAULT;
}
kfree(infos);
return 0;
}
default:
return -ENOIOCTLCMD;
}
}
/*****************************************************************************/

68
master/cdev.h Normal file
View File

@@ -0,0 +1,68 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The IgH EtherCAT Master is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The right to use EtherCAT Technology is granted and comes free of
* charge under condition of compatibility of product made by
* Licensee. People intending to distribute/sell products based on the
* code, have to sign an agreement to guarantee that products using
* software based on IgH EtherCAT master stay compatible with the actual
* EtherCAT specification (which are released themselves as an open
* standard) as the (only) precondition to have the right to use EtherCAT
* Technology, IP and trade marks.
*
*****************************************************************************/
/**
\file
EtherCAT master character device.
*/
/*****************************************************************************/
#ifndef __EC_CDEV_H__
#define __EC_CDEV_H__
#include <linux/fs.h>
#include <linux/cdev.h>
#include "globals.h"
#include "../include/ecrt.h"
/*****************************************************************************/
/** EtherCAT master character device.
*/
typedef struct {
ec_master_t *master; /**< Master owning the device. */
struct cdev cdev; /**< Character device. */
} ec_cdev_t;
/*****************************************************************************/
int ec_cdev_init(ec_cdev_t *, ec_master_t *, dev_t);
void ec_cdev_clear(ec_cdev_t *);
int ec_cdev_request(ec_cdev_t *, uint32_t, uint32_t);
/*****************************************************************************/
#endif

66
master/ioctl.h Normal file
View File

@@ -0,0 +1,66 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The IgH EtherCAT Master is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The right to use EtherCAT Technology is granted and comes free of
* charge under condition of compatibility of product made by
* Licensee. People intending to distribute/sell products based on the
* code, have to sign an agreement to guarantee that products using
* software based on IgH EtherCAT master stay compatible with the actual
* EtherCAT specification (which are released themselves as an open
* standard) as the (only) precondition to have the right to use EtherCAT
* Technology, IP and trade marks.
*
*****************************************************************************/
/**
\file
EtherCAT master character device IOCTL commands.
*/
/*****************************************************************************/
#ifndef __EC_IOCTL_H__
#define __EC_IOCTL_H__
/*****************************************************************************/
enum {
EC_IOCTL_SLAVE_COUNT = 0,
EC_IOCTL_SLAVE_INFO,
};
/*****************************************************************************/
#define EC_IOCTL_SLAVE_INFO_DESC_SIZE 243
struct ec_ioctl_slave_info {
uint32_t vendor_id;
uint32_t product_code;
uint16_t alias;
uint16_t ring_position;
uint8_t state;
char description[EC_IOCTL_SLAVE_INFO_DESC_SIZE];
};
/*****************************************************************************/
#endif

View File

@@ -105,7 +105,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
struct kobject *module_kobj, /**< kobject of the master module */
unsigned int index, /**< master index */
const uint8_t *main_mac, /**< MAC address of main device */
const uint8_t *backup_mac /**< MAC address of backup device */
const uint8_t *backup_mac, /**< MAC address of backup device */
dev_t device_number /**< Character device number. */
)
{
unsigned int i;
@@ -178,9 +179,13 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
init_MUTEX(&master->sdo_sem);
init_waitqueue_head(&master->sdo_queue);
// init character device
if (ec_cdev_init(&master->cdev, master, device_number))
goto out_return;
// init devices
if (ec_device_init(&master->main_device, master))
goto out_return;
goto out_cdev;
if (ec_device_init(&master->backup_device, master))
goto out_clear_main;
@@ -222,6 +227,8 @@ out_clear_backup:
ec_device_clear(&master->backup_device);
out_clear_main:
ec_device_clear(&master->main_device);
out_cdev:
ec_cdev_clear(&master->cdev);
out_return:
return -1;
}
@@ -248,6 +255,7 @@ void ec_master_clear(
ec_datagram_clear(&master->fsm_datagram);
ec_device_clear(&master->backup_device);
ec_device_clear(&master->main_device);
ec_cdev_clear(&master->cdev);
// destroy self
kobject_del(&master->kobj);

View File

@@ -50,6 +50,7 @@
#include "device.h"
#include "domain.h"
#include "fsm_master.h"
#include "cdev.h"
/*****************************************************************************/
@@ -84,6 +85,8 @@ struct ec_master {
unsigned int index; /**< master index */
unsigned int reserved; /**< non-zero, if the master is reserved for RT */
ec_cdev_t cdev; /**< Master character device. */
ec_device_t main_device; /**< EtherCAT device */
const uint8_t *main_mac; /**< MAC address of main device */
ec_device_t backup_device; /**< EtherCAT backup device */
@@ -166,7 +169,7 @@ struct ec_master {
// master creation/deletion
int ec_master_init(ec_master_t *, struct kobject *, unsigned int,
const uint8_t *, const uint8_t *);
const uint8_t *, const uint8_t *, dev_t);
void ec_master_clear(ec_master_t *);
// mode transitions

View File

@@ -40,6 +40,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include "globals.h"
#include "master.h"
@@ -68,6 +69,8 @@ static struct semaphore master_sem; /**< Master semaphore. */
static unsigned int master_count; /**< Number of masters. */
static unsigned int backup_count; /**< Number of backup devices. */
static dev_t device_number; /**< Device number for cdevs. */
static uint8_t macs[MAX_MASTERS][2][ETH_ALEN]; /**< MAC addresses. */
char *ec_master_version_str = EC_MASTER_VERSION; /**< Version string. */
@@ -92,7 +95,7 @@ MODULE_PARM_DESC(backup_devices, "MAC addresses of backup devices");
/** Module initialization.
*
* Initializes \a ec_master_count masters.
* Initializes \a master_count masters.
* \return 0 on success, else < 0
*/
int __init ec_init_module(void)
@@ -119,6 +122,12 @@ int __init ec_init_module(void)
goto out_put;
}
if (alloc_chrdev_region(&device_number, 0, master_count, "EtherCAT")) {
EC_ERR("Failed to obtain device number(s)!\n");
ret = -EBUSY;
goto out_del;
}
// zero MAC addresses
memset(macs, 0x00, sizeof(uint8_t) * MAX_MASTERS * 2 * ETH_ALEN);
@@ -126,12 +135,12 @@ int __init ec_init_module(void)
for (i = 0; i < master_count; i++) {
if (ec_mac_parse(macs[i][0], main_devices[i], 0)) {
ret = -EINVAL;
goto out_del;
goto out_cdev;
}
if (i < backup_count && ec_mac_parse(macs[i][1], backup_devices[i], 1)) {
ret = -EINVAL;
goto out_del;
goto out_cdev;
}
}
@@ -140,12 +149,13 @@ int __init ec_init_module(void)
GFP_KERNEL))) {
EC_ERR("Failed to allocate memory for EtherCAT masters.\n");
ret = -ENOMEM;
goto out_del;
goto out_cdev;
}
}
for (i = 0; i < master_count; i++) {
if (ec_master_init(&masters[i], &kobj, i, macs[i][0], macs[i][1])) {
if (ec_master_init(&masters[i], &kobj, i, macs[i][0], macs[i][1],
device_number)) {
ret = -EIO;
goto out_free_masters;
}
@@ -158,6 +168,8 @@ int __init ec_init_module(void)
out_free_masters:
for (i--; i >= 0; i--) ec_master_clear(&masters[i]);
kfree(masters);
out_cdev:
unregister_chrdev_region(device_number, master_count);
out_del:
kobject_del(&kobj);
out_put:
@@ -180,6 +192,8 @@ void __exit ec_cleanup_module(void)
}
if (master_count)
kfree(masters);
unregister_chrdev_region(device_number, master_count);
kobject_del(&kobj);
kobject_put(&kobj);

View File

@@ -49,6 +49,7 @@
#------------------------------------------------------------------------------
CDEV='EtherCAT'
MODPROBE=/sbin/modprobe
RMMOD=/sbin/rmmod
MODINFO=/sbin/modinfo
@@ -172,6 +173,7 @@ start)
MASTER_INDEX=$(expr ${MASTER_INDEX} + 1)
done
MASTER_INDICES=`seq 0 $((${MASTER_INDEX} - 1))`
# load master module
if ! ${MODPROBE} ${MODPROBE_FLAGS} ec_master \
@@ -179,6 +181,17 @@ start)
exit_fail
fi
# remove stale device nodes
rm -f /dev/${CDEV}*
# get dynamic major number
MAJOR=$(awk "\$2==\"EtherCAT\" {print \$1}" /proc/devices)
# create character devices
for i in ${MASTER_INDICES}; do
mknod /dev/${CDEV}${i} c ${MAJOR} ${i}
done
# check for modules to replace
for MODULE in ${DEVICE_MODULES}; do
ECMODULE=ec_${MODULE}
@@ -213,6 +226,9 @@ stop)
fi;
done
# remove device nodes
rm -f /dev/${CDEV}*
sleep 1
# reload previous modules

42
tools/Makefile.am Normal file
View File

@@ -0,0 +1,42 @@
#------------------------------------------------------------------------------
#
# $Id$
#
# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
#
# This file is part of the IgH EtherCAT Master.
#
# The IgH EtherCAT Master is free software; you can redistribute it
# and/or modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# The IgH EtherCAT Master is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with the IgH EtherCAT Master; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# The right to use EtherCAT Technology is granted and comes free of
# charge under condition of compatibility of product made by
# Licensee. People intending to distribute/sell products based on the
# code, have to sign an agreement to guarantee that products using
# software based on IgH EtherCAT master stay compatible with the actual
# EtherCAT specification (which are released themselves as an open
# standard) as the (only) precondition to have the right to use EtherCAT
# Technology, IP and trade marks.
#
#------------------------------------------------------------------------------
bin_PROGRAMS = ethercat
ethercat_SOURCES = \
Master.cpp Master.h \
main.cpp
ethercat_CFLAGS = -I../master
#------------------------------------------------------------------------------

140
tools/Master.cpp Normal file
View File

@@ -0,0 +1,140 @@
/*****************************************************************************
*
* $Id$
*
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#include "Master.h"
#include "../master/ioctl.h"
/****************************************************************************/
Master::Master()
{
index = 0;
fd = -1;
}
/****************************************************************************/
Master::~Master()
{
close();
}
/****************************************************************************/
void Master::open(unsigned int index)
{
stringstream deviceName;
Master::index = index;
deviceName << "/dev/EtherCAT" << index;
if ((fd = ::open(deviceName.str().c_str(), O_RDONLY)) == -1) {
stringstream err;
err << "Failed to open master device " << deviceName.str() << ": "
<< strerror(errno);
throw MasterException(err.str());
}
}
/****************************************************************************/
void Master::close()
{
if (fd == -1)
return;
::close(fd);
}
/****************************************************************************/
unsigned int Master::slaveCount()
{
unsigned int numSlaves;
if (ioctl(fd, EC_IOCTL_SLAVE_COUNT, &numSlaves)) {
stringstream err;
err << "Failed to get number of slaves: " << strerror(errno);
throw MasterException(err.str());
}
return numSlaves;
}
/****************************************************************************/
void Master::listSlaves()
{
unsigned int numSlaves = slaveCount(), i;
struct ec_ioctl_slave_info *infos, *info;
uint16_t lastAlias, aliasIndex;
if (!numSlaves)
return;
infos = new struct ec_ioctl_slave_info[numSlaves];
if (ioctl(fd, EC_IOCTL_SLAVE_INFO, infos)) {
stringstream err;
err << "Failed to get slave information: " << strerror(errno);
throw MasterException(err.str());
}
lastAlias = 0;
aliasIndex = 0;
for (i = 0; i < numSlaves; i++) {
info = &infos[i];
cout << setw(2) << info->ring_position << " ";
if (info->alias) {
lastAlias = info->alias;
aliasIndex = 0;
}
if (lastAlias) {
cout << setw(10) << "#" << lastAlias << ":" << aliasIndex;
}
cout << " " << slaveState(info->state) << " ";
if (strlen(info->description)) {
cout << info->description;
} else {
cout << "0x" << hex << setfill('0') << info->vendor_id
<< ":0x" << info->product_code;
}
cout << endl;
}
delete [] infos;
}
/****************************************************************************/
string Master::slaveState(uint8_t state) const
{
switch (state) {
case 1: return "INIT";
case 2: return "PREOP";
case 4: return "SAFEOP";
case 8: return "OP";
default: return "???";
}
}
/****************************************************************************/

54
tools/Master.h Normal file
View File

@@ -0,0 +1,54 @@
/*****************************************************************************
*
* $Id$
*
****************************************************************************/
#ifndef __EC_MASTER_H__
#define __EC_MASTER_H__
#include <stdexcept>
using namespace std;
/****************************************************************************/
class MasterException:
public runtime_error
{
public:
/** Constructor with std::string parameter. */
MasterException(
const string &s /**< Message. */
): runtime_error(s) {}
/** Constructor with const char pointer parameter. */
MasterException(
const char *s /**< Message. */
): runtime_error(s) {}
};
/****************************************************************************/
class Master
{
public:
Master();
~Master();
void open(unsigned int);
void close();
unsigned int slaveCount();
void listSlaves();
protected:
string slaveState(uint8_t) const;
private:
unsigned int index;
int fd;
};
/****************************************************************************/
#endif

117
tools/main.cpp Normal file
View File

@@ -0,0 +1,117 @@
/*****************************************************************************
*
* $Id$
*
****************************************************************************/
#include <getopt.h>
#include <iostream>
#include <string>
using namespace std;
#include "Master.h"
/*****************************************************************************/
#define DEFAULT_MASTER 0
#define DEFAULT_COMMAND "slaves"
#define DEFAULT_SLAVESPEC ""
static unsigned int masterIndex = DEFAULT_MASTER;
static string slaveSpec = DEFAULT_SLAVESPEC;
static string command = DEFAULT_COMMAND;
/*****************************************************************************/
void printUsage()
{
cerr
<< "Usage: ethercat <COMMAND> [OPTIONS]" << endl
<< "Commands:" << endl
<< " list (ls, slaves) List all slaves (former 'lsec')." << endl
<< "Global options:" << endl
<< " --master -m <master> Index of the master to use. Default: "
<< DEFAULT_MASTER << endl
<< " --slave -s <slave> Slave specification. Default: All "
"slaves." << endl
<< " --help -h Show this help." << endl;
}
/*****************************************************************************/
void getOptions(int argc, char **argv)
{
int c, argCount, optionIndex, number;
char *remainder;
static struct option longOptions[] = {
//name, has_arg, flag, val
{"master", required_argument, NULL, 'm'},
{"slave", required_argument, NULL, 's'},
{"help", no_argument, NULL, 'h'},
{}
};
do {
c = getopt_long(argc, argv, "m:s:h", longOptions, &optionIndex);
switch (c) {
case 'm':
number = strtoul(optarg, &remainder, 0);
if (remainder == optarg || *remainder || number < 0) {
cerr << "Invalid master number " << optarg << "!" << endl;
printUsage();
exit(1);
}
masterIndex = number;
break;
case 's':
slaveSpec = optarg;
break;
case 'h':
case '?':
printUsage();
exit(0);
default:
break;
}
}
while (c != -1);
argCount = argc - optind;
if (!argCount) {
cerr << "Please specify a command!" << endl;
printUsage();
exit(1);
}
command = argv[optind];
}
/****************************************************************************/
int main(int argc, char **argv)
{
Master master;
getOptions(argc, argv);
master.open(masterIndex);
if (command == "list" || command == "ls" || command == "slaves") {
master.listSlaves();
} else {
cerr << "Unknown command " << command << "!" << endl;
printUsage();
exit(1);
}
return 0;
}
/****************************************************************************/