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 
27 namespace genesys {
28 
29 CommandSetCommon::~CommandSetCommon() = default;
30 
is_head_home(Genesys_Device & dev,ScanHeadId scan_head) const31 bool 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 
set_xpa_lamp_power(Genesys_Device & dev,bool set) const69 void 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 
set_motor_mode(Genesys_Device & dev,Genesys_Register_Set & regs,MotorMode mode) const155 void 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