26 * industrial property and similar rights of Beckhoff Automation GmbH. |
26 * industrial property and similar rights of Beckhoff Automation GmbH. |
27 * |
27 * |
28 ****************************************************************************/ |
28 ****************************************************************************/ |
29 |
29 |
30 #include <iostream> |
30 #include <iostream> |
|
31 #include <iomanip> |
31 using namespace std; |
32 using namespace std; |
32 |
33 |
33 #include "CommandSoeWrite.h" |
34 #include "CommandSoeWrite.h" |
34 #include "MasterDevice.h" |
35 #include "MasterDevice.h" |
35 |
36 |
36 /*****************************************************************************/ |
37 /*****************************************************************************/ |
37 |
38 |
38 CommandSoeWrite::CommandSoeWrite(): |
39 CommandSoeWrite::CommandSoeWrite(): |
39 SoeCommand("soe_write", "Write an SoE IDN to a slave.") |
40 Command("soe_write", "Write an SoE IDN to a slave.") |
40 { |
41 { |
41 } |
42 } |
42 |
43 |
43 /*****************************************************************************/ |
44 /*****************************************************************************/ |
44 |
45 |
45 string CommandSoeWrite::helpString() const |
46 string CommandSoeWrite::helpString(const string &binaryBaseName) const |
46 { |
47 { |
47 stringstream str; |
48 stringstream str; |
48 |
49 |
49 str << getName() << " [OPTIONS] <IDN> <VALUE>" << endl |
50 str << binaryBaseName << " " << getName() |
|
51 << " [OPTIONS] <IDN> <VALUE>" << endl |
|
52 << binaryBaseName << " " << getName() |
|
53 << " [OPTIONS] <DRIVE> <IDN> <VALUE>" << endl |
50 << endl |
54 << endl |
51 << getBriefDescription() << endl |
55 << getBriefDescription() << endl |
52 << endl |
56 << endl |
53 << "This command requires a single slave to be selected." << endl |
57 << "This command requires a single slave to be selected." << endl |
54 << endl |
58 << endl |
55 << "Arguments:" << endl |
59 << "Arguments:" << endl |
|
60 << " DRIVE is the drive number (0 - 7). If omitted, 0 is assumed." |
|
61 << endl |
56 << " IDN is the IDN and must be either an unsigned" << endl |
62 << " IDN is the IDN and must be either an unsigned" << endl |
57 << " 16 bit number acc. to IEC 61800-7-204:" << endl |
63 << " 16 bit number acc. to IEC 61800-7-204:" << endl |
58 << " Bit 15: (0) Standard data, (1) Product data" << endl |
64 << " Bit 15: (0) Standard data, (1) Product data" << endl |
59 << " Bit 14 - 12: Parameter set (0 - 7)" << endl |
65 << " Bit 14 - 12: Parameter set (0 - 7)" << endl |
60 << " Bit 11 - 0: Data block number" << endl |
66 << " Bit 11 - 0: Data block number" << endl |
79 |
85 |
80 /****************************************************************************/ |
86 /****************************************************************************/ |
81 |
87 |
82 void CommandSoeWrite::execute(const StringVector &args) |
88 void CommandSoeWrite::execute(const StringVector &args) |
83 { |
89 { |
84 stringstream strIdn, err; |
90 stringstream err; |
85 const DataType *dataType = NULL; |
91 const DataType *dataType = NULL; |
86 ec_ioctl_slave_soe_write_t ioctl; |
92 ec_ioctl_slave_soe_write_t ioctl; |
87 SlaveList slaves; |
93 SlaveList slaves; |
88 size_t memSize; |
94 size_t memSize; |
|
95 int driveArgIndex = -1, idnArgIndex = -1, valueArgIndex = -1; |
89 |
96 |
90 if (args.size() != 2) { |
97 if (args.size() == 2) { |
91 err << "'" << getName() << "' takes 2 arguments!"; |
98 idnArgIndex = 0; |
|
99 valueArgIndex = 1; |
|
100 } else if (args.size() == 3) { |
|
101 driveArgIndex = 0; |
|
102 idnArgIndex = 1; |
|
103 valueArgIndex = 2; |
|
104 } else { |
|
105 err << "'" << getName() << "' takes eiter 2 or 3 arguments!"; |
92 throwInvalidUsageException(err); |
106 throwInvalidUsageException(err); |
93 } |
107 } |
94 |
108 |
95 ioctl.drive_no = 0; // FIXME |
109 if (driveArgIndex >= 0) { |
|
110 stringstream str; |
|
111 unsigned int number; |
|
112 str << args[driveArgIndex]; |
|
113 str |
|
114 >> resetiosflags(ios::basefield) // guess base from prefix |
|
115 >> number; |
|
116 if (str.fail() || number > 7) { |
|
117 err << "Invalid drive number '" << args[driveArgIndex] << "'!"; |
|
118 throwInvalidUsageException(err); |
|
119 } |
|
120 ioctl.drive_no = number; |
|
121 } else { |
|
122 ioctl.drive_no = 0; |
|
123 } |
96 |
124 |
97 try { |
125 try { |
98 ioctl.idn = parseIdn(args[0]); |
126 ioctl.idn = parseIdn(args[idnArgIndex]); |
99 } catch (runtime_error &e) { |
127 } catch (runtime_error &e) { |
100 err << "Invalid IDN '" << args[0] << "': " << e.what(); |
128 err << "Invalid IDN '" << args[idnArgIndex] << "': " << e.what(); |
101 throwInvalidUsageException(err); |
129 throwInvalidUsageException(err); |
102 } |
130 } |
103 |
131 |
104 MasterDevice m(getSingleMasterIndex()); |
132 MasterDevice m(getSingleMasterIndex()); |
105 m.open(MasterDevice::ReadWrite); |
133 m.open(MasterDevice::ReadWrite); |
121 |
149 |
122 if (dataType->byteSize) { |
150 if (dataType->byteSize) { |
123 memSize = dataType->byteSize; |
151 memSize = dataType->byteSize; |
124 } else { |
152 } else { |
125 // guess string type size |
153 // guess string type size |
126 memSize = args[1].size() + 1; |
154 memSize = args[valueArgIndex].size() + 1; |
127 if (!memSize) { |
155 if (!memSize) { |
128 err << "Empty argument not allowed."; |
156 err << "Empty argument not allowed."; |
129 throwInvalidUsageException(err); |
157 throwInvalidUsageException(err); |
130 } |
158 } |
131 } |
159 } |
132 |
160 |
133 ioctl.data = new uint8_t[memSize]; |
161 ioctl.data = new uint8_t[memSize]; |
134 |
162 |
135 try { |
163 try { |
136 ioctl.data_size = interpretAsType( |
164 ioctl.data_size = interpretAsType( |
137 dataType, args[1], ioctl.data, memSize); |
165 dataType, args[valueArgIndex], ioctl.data, memSize); |
138 } catch (SizeException &e) { |
166 } catch (SizeException &e) { |
139 delete [] ioctl.data; |
167 delete [] ioctl.data; |
140 throwCommandException(e.what()); |
168 throwCommandException(e.what()); |
141 } catch (ios::failure &e) { |
169 } catch (ios::failure &e) { |
142 delete [] ioctl.data; |
170 delete [] ioctl.data; |
143 err << "Invalid value argument '" << args[1] |
171 err << "Invalid value argument '" << args[valueArgIndex] |
144 << "' for type '" << dataType->name << "'!"; |
172 << "' for type '" << dataType->name << "'!"; |
145 throwInvalidUsageException(err); |
173 throwInvalidUsageException(err); |
146 } |
174 } |
147 |
175 |
148 try { |
176 try { |