# HG changeset patch # User Florian Pose # Date 1212073886 0 # Node ID fede1d8f5b71aed879a144231c01ca2e25012e55 # Parent c8c2caf0d667c14889ce40851df55f112fc4b58a Added the new ethercat comman-line tool with lsec functionality. diff -r c8c2caf0d667 -r fede1d8f5b71 Makefile.am --- a/Makefile.am Thu May 29 09:53:10 2008 +0000 +++ b/Makefile.am Thu May 29 15:11:26 2008 +0000 @@ -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 \ diff -r c8c2caf0d667 -r fede1d8f5b71 NEWS --- a/NEWS Thu May 29 09:53:10 2008 +0000 +++ b/NEWS Thu May 29 15:11:26 2008 +0000 @@ -49,6 +49,8 @@ - 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 @@ * 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 diff -r c8c2caf0d667 -r fede1d8f5b71 TODO --- a/TODO Thu May 29 09:53:10 2008 +0000 +++ b/TODO Thu May 29 15:11:26 2008 +0000 @@ -8,8 +8,7 @@ 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(). diff -r c8c2caf0d667 -r fede1d8f5b71 configure.ac --- a/configure.ac Thu May 29 09:53:10 2008 +0000 +++ b/configure.ac Thu May 29 15:11:26 2008 +0000 @@ -19,6 +19,8 @@ AC_DEFINE_UNQUOTED(BRANCH, ["$branch"], [Subversion branch]) AC_SUBST(BRANCH, [$branch]) +AC_PROG_CXX + #------------------------------------------------------------------------------ # Linux sources #------------------------------------------------------------------------------ @@ -510,6 +512,7 @@ script/Makefile script/init.d/Makefile script/sysconfig/Makefile + tools/Makefile ]) AC_OUTPUT diff -r c8c2caf0d667 -r fede1d8f5b71 master/Kbuild.in --- a/master/Kbuild.in Thu May 29 09:53:10 2008 +0000 +++ b/master/Kbuild.in Thu May 29 15:11:26 2008 +0000 @@ -36,6 +36,7 @@ obj-m := ec_master.o ec_master-objs := \ + cdev.o \ datagram.o \ device.o \ domain.o \ diff -r c8c2caf0d667 -r fede1d8f5b71 master/Makefile.am --- a/master/Makefile.am Thu May 29 09:53:10 2008 +0000 +++ b/master/Makefile.am Thu May 29 15:11:26 2008 +0000 @@ -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 @@ 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 \ diff -r c8c2caf0d667 -r fede1d8f5b71 master/cdev.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/cdev.c Thu May 29 15:11:26 2008 +0000 @@ -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 + +#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; + } +} + +/*****************************************************************************/ diff -r c8c2caf0d667 -r fede1d8f5b71 master/cdev.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/cdev.h Thu May 29 15:11:26 2008 +0000 @@ -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 +#include + +#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 diff -r c8c2caf0d667 -r fede1d8f5b71 master/ioctl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/ioctl.h Thu May 29 15:11:26 2008 +0000 @@ -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 diff -r c8c2caf0d667 -r fede1d8f5b71 master/master.c --- a/master/master.c Thu May 29 09:53:10 2008 +0000 +++ b/master/master.c Thu May 29 15:11:26 2008 +0000 @@ -105,7 +105,8 @@ 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 @@ 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 @@ 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 @@ 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); diff -r c8c2caf0d667 -r fede1d8f5b71 master/master.h --- a/master/master.h Thu May 29 09:53:10 2008 +0000 +++ b/master/master.h Thu May 29 15:11:26 2008 +0000 @@ -50,6 +50,7 @@ #include "device.h" #include "domain.h" #include "fsm_master.h" +#include "cdev.h" /*****************************************************************************/ @@ -84,6 +85,8 @@ 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 @@ // 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 diff -r c8c2caf0d667 -r fede1d8f5b71 master/module.c --- a/master/module.c Thu May 29 09:53:10 2008 +0000 +++ b/master/module.c Thu May 29 15:11:26 2008 +0000 @@ -40,6 +40,7 @@ #include #include #include +#include #include "globals.h" #include "master.h" @@ -68,6 +69,8 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } if (master_count) kfree(masters); + + unregister_chrdev_region(device_number, master_count); kobject_del(&kobj); kobject_put(&kobj); diff -r c8c2caf0d667 -r fede1d8f5b71 script/init.d/ethercat --- a/script/init.d/ethercat Thu May 29 09:53:10 2008 +0000 +++ b/script/init.d/ethercat Thu May 29 15:11:26 2008 +0000 @@ -49,6 +49,7 @@ #------------------------------------------------------------------------------ +CDEV='EtherCAT' MODPROBE=/sbin/modprobe RMMOD=/sbin/rmmod MODINFO=/sbin/modinfo @@ -172,6 +173,7 @@ 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 @@ 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 @@ fi; done + # remove device nodes + rm -f /dev/${CDEV}* + sleep 1 # reload previous modules diff -r c8c2caf0d667 -r fede1d8f5b71 tools/Makefile.am --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/Makefile.am Thu May 29 15:11:26 2008 +0000 @@ -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 + +#------------------------------------------------------------------------------ diff -r c8c2caf0d667 -r fede1d8f5b71 tools/Master.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/Master.cpp Thu May 29 15:11:26 2008 +0000 @@ -0,0 +1,140 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +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 "???"; + } +} + +/****************************************************************************/ diff -r c8c2caf0d667 -r fede1d8f5b71 tools/Master.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/Master.h Thu May 29 15:11:26 2008 +0000 @@ -0,0 +1,54 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#ifndef __EC_MASTER_H__ +#define __EC_MASTER_H__ + +#include +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 diff -r c8c2caf0d667 -r fede1d8f5b71 tools/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/main.cpp Thu May 29 15:11:26 2008 +0000 @@ -0,0 +1,117 @@ +/***************************************************************************** + * + * $Id$ + * + ****************************************************************************/ + +#include + +#include +#include +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 [OPTIONS]" << endl + << "Commands:" << endl + << " list (ls, slaves) List all slaves (former 'lsec')." << endl + << "Global options:" << endl + << " --master -m Index of the master to use. Default: " + << DEFAULT_MASTER << endl + << " --slave -s 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; +} + +/****************************************************************************/