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 "command_set_common.h"
24#include "low.h"
25#include "value_filter.h"
26
27namespace genesys {
28
29CommandSetCommon::~CommandSetCommon() = default;
30
31bool CommandSetCommon::is_head_home(Genesys_Device& dev, ScanHeadId scan_head) const
32{
33    struct HeadSettings {
34        ModelId model_id;
35        ScanHeadId scan_head;
36        GenesysRegisterSettingSet regs;
37    };
38
39    HeadSettings settings[] = {
40        {   ModelId::CANON_8600F,
41            ScanHeadId::PRIMARY, {
42                { 0x6c, 0x20, 0x60 },
43                { 0xa6, 0x00, 0x01 },
44            }
45        },
46        {   ModelId::CANON_8600F,
47            ScanHeadId::SECONDARY, {
48                { 0x6c, 0x00, 0x60 },
49                { 0xa6, 0x01, 0x01 },
50            }
51        },
52    };
53
54    for (const auto& setting : settings) {
55        if (setting.model_id == dev.model->model_id &&
56            setting.scan_head == scan_head)
57        {
58            auto reg_backup = apply_reg_settings_to_device_with_backup(dev, setting.regs);
59            auto status = scanner_read_status(dev);
60            apply_reg_settings_to_device(dev, reg_backup);
61            return status.is_at_home;
62        }
63    }
64
65    auto status = scanner_read_status(dev);
66    return status.is_at_home;
67}
68
69void CommandSetCommon::set_xpa_lamp_power(Genesys_Device& dev, bool set) const
70
71{
72    DBG_HELPER(dbg);
73
74    struct LampSettings {
75        ModelId model_id;
76        ScanMethod scan_method;
77        GenesysRegisterSettingSet regs_on;
78        GenesysRegisterSettingSet regs_off;
79    };
80
81    // FIXME: BUG: we're not clearing the registers to the previous state when returning back when
82    // turning off the lamp
83    LampSettings settings[] = {
84        {   ModelId::CANON_4400F, ScanMethod::TRANSPARENCY, {}, {} },
85        {   ModelId::CANON_5600F, ScanMethod::TRANSPARENCY, {}, {} },
86        {   ModelId::CANON_8400F, ScanMethod::TRANSPARENCY, {
87                { 0xa6, 0x34, 0xf4 },
88            }, {
89                { 0xa6, 0x40, 0x70 },
90            }
91        },
92        {   ModelId::CANON_8400F, ScanMethod::TRANSPARENCY_INFRARED, {
93                { 0x6c, 0x40, 0x40 },
94                { 0xa6, 0x01, 0xff },
95            }, {
96                { 0x6c, 0x00, 0x40 },
97                { 0xa6, 0x00, 0xff },
98            }
99        },
100        {   ModelId::CANON_8600F, ScanMethod::TRANSPARENCY, {
101                { 0xa6, 0x34, 0xf4 },
102                { 0xa7, 0xe0, 0xe0 },
103            }, {
104                { 0xa6, 0x40, 0x70 },
105            }
106        },
107        {   ModelId::CANON_8600F, ScanMethod::TRANSPARENCY_INFRARED, {
108                { 0xa6, 0x00, 0xc0 },
109                { 0xa7, 0xe0, 0xe0 },
110                { 0x6c, 0x80, 0x80 },
111            }, {
112                { 0xa6, 0x00, 0xc0 },
113                { 0x6c, 0x00, 0x80 },
114            }
115        },
116        {   ModelId::PLUSTEK_OPTICFILM_7200, ScanMethod::TRANSPARENCY, {}, {} },
117        {   ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY, {}, {} },
118        {   ModelId::PLUSTEK_OPTICFILM_7200I, ScanMethod::TRANSPARENCY_INFRARED, {
119                { 0xa8, 0x07, 0x07 },
120            }, {
121                { 0xa8, 0x00, 0x07 },
122            }
123        },
124        {   ModelId::PLUSTEK_OPTICFILM_7300, ScanMethod::TRANSPARENCY, {}, {} },
125        {   ModelId::PLUSTEK_OPTICFILM_7400, ScanMethod::TRANSPARENCY, {}, {} },
126        {   ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY, {}, {} },
127        {   ModelId::PLUSTEK_OPTICFILM_7500I, ScanMethod::TRANSPARENCY_INFRARED, {
128                { 0xa8, 0x07, 0x07 },
129            }, {
130                { 0xa8, 0x00, 0x07 },
131            }
132        },
133        {   ModelId::PLUSTEK_OPTICFILM_8200I, ScanMethod::TRANSPARENCY, {}, {} },
134        {   ModelId::PLUSTEK_OPTICFILM_8200I, ScanMethod::TRANSPARENCY_INFRARED, {
135                { 0xa8, 0x04, 0x04 },
136            }, {
137                { 0xa8, 0x00, 0x04 },
138            }
139        },
140    };
141
142    for (const auto& setting : settings) {
143        if (setting.model_id == dev.model->model_id &&
144            setting.scan_method == dev.settings.scan_method)
145        {
146            apply_reg_settings_to_device(dev, set ? setting.regs_on : setting.regs_off);
147            return;
148        }
149    }
150
151    throw SaneException("Could not find XPA lamp settings");
152}
153
154
155void CommandSetCommon::set_motor_mode(Genesys_Device& dev, Genesys_Register_Set& regs,
156                                      MotorMode mode) const
157{
158    DBG_HELPER(dbg);
159
160    struct MotorSettings {
161        ModelId model_id;
162        ValueFilterAny<unsigned> resolutions;
163        GenesysRegisterSettingSet regs_primary_and_secondary;
164        GenesysRegisterSettingSet regs_primary;
165        GenesysRegisterSettingSet regs_secondary;
166    };
167
168    MotorSettings settings[] = {
169        {   ModelId::CANON_8400F, { 400, 800, 1600, 3200 }, {
170                { 0x6c, 0x00, 0x90 },
171                { 0xa9, 0x04, 0x06 },
172            }, {
173                { 0x6c, 0x90, 0x90 },
174                { 0xa9, 0x02, 0x06 },
175            }, {}
176        },
177        {   ModelId::CANON_8600F, { 300, 600, 1200 }, {
178                { 0x6c, 0x00, 0x60 },
179                { 0xa6, 0x01, 0x41 },
180            }, {
181                { 0x6c, 0x20, 0x62 },
182                { 0xa6, 0x00, 0x41 },
183            }, {
184                { 0x6c, 0x40, 0x62 },
185                { 0xa6, 0x01, 0x41 },
186            }
187        },
188        {   ModelId::CANON_8600F, { 2400, 4800 }, {
189                { 0x6c, 0x02, 0x62 },
190                { 0xa6, 0x01, 0x41 },
191            }, {
192                { 0x6c, 0x20, 0x62 },
193                { 0xa6, 0x00, 0x41 },
194            }, {
195                { 0x6c, 0x40, 0x62 },
196                { 0xa6, 0x01, 0x41 },
197            }
198        },
199        {   ModelId::HP_SCANJET_G4050, VALUE_FILTER_ANY, {
200                { 0x6b, 0x81, 0x81 }, // set MULTFILM and GPOADF
201                { 0x6c, 0x00, 0x40 }, // note that reverse change is not applied on off
202                // 0xa6 register 0x08 bit likely sets motor power. No move at all without that one
203                { 0xa6, 0x08, 0x08 }, // note that reverse change is not applied on off
204                { 0xa8, 0x00, 0x04 },
205                { 0xa9, 0x30, 0x30 },
206            }, {
207                { 0x6b, 0x00, 0x01 }, // BUG: note that only ADF is unset
208                { 0xa8, 0x04, 0x04 },
209                { 0xa9, 0x00, 0x10 }, // note that 0x20 bit is not reset
210            }, {}
211        },
212        {   ModelId::PLUSTEK_OPTICFILM_7200, VALUE_FILTER_ANY, {}, {}, {} },
213        {   ModelId::PLUSTEK_OPTICFILM_7200I, VALUE_FILTER_ANY, {}, {}, {} },
214        {   ModelId::PLUSTEK_OPTICFILM_7300, VALUE_FILTER_ANY, {}, {}, {} },
215        {   ModelId::PLUSTEK_OPTICFILM_7400, VALUE_FILTER_ANY, {}, {}, {} },
216        {   ModelId::PLUSTEK_OPTICFILM_7500I, VALUE_FILTER_ANY, {}, {}, {} },
217        {   ModelId::PLUSTEK_OPTICFILM_8200I, VALUE_FILTER_ANY, {}, {}, {} },
218    };
219
220    for (const auto& setting : settings) {
221        if (setting.model_id == dev.model->model_id &&
222            setting.resolutions.matches(dev.session.output_resolution))
223        {
224            switch (mode) {
225                case MotorMode::PRIMARY: {
226                    apply_reg_settings_to_device(dev, setting.regs_primary);
227                    break;
228                }
229                case MotorMode::PRIMARY_AND_SECONDARY: {
230                    apply_reg_settings_to_device(dev, setting.regs_primary_and_secondary);
231                    break;
232                }
233                case MotorMode::SECONDARY: {
234                    apply_reg_settings_to_device(dev, setting.regs_secondary);
235                    break;
236                }
237            }
238            regs.state.motor_mode = mode;
239            return;
240        }
241    }
242
243    throw SaneException("Motor settings have not been found");
244}
245
246} // namespace genesys
247