10 #include <iostream> |
10 #include <iostream> |
11 #include <string> |
11 #include <string> |
12 #include <vector> |
12 #include <vector> |
13 using namespace std; |
13 using namespace std; |
14 |
14 |
15 #include "Master.h" |
15 #include "globals.h" |
16 |
16 |
17 /*****************************************************************************/ |
17 /*****************************************************************************/ |
18 |
18 |
19 #define DEFAULT_MASTER 0 |
19 string binaryBaseName; |
20 |
20 unsigned int masterIndex = 0; |
21 static string cmdName; |
21 int slavePosition = -1; |
22 static unsigned int masterIndex = DEFAULT_MASTER; |
22 int domainIndex = -1; |
23 static int slavePosition = -1; |
23 string command; |
24 static int domainIndex = -1; |
|
25 static string command; |
|
26 vector<string> commandArgs; |
24 vector<string> commandArgs; |
27 static Master::Verbosity verbosity = Master::Normal; |
25 Verbosity verbosity = Normal; |
28 string dataTypeStr; |
26 string dataTypeStr; |
29 bool force = false; |
27 bool force = false; |
|
28 |
30 bool helpRequested = false; |
29 bool helpRequested = false; |
31 |
30 |
32 /*****************************************************************************/ |
31 MasterDevice masterDev; |
33 |
32 |
34 void printUsage() |
33 /*****************************************************************************/ |
35 { |
34 |
36 cerr |
35 struct Command { |
37 << "Usage: " << cmdName << " <COMMAND> [OPTIONS]" << endl |
36 void (*func)(void); |
38 << "Commands:" << endl |
37 const char *helpString; |
39 << " alias Write alias addresses." << endl |
38 |
40 << " config Show bus configuration." << endl |
39 int execute(void) const; |
41 << " data Output binary domain process data." << endl |
40 void displayHelp(void) const; |
42 << " debug Set the master's debug level." << endl |
41 }; |
43 << " domain Show domain information." << endl |
42 |
44 << " master Show master information." << endl |
43 struct CommandAlias { |
45 << " pdos List Pdo assignment/mapping." << endl |
44 const char *name; |
46 << " sdo_download Write an Sdo entry." << endl |
45 const Command *command; |
47 << " sdos List Sdo dictionaries." << endl |
46 }; |
48 << " sdo_upload Read an Sdo entry." << endl |
47 |
49 << " sii_read Output a slave's SII contents." << endl |
48 /*****************************************************************************/ |
50 << " sii_write Write slave's SII contents." << endl |
49 |
51 << " slaves Show slaves." << endl |
50 #define COMMAND(name) \ |
52 << " state Request slave states." << endl |
51 void command_##name(void); \ |
53 << " xml Generate slave information xmls." << endl |
52 extern const char *help_##name; \ |
54 << "Global options:" << endl |
53 const Command cmd_##name = {command_##name, help_##name}; |
55 << " --master -m <master> Index of the master to use. Default: " |
54 |
56 << DEFAULT_MASTER << endl |
55 COMMAND(alias); |
57 << " --slave -s <index> Positive numerical ring position," |
56 COMMAND(config); |
58 << endl |
57 |
59 << " or 'all' for all slaves (default)." |
58 const CommandAlias commandAliases[] = { |
60 << endl |
59 {"alias", &cmd_alias}, |
61 << " --domain -d <index> Positive numerical index," |
60 |
62 << endl |
61 {"config", &cmd_config}, |
63 << " or 'all' for all domains (default)." |
62 {"conf", &cmd_config}, |
64 << endl |
63 {"cf", &cmd_config}, |
65 << " --type -t <type> Forced Sdo data type." << endl |
64 }; |
66 << " --force -f Force action." << endl |
65 |
67 << " --quiet -q Output less information." << endl |
66 #if 0 |
68 << " --verbose -v Output more information." << endl |
|
69 << " --help -h Show this help." << endl |
|
70 << "Call '" << cmdName << " <COMMAND> --help' for command-specific " |
|
71 << "help." << endl |
|
72 << "Send bug reports to " << PACKAGE_BUGREPORT << "." << endl; |
|
73 } |
|
74 |
|
75 /*****************************************************************************/ |
|
76 |
|
77 void getOptions(int argc, char **argv) |
|
78 { |
|
79 int c, argCount, optionIndex, number; |
|
80 char *remainder; |
|
81 |
|
82 static struct option longOptions[] = { |
|
83 //name, has_arg, flag, val |
|
84 {"master", required_argument, NULL, 'm'}, |
|
85 {"slave", required_argument, NULL, 's'}, |
|
86 {"domain", required_argument, NULL, 'd'}, |
|
87 {"type", required_argument, NULL, 't'}, |
|
88 {"force", no_argument, NULL, 'f'}, |
|
89 {"quiet", no_argument, NULL, 'q'}, |
|
90 {"verbose", no_argument, NULL, 'v'}, |
|
91 {"help", no_argument, NULL, 'h'}, |
|
92 {} |
|
93 }; |
|
94 |
|
95 do { |
|
96 c = getopt_long(argc, argv, "m:s:d:t:fqvh", longOptions, &optionIndex); |
|
97 |
|
98 switch (c) { |
|
99 case 'm': |
|
100 number = strtoul(optarg, &remainder, 0); |
|
101 if (remainder == optarg || *remainder || number < 0) { |
|
102 cerr << "Invalid master number " << optarg << "!" << endl; |
|
103 printUsage(); |
|
104 exit(1); |
|
105 } |
|
106 masterIndex = number; |
|
107 break; |
|
108 |
|
109 case 's': |
|
110 if (!strcmp(optarg, "all")) { |
|
111 slavePosition = -1; |
|
112 } else { |
|
113 number = strtoul(optarg, &remainder, 0); |
|
114 if (remainder == optarg || *remainder |
|
115 || number < 0 || number > 0xFFFF) { |
|
116 cerr << "Invalid slave position " |
|
117 << optarg << "!" << endl; |
|
118 printUsage(); |
|
119 exit(1); |
|
120 } |
|
121 slavePosition = number; |
|
122 } |
|
123 break; |
|
124 |
|
125 case 'd': |
|
126 if (!strcmp(optarg, "all")) { |
|
127 domainIndex = -1; |
|
128 } else { |
|
129 number = strtoul(optarg, &remainder, 0); |
|
130 if (remainder == optarg || *remainder || number < 0) { |
|
131 cerr << "Invalid domain index " |
|
132 << optarg << "!" << endl; |
|
133 printUsage(); |
|
134 exit(1); |
|
135 } |
|
136 domainIndex = number; |
|
137 } |
|
138 break; |
|
139 |
|
140 case 't': |
|
141 dataTypeStr = optarg; |
|
142 break; |
|
143 |
|
144 case 'f': |
|
145 force = true; |
|
146 break; |
|
147 |
|
148 case 'q': |
|
149 verbosity = Master::Quiet; |
|
150 break; |
|
151 |
|
152 case 'v': |
|
153 verbosity = Master::Verbose; |
|
154 break; |
|
155 |
|
156 case 'h': |
|
157 helpRequested = true; |
|
158 break; |
|
159 |
|
160 case '?': |
|
161 printUsage(); |
|
162 exit(1); |
|
163 |
|
164 default: |
|
165 break; |
|
166 } |
|
167 } |
|
168 while (c != -1); |
|
169 |
|
170 argCount = argc - optind; |
|
171 |
|
172 if (!argCount) { |
|
173 if (!helpRequested) { |
|
174 cerr << "Please specify a command!" << endl; |
|
175 } |
|
176 printUsage(); |
|
177 exit(!helpRequested); |
|
178 } |
|
179 |
|
180 command = argv[optind]; |
|
181 while (++optind < argc) |
|
182 commandArgs.push_back(string(argv[optind])); |
|
183 } |
|
184 |
|
185 /****************************************************************************/ |
|
186 |
|
187 int main(int argc, char **argv) |
|
188 { |
|
189 Master master; |
|
190 |
|
191 cmdName = basename(argv[0]); |
|
192 |
|
193 getOptions(argc, argv); |
|
194 |
|
195 master.setIndex(masterIndex); |
|
196 master.setVerbosity(verbosity); |
|
197 |
|
198 try { |
|
199 if (command == "alias") { |
|
200 master.writeAlias(slavePosition, force, commandArgs); |
|
201 } else if (command == "config") { |
|
202 master.showConfigs(); |
|
203 } else if (command == "data") { |
67 } else if (command == "data") { |
204 master.outputData(domainIndex); |
68 master.outputData(domainIndex); |
205 } else if (command == "debug") { |
69 } else if (command == "debug") { |
206 master.setDebug(commandArgs); |
70 master.setDebug(commandArgs); |
207 } else if (command == "domain") { |
71 } else if (command == "domain") { |
225 master.siiWrite(slavePosition, force, commandArgs); |
89 master.siiWrite(slavePosition, force, commandArgs); |
226 } else if (command == "state") { |
90 } else if (command == "state") { |
227 master.requestStates(slavePosition, commandArgs); |
91 master.requestStates(slavePosition, commandArgs); |
228 } else if (command == "xml") { |
92 } else if (command == "xml") { |
229 master.generateXml(slavePosition); |
93 master.generateXml(slavePosition); |
|
94 #endif |
|
95 |
|
96 /*****************************************************************************/ |
|
97 |
|
98 void printUsage() |
|
99 { |
|
100 cerr |
|
101 << "Usage: " << binaryBaseName << " <COMMAND> [OPTIONS]" << endl |
|
102 << "Commands:" << endl |
|
103 << " alias Write alias addresses." << endl |
|
104 << " config Show bus configuration." << endl |
|
105 << " data Output binary domain process data." << endl |
|
106 << " debug Set the master's debug level." << endl |
|
107 << " domain Show domain information." << endl |
|
108 << " master Show master information." << endl |
|
109 << " pdos List Pdo assignment/mapping." << endl |
|
110 << " sdo_download Write an Sdo entry." << endl |
|
111 << " sdos List Sdo dictionaries." << endl |
|
112 << " sdo_upload Read an Sdo entry." << endl |
|
113 << " sii_read Output a slave's SII contents." << endl |
|
114 << " sii_write Write slave's SII contents." << endl |
|
115 << " slaves Show slaves." << endl |
|
116 << " state Request slave states." << endl |
|
117 << " xml Generate slave information xmls." << endl |
|
118 << "Global options:" << endl |
|
119 << " --master -m <master> Index of the master to use. Default: 0" |
|
120 << endl |
|
121 << " --slave -s <index> Positive numerical ring position," |
|
122 << endl |
|
123 << " or 'all' for all slaves (default)." |
|
124 << endl |
|
125 << " --domain -d <index> Positive numerical index," |
|
126 << endl |
|
127 << " or 'all' for all domains (default)." |
|
128 << endl |
|
129 << " --type -t <type> Forced Sdo data type." << endl |
|
130 << " --force -f Force action." << endl |
|
131 << " --quiet -q Output less information." << endl |
|
132 << " --verbose -v Output more information." << endl |
|
133 << " --help -h Show this help." << endl |
|
134 << "Call '" << binaryBaseName |
|
135 << " <COMMAND> --help' for command-specific help." << endl |
|
136 << "Send bug reports to " << PACKAGE_BUGREPORT << "." << endl; |
|
137 } |
|
138 |
|
139 /*****************************************************************************/ |
|
140 |
|
141 void getOptions(int argc, char **argv) |
|
142 { |
|
143 int c, argCount, optionIndex, number; |
|
144 char *remainder; |
|
145 |
|
146 static struct option longOptions[] = { |
|
147 //name, has_arg, flag, val |
|
148 {"master", required_argument, NULL, 'm'}, |
|
149 {"slave", required_argument, NULL, 's'}, |
|
150 {"domain", required_argument, NULL, 'd'}, |
|
151 {"type", required_argument, NULL, 't'}, |
|
152 {"force", no_argument, NULL, 'f'}, |
|
153 {"quiet", no_argument, NULL, 'q'}, |
|
154 {"verbose", no_argument, NULL, 'v'}, |
|
155 {"help", no_argument, NULL, 'h'}, |
|
156 {} |
|
157 }; |
|
158 |
|
159 do { |
|
160 c = getopt_long(argc, argv, "m:s:d:t:fqvh", longOptions, &optionIndex); |
|
161 |
|
162 switch (c) { |
|
163 case 'm': |
|
164 number = strtoul(optarg, &remainder, 0); |
|
165 if (remainder == optarg || *remainder || number < 0) { |
|
166 cerr << "Invalid master number " << optarg << "!" << endl; |
|
167 printUsage(); |
|
168 exit(1); |
|
169 } |
|
170 masterIndex = number; |
|
171 break; |
|
172 |
|
173 case 's': |
|
174 if (!strcmp(optarg, "all")) { |
|
175 slavePosition = -1; |
|
176 } else { |
|
177 number = strtoul(optarg, &remainder, 0); |
|
178 if (remainder == optarg || *remainder |
|
179 || number < 0 || number > 0xFFFF) { |
|
180 cerr << "Invalid slave position " |
|
181 << optarg << "!" << endl; |
|
182 printUsage(); |
|
183 exit(1); |
|
184 } |
|
185 slavePosition = number; |
|
186 } |
|
187 break; |
|
188 |
|
189 case 'd': |
|
190 if (!strcmp(optarg, "all")) { |
|
191 domainIndex = -1; |
|
192 } else { |
|
193 number = strtoul(optarg, &remainder, 0); |
|
194 if (remainder == optarg || *remainder || number < 0) { |
|
195 cerr << "Invalid domain index " |
|
196 << optarg << "!" << endl; |
|
197 printUsage(); |
|
198 exit(1); |
|
199 } |
|
200 domainIndex = number; |
|
201 } |
|
202 break; |
|
203 |
|
204 case 't': |
|
205 dataTypeStr = optarg; |
|
206 break; |
|
207 |
|
208 case 'f': |
|
209 force = true; |
|
210 break; |
|
211 |
|
212 case 'q': |
|
213 verbosity = Quiet; |
|
214 break; |
|
215 |
|
216 case 'v': |
|
217 verbosity = Verbose; |
|
218 break; |
|
219 |
|
220 case 'h': |
|
221 helpRequested = true; |
|
222 break; |
|
223 |
|
224 case '?': |
|
225 printUsage(); |
|
226 exit(1); |
|
227 |
|
228 default: |
|
229 break; |
|
230 } |
|
231 } |
|
232 while (c != -1); |
|
233 |
|
234 argCount = argc - optind; |
|
235 |
|
236 if (!argCount) { |
|
237 if (!helpRequested) { |
|
238 cerr << "Please specify a command!" << endl; |
|
239 } |
|
240 printUsage(); |
|
241 exit(!helpRequested); |
|
242 } |
|
243 |
|
244 command = argv[optind]; |
|
245 while (++optind < argc) |
|
246 commandArgs.push_back(string(argv[optind])); |
|
247 } |
|
248 |
|
249 /****************************************************************************/ |
|
250 |
|
251 int Command::execute() const |
|
252 { |
|
253 try { |
|
254 func(); |
|
255 } catch (InvalidUsageException &e) { |
|
256 cerr << e.what() << endl << endl; |
|
257 displayHelp(); |
|
258 return 1; |
|
259 } catch (ExecutionFailureException &e) { |
|
260 cerr << e.what() << endl; |
|
261 return 1; |
|
262 } catch (MasterDeviceException &e) { |
|
263 cerr << e.what() << endl; |
|
264 return 1; |
|
265 } |
|
266 |
|
267 return 0; |
|
268 } |
|
269 |
|
270 /****************************************************************************/ |
|
271 |
|
272 void Command::displayHelp() const |
|
273 { |
|
274 cerr << binaryBaseName << " " << command << " " << helpString; |
|
275 } |
|
276 |
|
277 /****************************************************************************/ |
|
278 |
|
279 int main(int argc, char **argv) |
|
280 { |
|
281 int retval = 0; |
|
282 const CommandAlias *alias; |
|
283 const CommandAlias *endAlias = |
|
284 commandAliases + sizeof(commandAliases) / sizeof(CommandAlias); |
|
285 |
|
286 binaryBaseName = basename(argv[0]); |
|
287 getOptions(argc, argv); |
|
288 |
|
289 // search command alias in alias map |
|
290 for (alias = commandAliases; alias < endAlias; alias++) { |
|
291 if (command == alias->name) |
|
292 break; |
|
293 } |
|
294 |
|
295 if (alias < endAlias) { // command alias found |
|
296 if (!helpRequested) { |
|
297 masterDev.setIndex(masterIndex); |
|
298 retval = alias->command->execute(); |
230 } else { |
299 } else { |
231 cerr << "Unknown command " << command << "!" << endl; |
300 alias->command->displayHelp(); |
232 printUsage(); |
|
233 exit(1); |
|
234 } |
301 } |
235 } catch (MasterException &e) { |
302 } else { // command not found |
236 cerr << e.what() << endl; |
303 cerr << "Unknown command " << command << "!" << endl << endl; |
237 exit(1); |
304 printUsage(); |
|
305 retval = 1; |
238 } |
306 } |
239 |
307 |
240 return 0; |
308 return retval; |
241 } |
309 } |
242 |
310 |
243 /****************************************************************************/ |
311 /****************************************************************************/ |