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