47 { |
47 { |
48 stringstream str; |
48 stringstream str; |
49 |
49 |
50 str << binaryBaseName << " " << getName() |
50 str << binaryBaseName << " " << getName() |
51 << " [OPTIONS] <INDEX> <SUBINDEX> <VALUE>" << endl |
51 << " [OPTIONS] <INDEX> <SUBINDEX> <VALUE>" << endl |
|
52 << " [OPTIONS] <INDEX> <VALUE>" << endl |
52 << endl |
53 << endl |
53 << getBriefDescription() << endl |
54 << getBriefDescription() << endl |
54 << endl |
55 << endl |
55 << "This command requires a single slave to be selected." << endl |
56 << "This command requires a single slave to be selected." << endl |
56 << endl |
57 << endl |
57 << "The data type of the SDO entry is taken from the SDO" << endl |
58 << "The data type of the SDO entry is taken from the SDO" << endl |
58 << "dictionary by default. It can be overridden with the" << endl |
59 << "dictionary by default. It can be overridden with the" << endl |
59 << "--type option. If the slave does not support the SDO" << endl |
60 << "--type option. If the slave does not support the SDO" << endl |
60 << "information service or the SDO is not in the dictionary," << endl |
61 << "information service or the SDO is not in the dictionary," << endl |
61 << "the --type option is mandatory." << endl |
62 << "the --type option is mandatory." << endl |
|
63 << endl |
|
64 << "The second call (without <SUBINDEX>) uses the complete" << endl |
|
65 << "access method." << endl |
62 << endl |
66 << endl |
63 << typeInfo() |
67 << typeInfo() |
64 << endl |
68 << endl |
65 << "Arguments:" << endl |
69 << "Arguments:" << endl |
66 << " INDEX is the SDO index and must be an unsigned" << endl |
70 << " INDEX is the SDO index and must be an unsigned" << endl |
67 << " 16 bit number." << endl |
71 << " 16 bit number." << endl |
68 << " SUBINDEX is the SDO entry subindex and must be an" << endl |
72 << " SUBINDEX is the SDO entry subindex and must be an" << endl |
69 << " unsigned 8 bit number." << endl |
73 << " unsigned 8 bit number." << endl |
70 << " VALUE is the value to download and must correspond" << endl |
74 << " VALUE is the value to download and must correspond" << endl |
71 << " to the SDO entry datatype (see above)." << endl |
75 << " to the SDO entry datatype (see above). Use" << endl |
|
76 << " '-' to read from standard input." << endl |
72 << endl |
77 << endl |
73 << "Command-specific options:" << endl |
78 << "Command-specific options:" << endl |
74 << " --alias -a <alias>" << endl |
79 << " --alias -a <alias>" << endl |
75 << " --position -p <pos> Slave selection. See the help of" << endl |
80 << " --position -p <pos> Slave selection. See the help of" << endl |
76 << " the 'slaves' command." << endl |
81 << " the 'slaves' command." << endl |
83 |
88 |
84 /****************************************************************************/ |
89 /****************************************************************************/ |
85 |
90 |
86 void CommandDownload::execute(const StringVector &args) |
91 void CommandDownload::execute(const StringVector &args) |
87 { |
92 { |
88 stringstream strIndex, strSubIndex, err; |
93 stringstream strIndex, err; |
89 ec_ioctl_slave_sdo_download_t data; |
94 ec_ioctl_slave_sdo_download_t data; |
90 unsigned int number; |
95 unsigned int valueIndex; |
91 const DataType *dataType = NULL; |
96 const DataType *dataType = NULL; |
92 SlaveList slaves; |
97 SlaveList slaves; |
93 |
98 |
94 if (args.size() != 3) { |
99 if (args.size() != 2 && args.size() != 3) { |
95 err << "'" << getName() << "' takes 3 arguments!"; |
100 err << "'" << getName() << "' takes 2 or 3 arguments!"; |
96 throwInvalidUsageException(err); |
101 throwInvalidUsageException(err); |
97 } |
102 } |
|
103 data.complete_access = args.size() == 2; |
|
104 valueIndex = data.complete_access ? 1 : 2; |
98 |
105 |
99 strIndex << args[0]; |
106 strIndex << args[0]; |
100 strIndex |
107 strIndex |
101 >> resetiosflags(ios::basefield) // guess base from prefix |
108 >> resetiosflags(ios::basefield) // guess base from prefix |
102 >> data.sdo_index; |
109 >> data.sdo_index; |
103 if (strIndex.fail()) { |
110 if (strIndex.fail()) { |
104 err << "Invalid SDO index '" << args[0] << "'!"; |
111 err << "Invalid SDO index '" << args[0] << "'!"; |
105 throwInvalidUsageException(err); |
112 throwInvalidUsageException(err); |
106 } |
113 } |
107 |
114 |
108 strSubIndex << args[1]; |
115 if (data.complete_access) { |
109 strSubIndex |
116 data.sdo_entry_subindex = 0; |
110 >> resetiosflags(ios::basefield) // guess base from prefix |
117 } else { |
111 >> number; |
118 stringstream strSubIndex; |
112 if (strSubIndex.fail() || number > 0xff) { |
119 unsigned int number; |
113 err << "Invalid SDO subindex '" << args[1] << "'!"; |
120 |
114 throwInvalidUsageException(err); |
121 strSubIndex << args[1]; |
115 } |
122 strSubIndex |
116 data.sdo_entry_subindex = number; |
123 >> resetiosflags(ios::basefield) // guess base from prefix |
|
124 >> number; |
|
125 if (strSubIndex.fail() || number > 0xff) { |
|
126 err << "Invalid SDO subindex '" << args[1] << "'!"; |
|
127 throwInvalidUsageException(err); |
|
128 } |
|
129 data.sdo_entry_subindex = number; |
|
130 } |
117 |
131 |
118 MasterDevice m(getSingleMasterIndex()); |
132 MasterDevice m(getSingleMasterIndex()); |
119 m.open(MasterDevice::ReadWrite); |
133 m.open(MasterDevice::ReadWrite); |
120 slaves = selectedSlaves(m); |
134 slaves = selectedSlaves(m); |
121 if (slaves.size() != 1) { |
135 if (slaves.size() != 1) { |
145 << " Please specify --type."; |
159 << " Please specify --type."; |
146 throwCommandException(err); |
160 throwCommandException(err); |
147 } |
161 } |
148 } |
162 } |
149 |
163 |
150 if (dataType->byteSize) { |
164 if (args[valueIndex] == "-") { |
151 data.data_size = dataType->byteSize; |
165 ostringstream tmp; |
|
166 |
|
167 tmp << cin.rdbuf(); |
|
168 string const &contents = tmp.str(); |
|
169 |
|
170 if (!contents.size()) { |
|
171 err << "Invalid data size " << contents.size() << "! " |
|
172 << "Must be non-zero."; |
|
173 throwCommandException(err); |
|
174 } |
|
175 data.data_size = contents.size(); |
|
176 data.data = new uint8_t[data.data_size + 1]; |
|
177 |
|
178 try { |
|
179 data.data_size = interpretAsType( |
|
180 dataType, contents, data.data, data.data_size); |
|
181 } catch (SizeException &e) { |
|
182 delete [] data.data; |
|
183 throwCommandException(e.what()); |
|
184 } catch (ios::failure &e) { |
|
185 delete [] data.data; |
|
186 err << "Invalid value argument '" << args[2] |
|
187 << "' for type '" << dataType->name << "'!"; |
|
188 throwInvalidUsageException(err); |
|
189 } |
|
190 |
152 } else { |
191 } else { |
153 data.data_size = DefaultBufferSize; |
192 if (dataType->byteSize) { |
154 } |
193 data.data_size = dataType->byteSize; |
155 |
194 } else { |
156 data.data = new uint8_t[data.data_size + 1]; |
195 data.data_size = DefaultBufferSize; |
|
196 } |
|
197 |
|
198 data.data = new uint8_t[data.data_size + 1]; |
|
199 |
|
200 try { |
|
201 data.data_size = interpretAsType( |
|
202 dataType, args[valueIndex], data.data, data.data_size); |
|
203 } catch (SizeException &e) { |
|
204 delete [] data.data; |
|
205 throwCommandException(e.what()); |
|
206 } catch (ios::failure &e) { |
|
207 delete [] data.data; |
|
208 err << "Invalid value argument '" << args[2] |
|
209 << "' for type '" << dataType->name << "'!"; |
|
210 throwInvalidUsageException(err); |
|
211 } |
|
212 } |
157 |
213 |
158 try { |
214 try { |
159 data.data_size = interpretAsType( |
215 data.data_size = interpretAsType( |
160 dataType, args[2], data.data, data.data_size); |
216 dataType, args[valueIndex], data.data, data.data_size); |
161 } catch (SizeException &e) { |
217 } catch (SizeException &e) { |
162 delete [] data.data; |
218 delete [] data.data; |
163 throwCommandException(e.what()); |
219 throwCommandException(e.what()); |
164 } catch (ios::failure &e) { |
220 } catch (ios::failure &e) { |
165 delete [] data.data; |
221 delete [] data.data; |