diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-02-02 17:14:32 +0100 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-02-02 17:14:32 +0100 |
commit | 5dadc28ea784db1ba1f56c2ea8618d2db67af1c8 (patch) | |
tree | 808b2499b54563b3290f34d70d159b1024310873 /backend/genesys/device.cpp | |
parent | 5bb4cf12855ec0151de15d6c5a2354ff08766957 (diff) | |
parent | 3dade5db2a37543f19f0967901d8d80a52a1e459 (diff) |
Merge branch 'feature/upstream' into develop
Diffstat (limited to 'backend/genesys/device.cpp')
-rw-r--r-- | backend/genesys/device.cpp | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/backend/genesys/device.cpp b/backend/genesys/device.cpp new file mode 100644 index 0000000..ba035fd --- /dev/null +++ b/backend/genesys/device.cpp @@ -0,0 +1,272 @@ +/* sane - Scanner Access Now Easy. + + Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt> + + This file is part of the SANE package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + As a special exception, the authors of SANE give permission for + additional uses of the libraries contained in this release of SANE. + + The exception is that, if you link a SANE library with other files + to produce an executable, this does not by itself cause the + resulting executable to be covered by the GNU General Public + License. Your use of that executable is in no way restricted on + account of linking the SANE library code into it. + + This exception does not, however, invalidate any other reasons why + the executable file might be covered by the GNU General Public + License. + + If you submit changes to SANE to the maintainers to be included in + a subsequent release, you agree by submitting the changes that + those changes may be distributed with this exception intact. + + If you write modifications of your own for SANE, it is your choice + whether to permit this exception to apply to your modifications. + If you do not wish that, delete this exception notice. +*/ + +#define DEBUG_DECLARE_ONLY + +#include "device.h" +#include "command_set.h" +#include "low.h" +#include "utilities.h" + +namespace genesys { + +std::vector<unsigned> MethodResolutions::get_resolutions() const +{ + std::vector<unsigned> ret; + std::copy(resolutions_x.begin(), resolutions_x.end(), std::back_inserter(ret)); + std::copy(resolutions_y.begin(), resolutions_y.end(), std::back_inserter(ret)); + // sort in decreasing order + + std::sort(ret.begin(), ret.end(), std::greater<unsigned>()); + ret.erase(std::unique(ret.begin(), ret.end()), ret.end()); + return ret; +} + +const MethodResolutions& Genesys_Model::get_resolution_settings(ScanMethod method) const +{ + for (const auto& res_for_method : resolutions) { + for (auto res_method : res_for_method.methods) { + if (res_method == method) { + return res_for_method; + } + } + } + throw SaneException("Could not find resolution settings for method %d", + static_cast<unsigned>(method)); +} + +std::vector<unsigned> Genesys_Model::get_resolutions(ScanMethod method) const +{ + return get_resolution_settings(method).get_resolutions(); +} + +Genesys_Device::~Genesys_Device() +{ + clear(); +} + +void Genesys_Device::clear() +{ + read_buffer.clear(); + binarize_buffer.clear(); + local_buffer.clear(); + + calib_file.clear(); + + calibration_cache.clear(); + + white_average_data.clear(); + dark_average_data.clear(); +} + +ImagePipelineNodeBytesSource& Genesys_Device::get_pipeline_source() +{ + return static_cast<ImagePipelineNodeBytesSource&>(pipeline.front()); +} + +bool Genesys_Device::is_head_pos_known(ScanHeadId scan_head) const +{ + switch (scan_head) { + case ScanHeadId::PRIMARY: return is_head_pos_primary_known_; + case ScanHeadId::SECONDARY: return is_head_pos_secondary_known_; + case ScanHeadId::ALL: return is_head_pos_primary_known_ && is_head_pos_secondary_known_; + default: + throw SaneException("Unknown scan head ID"); + } +} +unsigned Genesys_Device::head_pos(ScanHeadId scan_head) const +{ + switch (scan_head) { + case ScanHeadId::PRIMARY: return head_pos_primary_; + case ScanHeadId::SECONDARY: return head_pos_secondary_; + default: + throw SaneException("Unknown scan head ID"); + } +} + +void Genesys_Device::set_head_pos_unknown() +{ + is_head_pos_primary_known_ = false; + is_head_pos_secondary_known_ = false; +} + +void Genesys_Device::set_head_pos_zero(ScanHeadId scan_head) +{ + if ((scan_head & ScanHeadId::PRIMARY) != ScanHeadId::NONE) { + head_pos_primary_ = 0; + is_head_pos_primary_known_ = true; + } + if ((scan_head & ScanHeadId::SECONDARY) != ScanHeadId::NONE) { + head_pos_secondary_ = 0; + is_head_pos_secondary_known_ = true; + } +} + +void Genesys_Device::advance_head_pos_by_session(ScanHeadId scan_head) +{ + int motor_steps = session.params.starty + + (session.params.lines * motor.base_ydpi) / session.params.yres; + auto direction = has_flag(session.params.flags, ScanFlag::REVERSE) ? Direction::BACKWARD + : Direction::FORWARD; + advance_head_pos_by_steps(scan_head, direction, motor_steps); +} + +static void advance_pos(unsigned& pos, Direction direction, unsigned offset) +{ + if (direction == Direction::FORWARD) { + pos += offset; + } else { + if (pos < offset) { + throw SaneException("Trying to advance head behind the home sensor"); + } + pos -= offset; + } +} + +void Genesys_Device::advance_head_pos_by_steps(ScanHeadId scan_head, Direction direction, + unsigned steps) +{ + if ((scan_head & ScanHeadId::PRIMARY) != ScanHeadId::NONE) { + if (!is_head_pos_primary_known_) { + throw SaneException("Trying to advance head while scanhead position is not known"); + } + advance_pos(head_pos_primary_, direction, steps); + } + if ((scan_head & ScanHeadId::SECONDARY) != ScanHeadId::NONE) { + if (!is_head_pos_secondary_known_) { + throw SaneException("Trying to advance head while scanhead position is not known"); + } + advance_pos(head_pos_secondary_, direction, steps); + } +} + +void print_scan_position(std::ostream& out, const Genesys_Device& dev, ScanHeadId scan_head) +{ + if (dev.is_head_pos_known(scan_head)) { + out << dev.head_pos(scan_head); + } else { + out <<"(unknown)"; + } +} + +std::ostream& operator<<(std::ostream& out, const Genesys_Device& dev) +{ + StreamStateSaver state_saver{out}; + + out << "Genesys_Device{\n" + << std::hex + << " vendorId: 0x" << dev.vendorId << '\n' + << " productId: 0x" << dev.productId << '\n' + << std::dec + << " usb_mode: " << dev.usb_mode << '\n' + << " file_name: " << dev.file_name << '\n' + << " calib_file: " << dev.calib_file << '\n' + << " force_calibration: " << dev.force_calibration << '\n' + << " ignore_offsets: " << dev.ignore_offsets << '\n' + << " model: (not printed)\n" + << " reg: " << format_indent_braced_list(4, dev.reg) << '\n' + << " calib_reg: " << format_indent_braced_list(4, dev.calib_reg) << '\n' + << " settings: " << format_indent_braced_list(4, dev.settings) << '\n' + << " frontend: " << format_indent_braced_list(4, dev.frontend) << '\n' + << " frontend_initial: " << format_indent_braced_list(4, dev.frontend_initial) << '\n' + << " frontend_is_init: " << dev.frontend_is_init << '\n' + << " gpo.regs: " << format_indent_braced_list(4, dev.gpo.regs) << '\n' + << " motor: " << format_indent_braced_list(4, dev.motor) << '\n' + << " control[0..6]: " << std::hex + << static_cast<unsigned>(dev.control[0]) << ' ' + << static_cast<unsigned>(dev.control[1]) << ' ' + << static_cast<unsigned>(dev.control[2]) << ' ' + << static_cast<unsigned>(dev.control[3]) << ' ' + << static_cast<unsigned>(dev.control[4]) << ' ' + << static_cast<unsigned>(dev.control[5]) << '\n' << std::dec + << " average_size: " << dev.average_size << '\n' + << " calib_pixels: " << dev.calib_pixels << '\n' + << " calib_lines: " << dev.calib_lines << '\n' + << " calib_channels: " << dev.calib_channels << '\n' + << " calib_resolution: " << dev.calib_resolution << '\n' + << " calib_total_bytes_to_read: " << dev.calib_total_bytes_to_read << '\n' + << " calib_session: " << format_indent_braced_list(4, dev.calib_session) << '\n' + << " calib_pixels_offset: " << dev.calib_pixels_offset << '\n' + << " gamma_override_tables[0].size(): " << dev.gamma_override_tables[0].size() << '\n' + << " gamma_override_tables[1].size(): " << dev.gamma_override_tables[1].size() << '\n' + << " gamma_override_tables[2].size(): " << dev.gamma_override_tables[2].size() << '\n' + << " white_average_data.size(): " << dev.white_average_data.size() << '\n' + << " dark_average_data.size(): " << dev.dark_average_data.size() << '\n' + << " already_initialized: " << dev.already_initialized << '\n' + << " scanhead_position[PRIMARY]: "; + print_scan_position(out, dev, ScanHeadId::PRIMARY); + out << '\n' + << " scanhead_position[SECONDARY]: "; + print_scan_position(out, dev, ScanHeadId::SECONDARY); + out << '\n' + << " read_active: " << dev.read_active << '\n' + << " parking: " << dev.parking << '\n' + << " document: " << dev.document << '\n' + << " read_buffer.size(): " << dev.read_buffer.size() << '\n' + << " binarize_buffer.size(): " << dev.binarize_buffer.size() << '\n' + << " local_buffer.size(): " << dev.local_buffer.size() << '\n' + << " oe_buffer.size(): " << dev.oe_buffer.size() << '\n' + << " total_bytes_read: " << dev.total_bytes_read << '\n' + << " total_bytes_to_read: " << dev.total_bytes_to_read << '\n' + << " session: " << format_indent_braced_list(4, dev.session) << '\n' + << " lineart_lut: (not printed)\n" + << " calibration_cache: (not printed)\n" + << " line_count: " << dev.line_count << '\n' + << " segment_order: " + << format_indent_braced_list(4, format_vector_unsigned(4, dev.segment_order)) << '\n' + << " buffer_image: " << dev.buffer_image << '\n' + << " img_buffer.size(): " << dev.img_buffer.size() << '\n' + << '}'; + return out; +} + +void apply_reg_settings_to_device(Genesys_Device& dev, const GenesysRegisterSettingSet& regs) +{ + for (const auto& reg : regs) { + uint8_t val = dev.interface->read_register(reg.address); + val = (val & ~reg.mask) | (reg.value & reg.mask); + dev.interface->write_register(reg.address, val); + } +} + +} // namespace genesys |