52 |
53 |
53 /****************************************************************************/ |
54 /****************************************************************************/ |
54 |
55 |
55 void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args) |
56 void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args) |
56 { |
57 { |
57 SlaveList slaves; |
|
58 stringstream err; |
58 stringstream err; |
59 ec_ioctl_slave_sii_t data; |
59 ec_ioctl_slave_sii_t data; |
60 ifstream file; |
60 ifstream file; |
61 unsigned int byte_size; |
61 SlaveList slaves; |
62 const uint16_t *categoryHeader; |
|
63 uint16_t categoryType, categorySize; |
|
64 uint8_t crc; |
|
65 |
62 |
66 if (args.size() != 1) { |
63 if (args.size() != 1) { |
67 err << "'" << getName() << "' takes exactly one argument!"; |
64 err << "'" << getName() << "' takes exactly one argument!"; |
68 throwInvalidUsageException(err); |
65 throwInvalidUsageException(err); |
69 } |
66 } |
70 |
67 |
71 file.open(args[0].c_str(), ifstream::in | ifstream::binary); |
68 if (args[0] == "-") { |
72 if (file.fail()) { |
69 loadSiiData(&data, cin); |
73 err << "Failed to open '" << args[0] << "'!"; |
70 } else { |
74 throwCommandException(err); |
71 file.open(args[0].c_str(), ifstream::in | ifstream::binary); |
|
72 if (file.fail()) { |
|
73 err << "Failed to open '" << args[0] << "'!"; |
|
74 throwCommandException(err); |
|
75 } |
|
76 loadSiiData(&data, file); |
|
77 file.close(); |
75 } |
78 } |
76 |
79 |
77 // get length of file |
|
78 file.seekg(0, ios::end); |
|
79 byte_size = file.tellg(); |
|
80 file.seekg(0, ios::beg); |
|
81 |
|
82 if (!byte_size || byte_size % 2) { |
|
83 err << "Invalid file size! Must be non-zero and even."; |
|
84 throwCommandException(err); |
|
85 } |
|
86 |
|
87 data.nwords = byte_size / 2; |
|
88 if (data.nwords < 0x0041 && !force) { |
|
89 err << "SII data too short (" << data.nwords << " words)! Mimimum is" |
|
90 " 40 fixed words + 1 delimiter. Use --force to write anyway."; |
|
91 throwCommandException(err); |
|
92 } |
|
93 |
|
94 // allocate buffer and read file into buffer |
|
95 data.words = new uint16_t[data.nwords]; |
|
96 file.read((char *) data.words, byte_size); |
|
97 file.close(); |
|
98 |
|
99 if (!force) { |
80 if (!force) { |
100 // calculate checksum over words 0 to 6 |
81 try { |
101 crc = calcSiiCrc((const uint8_t *) data.words, 14); |
82 checkSiiData(&data); |
102 if (crc != ((const uint8_t *) data.words)[14]) { |
83 } catch (CommandException &e) { |
103 err << "CRC incorrect. Must be 0x" |
84 delete [] data.words; |
104 << hex << setfill('0') << setw(2) << (unsigned int) crc |
85 throw e; |
105 << ". Use --force to write anyway."; |
|
106 throwCommandException(err); |
|
107 } |
|
108 |
|
109 // cycle through categories to detect corruption |
|
110 categoryHeader = data.words + 0x0040U; |
|
111 categoryType = le16tocpu(*categoryHeader); |
|
112 while (categoryType != 0xffff) { |
|
113 if (categoryHeader + 1 > data.words + data.nwords) { |
|
114 err << "SII data seem to be corrupted! " |
|
115 << "Use --force to write anyway."; |
|
116 throwCommandException(err); |
|
117 } |
|
118 categorySize = le16tocpu(*(categoryHeader + 1)); |
|
119 if (categoryHeader + 2 + categorySize + 1 |
|
120 > data.words + data.nwords) { |
|
121 err << "SII data seem to be corrupted! " |
|
122 "Use --force to write anyway."; |
|
123 throwCommandException(err); |
|
124 } |
|
125 categoryHeader += 2 + categorySize; |
|
126 categoryType = le16tocpu(*categoryHeader); |
|
127 } |
86 } |
128 } |
87 } |
129 |
88 |
130 m.open(MasterDevice::ReadWrite); |
89 try { |
|
90 m.open(MasterDevice::ReadWrite); |
|
91 } catch (MasterDeviceException &e) { |
|
92 delete [] data.words; |
|
93 throw e; |
|
94 } |
|
95 |
131 slaves = selectedSlaves(m); |
96 slaves = selectedSlaves(m); |
132 if (slaves.size() != 1) { |
97 if (slaves.size() != 1) { |
|
98 delete [] data.words; |
133 throwSingleSlaveRequired(slaves.size()); |
99 throwSingleSlaveRequired(slaves.size()); |
134 } |
100 } |
135 data.slave_position = slaves.front().position; |
101 data.slave_position = slaves.front().position; |
136 |
102 |
137 // send data to master |
103 // send data to master |
138 data.offset = 0; |
104 data.offset = 0; |
139 m.writeSii(&data); |
105 try { |
|
106 m.writeSii(&data); |
|
107 } catch (MasterDeviceException &e) { |
|
108 delete [] data.words; |
|
109 throw e; |
|
110 } |
|
111 |
|
112 if (getVerbosity() == Verbose) { |
|
113 cerr << "SII writing finished." << endl; |
|
114 } |
|
115 |
|
116 delete [] data.words; |
140 } |
117 } |
141 |
118 |
142 /*****************************************************************************/ |
119 /*****************************************************************************/ |
|
120 |
|
121 void CommandSiiWrite::loadSiiData( |
|
122 ec_ioctl_slave_sii_t *data, |
|
123 const istream &in |
|
124 ) |
|
125 { |
|
126 stringstream err; |
|
127 ostringstream tmp; |
|
128 |
|
129 tmp << in.rdbuf(); |
|
130 string const &contents = tmp.str(); |
|
131 |
|
132 if (getVerbosity() == Verbose) { |
|
133 cerr << "Read " << contents.size() << " bytes of SII data." << endl; |
|
134 } |
|
135 |
|
136 if (!contents.size() || contents.size() % 2) { |
|
137 err << "Invalid data size " << contents.size() << "! " |
|
138 << "Must be non-zero and even."; |
|
139 throwCommandException(err); |
|
140 } |
|
141 data->nwords = contents.size() / 2; |
|
142 |
|
143 // allocate buffer and read file into buffer |
|
144 data->words = new uint16_t[data->nwords]; |
|
145 contents.copy((char *) data->words, contents.size()); |
|
146 } |
|
147 |
|
148 /*****************************************************************************/ |
|
149 |
|
150 void CommandSiiWrite::checkSiiData( |
|
151 const ec_ioctl_slave_sii_t *data |
|
152 ) |
|
153 { |
|
154 stringstream err; |
|
155 const uint16_t *categoryHeader; |
|
156 uint16_t categoryType, categorySize; |
|
157 uint8_t crc; |
|
158 |
|
159 if (data->nwords < 0x0041) { |
|
160 err << "SII data too short (" << data->nwords << " words)! Mimimum is" |
|
161 " 40 fixed words + 1 delimiter. Use --force to write anyway."; |
|
162 throwCommandException(err); |
|
163 } |
|
164 |
|
165 // calculate checksum over words 0 to 6 |
|
166 crc = calcSiiCrc((const uint8_t *) data->words, 14); |
|
167 if (crc != ((const uint8_t *) data->words)[14]) { |
|
168 err << "CRC incorrect. Must be 0x" |
|
169 << hex << setfill('0') << setw(2) << (unsigned int) crc |
|
170 << ". Use --force to write anyway."; |
|
171 throwCommandException(err); |
|
172 } |
|
173 |
|
174 // cycle through categories to detect corruption |
|
175 categoryHeader = data->words + 0x0040U; |
|
176 categoryType = le16tocpu(*categoryHeader); |
|
177 while (categoryType != 0xffff) { |
|
178 if (categoryHeader + 1 > data->words + data->nwords) { |
|
179 err << "SII data seem to be corrupted! " |
|
180 << "Use --force to write anyway."; |
|
181 throwCommandException(err); |
|
182 } |
|
183 categorySize = le16tocpu(*(categoryHeader + 1)); |
|
184 if (categoryHeader + 2 + categorySize + 1 |
|
185 > data->words + data->nwords) { |
|
186 err << "SII data seem to be corrupted! " |
|
187 "Use --force to write anyway."; |
|
188 throwCommandException(err); |
|
189 } |
|
190 categoryHeader += 2 + categorySize; |
|
191 categoryType = le16tocpu(*categoryHeader); |
|
192 } |
|
193 } |
|
194 |
|
195 /*****************************************************************************/ |