1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
4
5 This file is part of the SANE package.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21 #define DEBUG_DECLARE_ONLY
22
23 #include "scanner_interface_usb.h"
24 #include "low.h"
25
26 namespace genesys {
27
28 ScannerInterfaceUsb::~ScannerInterfaceUsb() = default;
29
ScannerInterfaceUsb(Genesys_Device* dev)30 ScannerInterfaceUsb::ScannerInterfaceUsb(Genesys_Device* dev) : dev_{dev} {}
31
is_mock() const32 bool ScannerInterfaceUsb::is_mock() const
33 {
34 return false;
35 }
36
read_register(std::uint16_t address)37 std::uint8_t ScannerInterfaceUsb::read_register(std::uint16_t address)
38 {
39 DBG_HELPER(dbg);
40
41 std::uint8_t value = 0;
42
43 if (dev_->model->asic_type == AsicType::GL847 ||
44 dev_->model->asic_type == AsicType::GL845 ||
45 dev_->model->asic_type == AsicType::GL846 ||
46 dev_->model->asic_type == AsicType::GL124)
47 {
48 std::uint8_t value2x8[2];
49 std::uint16_t address16 = 0x22 + (address << 8);
50
51 std::uint16_t usb_value = VALUE_GET_REGISTER;
52 if (address > 0xff) {
53 usb_value |= 0x100;
54 }
55
56 usb_dev_.control_msg(REQUEST_TYPE_IN, REQUEST_BUFFER, usb_value, address16, 2, value2x8);
57
58 // check usb link status
59 if (value2x8[1] != 0x55) {
60 throw SaneException(SANE_STATUS_IO_ERROR, "invalid read, scanner unplugged?");
61 }
62
63 DBG(DBG_io, "%s (0x%02x, 0x%02x) completed\n", __func__, address, value2x8[0]);
64
65 value = value2x8[0];
66
67 } else {
68
69 if (address > 0xff) {
70 throw SaneException("Invalid register address 0x%04x", address);
71 }
72
73 std::uint8_t address8 = address & 0xff;
74
75 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX,
76 1, &address8);
77 usb_dev_.control_msg(REQUEST_TYPE_IN, REQUEST_REGISTER, VALUE_READ_REGISTER, INDEX,
78 1, &value);
79 }
80 return value;
81 }
82
write_register(std::uint16_t address, std::uint8_t value)83 void ScannerInterfaceUsb::write_register(std::uint16_t address, std::uint8_t value)
84 {
85 DBG_HELPER_ARGS(dbg, "address: 0x%04x, value: 0x%02x", static_cast<unsigned>(address),
86 static_cast<unsigned>(value));
87
88 if (dev_->model->asic_type == AsicType::GL847 ||
89 dev_->model->asic_type == AsicType::GL845 ||
90 dev_->model->asic_type == AsicType::GL846 ||
91 dev_->model->asic_type == AsicType::GL124)
92 {
93 std::uint8_t buffer[2];
94
95 buffer[0] = address & 0xff;
96 buffer[1] = value;
97
98 std::uint16_t usb_value = VALUE_SET_REGISTER;
99 if (address > 0xff) {
100 usb_value |= 0x100;
101 }
102
103 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_BUFFER, usb_value, INDEX,
104 2, buffer);
105
106 } else {
107 if (address > 0xff) {
108 throw SaneException("Invalid register address 0x%04x", address);
109 }
110
111 std::uint8_t address8 = address & 0xff;
112
113 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX,
114 1, &address8);
115
116 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_WRITE_REGISTER, INDEX,
117 1, &value);
118
119 }
120 DBG(DBG_io, "%s (0x%02x, 0x%02x) completed\n", __func__, address, value);
121 }
122
write_registers(const Genesys_Register_Set& regs)123 void ScannerInterfaceUsb::write_registers(const Genesys_Register_Set& regs)
124 {
125 DBG_HELPER(dbg);
126 if (dev_->model->asic_type == AsicType::GL646 ||
127 dev_->model->asic_type == AsicType::GL841)
128 {
129 std::uint8_t outdata[8];
130 std::vector<std::uint8_t> buffer;
131 buffer.reserve(regs.size() * 2);
132
133 /* copy registers and values in data buffer */
134 for (const auto& r : regs) {
135 buffer.push_back(r.address);
136 buffer.push_back(r.value);
137 }
138
139 DBG(DBG_io, "%s (elems= %zu, size = %zu)\n", __func__, regs.size(), buffer.size());
140
141 if (dev_->model->asic_type == AsicType::GL646) {
142 outdata[0] = BULK_OUT;
143 outdata[1] = BULK_REGISTER;
144 outdata[2] = 0x00;
145 outdata[3] = 0x00;
146 outdata[4] = (buffer.size() & 0xff);
147 outdata[5] = ((buffer.size() >> 8) & 0xff);
148 outdata[6] = ((buffer.size() >> 16) & 0xff);
149 outdata[7] = ((buffer.size() >> 24) & 0xff);
150
151 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, INDEX,
152 sizeof(outdata), outdata);
153
154 size_t write_size = buffer.size();
155
156 usb_dev_.bulk_write(buffer.data(), &write_size);
157 } else {
158 for (std::size_t i = 0; i < regs.size();) {
159 std::size_t c = regs.size() - i;
160 if (c > 32) /*32 is max on GL841. checked that.*/
161 c = 32;
162
163 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_SET_REGISTER,
164 INDEX, c * 2, buffer.data() + i * 2);
165
166 i += c;
167 }
168 }
169 } else {
170 for (const auto& r : regs) {
171 write_register(r.address, r.value);
172 }
173 }
174
175 DBG(DBG_io, "%s: wrote %zu registers\n", __func__, regs.size());
176 }
177
write_0x8c(std::uint8_t index, std::uint8_t value)178 void ScannerInterfaceUsb::write_0x8c(std::uint8_t index, std::uint8_t value)
179 {
180 DBG_HELPER_ARGS(dbg, "0x%02x,0x%02x", index, value);
181 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_BUF_ENDACCESS, index, 1, &value);
182 }
183
bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, size_t size)184 static void bulk_read_data_send_header(UsbDevice& usb_dev, AsicType asic_type, size_t size)
185 {
186 DBG_HELPER(dbg);
187
188 std::uint8_t outdata[8];
189 if (asic_type == AsicType::GL124 ||
190 asic_type == AsicType::GL845 ||
191 asic_type == AsicType::GL846 ||
192 asic_type == AsicType::GL847)
193 {
194 // hard coded 0x10000000 address
195 outdata[0] = 0;
196 outdata[1] = 0;
197 outdata[2] = 0;
198 outdata[3] = 0x10;
199 } else if (asic_type == AsicType::GL841 ||
200 asic_type == AsicType::GL842 ||
201 asic_type == AsicType::GL843)
202 {
203 outdata[0] = BULK_IN;
204 outdata[1] = BULK_RAM;
205 outdata[2] = 0x82; //
206 outdata[3] = 0x00;
207 } else {
208 outdata[0] = BULK_IN;
209 outdata[1] = BULK_RAM;
210 outdata[2] = 0x00;
211 outdata[3] = 0x00;
212 }
213
214 /* data size to transfer */
215 outdata[4] = (size & 0xff);
216 outdata[5] = ((size >> 8) & 0xff);
217 outdata[6] = ((size >> 16) & 0xff);
218 outdata[7] = ((size >> 24) & 0xff);
219
220 usb_dev.control_msg(REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, 0x00,
221 sizeof(outdata), outdata);
222 }
223
bulk_read_data(std::uint8_t addr, std::uint8_t* data, std::size_t size)224 void ScannerInterfaceUsb::bulk_read_data(std::uint8_t addr, std::uint8_t* data, std::size_t size)
225 {
226 // currently supported: GL646, GL841, GL843, GL845, GL846, GL847, GL124
227 DBG_HELPER(dbg);
228
229 unsigned is_addr_used = 1;
230 unsigned has_header_before_each_chunk = 0;
231 if (dev_->model->asic_type == AsicType::GL124 ||
232 dev_->model->asic_type == AsicType::GL845 ||
233 dev_->model->asic_type == AsicType::GL846 ||
234 dev_->model->asic_type == AsicType::GL847)
235 {
236 is_addr_used = 0;
237 has_header_before_each_chunk = 1;
238 }
239
240 if (is_addr_used) {
241 DBG(DBG_io, "%s: requesting %zu bytes from 0x%02x addr\n", __func__, size, addr);
242 } else {
243 DBG(DBG_io, "%s: requesting %zu bytes\n", __func__, size);
244 }
245
246 if (size == 0)
247 return;
248
249 if (is_addr_used) {
250 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, 0x00,
251 1, &addr);
252 }
253
254 std::size_t target_size = size;
255
256 std::size_t max_in_size = sanei_genesys_get_bulk_max_size(dev_->model->asic_type);
257
258 if (!has_header_before_each_chunk) {
259 bulk_read_data_send_header(usb_dev_, dev_->model->asic_type, size);
260 }
261
262 // loop until computed data size is read
263 while (target_size > 0) {
264 std::size_t block_size = std::min(target_size, max_in_size);
265
266 if (has_header_before_each_chunk) {
267 bulk_read_data_send_header(usb_dev_, dev_->model->asic_type, block_size);
268 }
269
270 DBG(DBG_io2, "%s: trying to read %zu bytes of data\n", __func__, block_size);
271
272 usb_dev_.bulk_read(data, &block_size);
273
274 DBG(DBG_io2, "%s: read %zu bytes, %zu remaining\n", __func__, block_size, target_size - block_size);
275
276 target_size -= block_size;
277 data += block_size;
278 }
279 }
280
bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t len)281 void ScannerInterfaceUsb::bulk_write_data(std::uint8_t addr, std::uint8_t* data, std::size_t len)
282 {
283 DBG_HELPER_ARGS(dbg, "writing %zu bytes", len);
284
285 // supported: GL646, GL841, GL843
286 std::size_t size;
287 std::uint8_t outdata[8];
288
289 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_REGISTER, VALUE_SET_REGISTER, INDEX,
290 1, &addr);
291
292 std::size_t max_out_size = sanei_genesys_get_bulk_max_size(dev_->model->asic_type);
293
294 while (len) {
295 if (len > max_out_size)
296 size = max_out_size;
297 else
298 size = len;
299
300 if (dev_->model->asic_type == AsicType::GL841) {
301 outdata[0] = BULK_OUT;
302 outdata[1] = BULK_RAM;
303 // both 0x82 and 0x00 works on GL841.
304 outdata[2] = 0x82;
305 outdata[3] = 0x00;
306 } else {
307 outdata[0] = BULK_OUT;
308 outdata[1] = BULK_RAM;
309 // 8600F uses 0x82, but 0x00 works too. 8400F uses 0x02 for certain transactions.
310 outdata[2] = 0x00;
311 outdata[3] = 0x00;
312 }
313
314 outdata[4] = (size & 0xff);
315 outdata[5] = ((size >> 8) & 0xff);
316 outdata[6] = ((size >> 16) & 0xff);
317 outdata[7] = ((size >> 24) & 0xff);
318
319 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, 0x00,
320 sizeof(outdata), outdata);
321
322 usb_dev_.bulk_write(data, &size);
323
324 DBG(DBG_io2, "%s: wrote %zu bytes, %zu remaining\n", __func__, size, len - size);
325
326 len -= size;
327 data += size;
328 }
329 }
330
write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data, std::size_t size)331 void ScannerInterfaceUsb::write_buffer(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
332 std::size_t size)
333 {
334 DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
335 if (dev_->model->asic_type != AsicType::GL646 &&
336 dev_->model->asic_type != AsicType::GL841 &&
337 dev_->model->asic_type != AsicType::GL842 &&
338 dev_->model->asic_type != AsicType::GL843)
339 {
340 throw SaneException("Unsupported transfer mode");
341 }
342
343 if (dev_->model->asic_type == AsicType::GL843) {
344 write_register(0x2b, ((addr >> 4) & 0xff));
345 write_register(0x2a, ((addr >> 12) & 0xff));
346 write_register(0x29, ((addr >> 20) & 0xff));
347 } else {
348 write_register(0x2b, ((addr >> 4) & 0xff));
349 write_register(0x2a, ((addr >> 12) & 0xff));
350 }
351 bulk_write_data(type, data, size);
352 }
353
write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data, std::size_t size)354 void ScannerInterfaceUsb::write_gamma(std::uint8_t type, std::uint32_t addr, std::uint8_t* data,
355 std::size_t size)
356 {
357 DBG_HELPER_ARGS(dbg, "type: 0x%02x, addr: 0x%08x, size: 0x%08zx", type, addr, size);
358 if (dev_->model->asic_type != AsicType::GL841 &&
359 dev_->model->asic_type != AsicType::GL842 &&
360 dev_->model->asic_type != AsicType::GL843)
361 {
362 throw SaneException("Unsupported transfer mode");
363 }
364
365 write_register(0x5b, ((addr >> 12) & 0xff));
366 write_register(0x5c, ((addr >> 4) & 0xff));
367 bulk_write_data(type, data, size);
368
369 if (dev_->model->asic_type == AsicType::GL842 ||
370 dev_->model->asic_type == AsicType::GL843)
371 {
372 // it looks like we need to reset the address so that subsequent buffer operations work.
373 // Most likely the MTRTBL register is to blame.
374 write_register(0x5b, 0);
375 write_register(0x5c, 0);
376 }
377 }
378
write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)379 void ScannerInterfaceUsb::write_ahb(std::uint32_t addr, std::uint32_t size, std::uint8_t* data)
380 {
381 DBG_HELPER_ARGS(dbg, "address: 0x%08x, size: %d", static_cast<unsigned>(addr),
382 static_cast<unsigned>(size));
383
384 if (dev_->model->asic_type != AsicType::GL845 &&
385 dev_->model->asic_type != AsicType::GL846 &&
386 dev_->model->asic_type != AsicType::GL847 &&
387 dev_->model->asic_type != AsicType::GL124)
388 {
389 throw SaneException("Unsupported transfer type");
390 }
391 std::uint8_t outdata[8];
392 outdata[0] = addr & 0xff;
393 outdata[1] = ((addr >> 8) & 0xff);
394 outdata[2] = ((addr >> 16) & 0xff);
395 outdata[3] = ((addr >> 24) & 0xff);
396 outdata[4] = (size & 0xff);
397 outdata[5] = ((size >> 8) & 0xff);
398 outdata[6] = ((size >> 16) & 0xff);
399 outdata[7] = ((size >> 24) & 0xff);
400
401 // write addr and size for AHB
402 usb_dev_.control_msg(REQUEST_TYPE_OUT, REQUEST_BUFFER, VALUE_BUFFER, 0x01, 8, outdata);
403
404 std::size_t max_out_size = sanei_genesys_get_bulk_max_size(dev_->model->asic_type);
405
406 // write actual data
407 std::size_t written = 0;
408 do {
409 std::size_t block_size = std::min(size - written, max_out_size);
410
411 usb_dev_.bulk_write(data + written, &block_size);
412
413 written += block_size;
414 } while (written < size);
415 }
416
read_fe_register(std::uint8_t address)417 std::uint16_t ScannerInterfaceUsb::read_fe_register(std::uint8_t address)
418 {
419 DBG_HELPER(dbg);
420 Genesys_Register_Set reg;
421
422 reg.init_reg(0x50, address);
423
424 // set up read address
425 write_registers(reg);
426
427 // read data
428 std::uint16_t value = read_register(0x46) << 8;
429 value |= read_register(0x47);
430
431 DBG(DBG_io, "%s (0x%02x, 0x%04x)\n", __func__, address, value);
432 return value;
433 }
434
write_fe_register(std::uint8_t address, std::uint16_t value)435 void ScannerInterfaceUsb::write_fe_register(std::uint8_t address, std::uint16_t value)
436 {
437 DBG_HELPER_ARGS(dbg, "0x%02x, 0x%04x", address, value);
438 Genesys_Register_Set reg(Genesys_Register_Set::SEQUENTIAL);
439
440 reg.init_reg(0x51, address);
441 if (dev_->model->asic_type == AsicType::GL124) {
442 reg.init_reg(0x5d, (value / 256) & 0xff);
443 reg.init_reg(0x5e, value & 0xff);
444 } else {
445 reg.init_reg(0x3a, (value / 256) & 0xff);
446 reg.init_reg(0x3b, value & 0xff);
447 }
448
449 write_registers(reg);
450 }
451
get_usb_device()452 IUsbDevice& ScannerInterfaceUsb::get_usb_device()
453 {
454 return usb_dev_;
455 }
456
sleep_us(unsigned microseconds)457 void ScannerInterfaceUsb::sleep_us(unsigned microseconds)
458 {
459 if (sanei_usb_is_replay_mode_enabled()) {
460 return;
461 }
462 usleep(microseconds);
463 }
464
record_progress_message(const char* msg)465 void ScannerInterfaceUsb::record_progress_message(const char* msg)
466 {
467 sanei_usb_testing_record_message(msg);
468 }
469
record_slope_table(unsigned table_nr, const std::vector<std::uint16_t>& steps)470 void ScannerInterfaceUsb::record_slope_table(unsigned table_nr,
471 const std::vector<std::uint16_t>& steps)
472 {
473 (void) table_nr;
474 (void) steps;
475 }
476
record_key_value(const std::string& key, const std::string& value)477 void ScannerInterfaceUsb::record_key_value(const std::string& key, const std::string& value)
478 {
479 (void) key;
480 (void) value;
481 }
482
test_checkpoint(const std::string& name)483 void ScannerInterfaceUsb::test_checkpoint(const std::string& name)
484 {
485 (void) name;
486 }
487
488 } // namespace genesys
489