fp@1422: /***************************************************************************** fp@1422: * fp@1422: * $Id$ fp@1422: * fp@1422: * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH fp@1422: * fp@1422: * This file is part of the IgH EtherCAT Master. fp@1422: * fp@1422: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1422: * modify it under the terms of the GNU General Public License version 2, as fp@1422: * published by the Free Software Foundation. fp@1422: * fp@1422: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1422: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1422: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1422: * Public License for more details. fp@1422: * fp@1422: * You should have received a copy of the GNU General Public License along fp@1422: * with the IgH EtherCAT Master; if not, write to the Free Software fp@1422: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1422: * fp@1422: * --- fp@1422: * fp@1422: * The license mentioned above concerns the source code only. Using the fp@1422: * EtherCAT technology and brand is only permitted in compliance with the fp@1422: * industrial property and similar rights of Beckhoff Automation GmbH. fp@1422: * fp@1422: ****************************************************************************/ fp@1422: fp@1422: #include fp@1422: #include fp@1422: using namespace std; fp@1422: fp@1422: #include "CommandGraph.h" fp@1422: fp@1422: /*****************************************************************************/ fp@1422: fp@1422: CommandGraph::CommandGraph(): fp@1422: Command("graph", "Output the bus topology as a graph.") fp@1422: { fp@1422: } fp@1422: fp@1422: /*****************************************************************************/ fp@1422: fp@1422: string CommandGraph::helpString() const fp@1422: { fp@1422: stringstream str; fp@1422: fp@1422: str << getName() << " [OPTIONS]" << endl fp@1422: << endl fp@1422: << getBriefDescription() << endl fp@1422: << endl fp@1422: << "The bus is output in DOT language (see" << endl fp@1422: << "http://www.graphviz.org/doc/info/lang.html), which can" << endl fp@1422: << "be processed with the tools from the Graphviz" << endl fp@1422: << "package. Example:" << endl fp@1422: << endl fp@1422: << " ethercat graph | dot -Tsvg > bus.svg" << endl fp@1422: << endl fp@1422: << "See 'man dot' for more information." << endl; fp@1422: fp@1422: return str.str(); fp@1422: } fp@1422: fp@1422: /****************************************************************************/ fp@1422: fp@1422: void CommandGraph::execute(MasterDevice &m, const StringVector &args) fp@1422: { fp@1422: ec_ioctl_master_t master; fp@1422: unsigned int i; fp@1422: typedef vector SlaveVector; fp@1422: SlaveVector slaves; fp@1422: ec_ioctl_slave_t slave; fp@1422: SlaveVector::const_iterator si; fp@1422: string font("fontname=\"Helvetica\""); fp@1422: map portMedia; fp@1422: map::const_iterator mi; fp@1422: map mediaWeights; fp@1422: map::const_iterator wi; fp@1422: fp@1422: portMedia[EC_PORT_MII] = "MII"; fp@1422: mediaWeights[EC_PORT_MII] = 1; fp@1422: fp@1422: portMedia[EC_PORT_EBUS] = "EBUS"; fp@1422: mediaWeights[EC_PORT_EBUS] = 5; fp@1422: fp@1422: if (args.size()) { fp@1422: stringstream err; fp@1422: err << "'" << getName() << "' takes no arguments!"; fp@1422: throwInvalidUsageException(err); fp@1422: } fp@1422: fp@1422: m.open(MasterDevice::Read); fp@1422: m.getMaster(&master); fp@1422: fp@1422: for (i = 0; i < master.slave_count; i++) { fp@1422: m.getSlave(&slave, i); fp@1422: slaves.push_back(slave); fp@1422: } fp@1422: fp@1422: cout << "/* EtherCAT bus graph. Generated by 'ethercat graph'. */" << endl fp@1422: << endl fp@1422: << "strict graph bus {" << endl fp@1422: << " rankdir=\"LR\"" << endl fp@1422: << endl fp@1422: << " master [" << font << ",label=\"EtherCAT\\nMaster\"]" << endl; fp@1422: fp@1422: if (slaves.size()) { fp@1422: cout << " master -- slave0 [" << font; fp@1422: fp@1422: mi = portMedia.find(slaves.front().port_descs[0]); fp@1422: if (mi != portMedia.end()) fp@1422: cout << ",label=\"" << mi->second << "\""; fp@1422: fp@1422: cout << "]" << endl; fp@1422: } fp@1422: cout << endl; fp@1422: fp@1422: for (si = slaves.begin(); si != slaves.end(); si++) { fp@1422: cout << " slave" << si->position << " [" << font << fp@1422: ",shape=\"box\",label=\"" << si->position; fp@1422: if (string(si->order).size()) fp@1422: cout << "\\n" << si->order; fp@1422: cout << "\"]" << endl; fp@1422: fp@1422: for (i = 1; i < EC_MAX_PORTS; i++) { fp@1422: if (si->next_slave[i] == 0xffff) fp@1422: continue; fp@1422: fp@1422: cout << " slave" << si->position << " -- " fp@1422: << "slave" << si->next_slave[i] << " [" << font << "," fp@1422: << "taillabel=\"" << i << "\""; fp@1422: fp@1422: mi = portMedia.find(si->port_descs[i]); fp@1422: if (mi == portMedia.end()) { fp@1422: /* Try medium of next-hop slave. */ fp@1422: unsigned int pos = si->next_slave[i]; fp@1422: if (pos < slaves.size()) { fp@1422: ec_ioctl_slave_t *next = &slaves[pos]; fp@1422: mi = portMedia.find(next->port_descs[0]); fp@1422: } else { fp@1422: cerr << "Invalid next slave pointer." << endl; fp@1422: } fp@1422: } fp@1422: fp@1422: if (mi != portMedia.end()) fp@1422: cout << ",label=\"" << mi->second << "\""; fp@1422: fp@1422: wi = mediaWeights.find(si->port_descs[i]); fp@1422: if (wi != mediaWeights.end()) fp@1422: cout << ",weight=\"" << wi->second << "\""; fp@1422: fp@1422: cout << "]" << endl; fp@1422: } fp@1422: fp@1422: cout << endl; fp@1422: } fp@1422: fp@1422: cout << "}" << endl; fp@1422: } fp@1422: fp@1422: /*****************************************************************************/