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