1/* sane - Scanner Access Now Easy.
2
3   Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
4   Copyright (C) 2002-2007 Henning Geinitz <sane@geinitz.org>
5
6   This file is part of the SANE package.
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
21   As a special exception, the authors of SANE give permission for
22   additional uses of the libraries contained in this release of SANE.
23
24   The exception is that, if you link a SANE library with other files
25   to produce an executable, this does not by itself cause the
26   resulting executable to be covered by the GNU General Public
27   License.  Your use of that executable is in no way restricted on
28   account of linking the SANE library code into it.
29
30   This exception does not, however, invalidate any other reasons why
31   the executable file might be covered by the GNU General Public
32   License.
33
34   If you submit changes to SANE to the maintainers to be included in
35   a subsequent release, you agree by submitting the changes that
36   those changes may be distributed with this exception intact.
37
38   If you write modifications of your own for SANE, it is your choice
39   whether to permit this exception to apply to your modifications.
40   If you do not wish that, delete this exception notice.
41*/
42
43/** @file
44 * @brief Implementation of the gt6816 specific functions.
45 */
46
47#include "gt68xx_gt6816.h"
48
49SANE_Status
50gt6816_check_firmware (GT68xx_Device * dev, SANE_Bool * loaded)
51{
52  SANE_Status status;
53  GT68xx_Packet req;
54
55  memset (req, 0, sizeof (req));
56  req[0] = 0x70;
57  req[1] = 0x01;
58
59  status = gt68xx_device_small_req (dev, req, req);
60  if (status != SANE_STATUS_GOOD)
61    {
62      /* Assume that firmware is not loaded because without firmware, we need
63         64 bytes for the result, not 8 */
64      *loaded = SANE_FALSE;
65      return SANE_STATUS_GOOD;
66    }
67  /* check anyway */
68  if (req[0] == 0x00 && req[1] == 0x70 && req[2] == 0xff)
69    *loaded = SANE_TRUE;
70  else
71    *loaded = SANE_FALSE;
72
73  return SANE_STATUS_GOOD;
74}
75
76
77#define MAX_DOWNLOAD_BLOCK_SIZE 64
78
79SANE_Status
80gt6816_download_firmware (GT68xx_Device * dev,
81			  SANE_Byte * data, SANE_Word size)
82{
83  SANE_Status status;
84  SANE_Byte download_buf[MAX_DOWNLOAD_BLOCK_SIZE];
85  SANE_Byte check_buf[MAX_DOWNLOAD_BLOCK_SIZE];
86  SANE_Byte *block;
87  SANE_Word addr, bytes_left;
88  GT68xx_Packet boot_req;
89  SANE_Word block_size = MAX_DOWNLOAD_BLOCK_SIZE;
90
91  CHECK_DEV_ACTIVE (dev, "gt6816_download_firmware");
92
93  for (addr = 0; addr < size; addr += block_size)
94    {
95      bytes_left = size - addr;
96      if (bytes_left > block_size)
97	block = data + addr;
98      else
99	{
100	  memset (download_buf, 0, block_size);
101	  memcpy (download_buf, data + addr, bytes_left);
102	  block = download_buf;
103	}
104      RIE (gt68xx_device_memory_write (dev, addr, block_size, block));
105      RIE (gt68xx_device_memory_read (dev, addr, block_size, check_buf));
106      if (memcmp (block, check_buf, block_size) != 0)
107	{
108	  DBG (3, "gt6816_download_firmware: mismatch at block 0x%0x\n",
109	       addr);
110	  return SANE_STATUS_IO_ERROR;
111	}
112    }
113
114  memset (boot_req, 0, sizeof (boot_req));
115  boot_req[0] = 0x69;
116  boot_req[1] = 0x01;
117  boot_req[2] = LOBYTE (addr);
118  boot_req[3] = HIBYTE (addr);
119  RIE (gt68xx_device_req (dev, boot_req, boot_req));
120
121  return SANE_STATUS_GOOD;
122}
123
124
125SANE_Status
126gt6816_get_power_status (GT68xx_Device * dev, SANE_Bool * power_ok)
127{
128  SANE_Status status;
129  GT68xx_Packet req;
130
131  memset (req, 0, sizeof (req));
132  req[0] = 0x3f;
133  req[1] = 0x01;
134
135  RIE (gt68xx_device_req (dev, req, req));
136
137  if ((req[0] == 0x00 && req[1] == 0x3f && req[2] == 0x01)
138      || (dev->model->flags & GT68XX_FLAG_NO_POWER_STATUS))
139    *power_ok = SANE_TRUE;
140  else
141    *power_ok = SANE_FALSE;
142
143  return SANE_STATUS_GOOD;
144}
145
146SANE_Status
147gt6816_get_ta_status (GT68xx_Device * dev, SANE_Bool * ta_attached)
148{
149  SANE_Status status;
150  GT68xx_Packet req;
151
152  memset (req, 0, sizeof (req));
153  req[0] = 0x28;
154  req[1] = 0x01;
155
156  RIE (gt68xx_device_req (dev, req, req));
157
158  if (req[0] == 0x00 && req[1] == 0x28 && (req[8] & 0x01) != 0
159      && !dev->model->is_cis)
160    *ta_attached = SANE_TRUE;
161  else
162    *ta_attached = SANE_FALSE;
163
164  return SANE_STATUS_GOOD;
165}
166
167
168SANE_Status
169gt6816_lamp_control (GT68xx_Device * dev, SANE_Bool fb_lamp,
170		     SANE_Bool ta_lamp)
171{
172  GT68xx_Packet req;
173
174  memset (req, 0, sizeof (req));
175  req[0] = 0x25;
176  req[1] = 0x01;
177  req[2] = 0;
178  if (fb_lamp)
179    req[2] |= 0x01;
180  if (ta_lamp)
181    req[2] |= 0x02;
182
183  return gt68xx_device_req (dev, req, req);
184}
185
186
187SANE_Status
188gt6816_is_moving (GT68xx_Device * dev, SANE_Bool * moving)
189{
190  SANE_Status status;
191  GT68xx_Packet req;
192
193  memset (req, 0, sizeof (req));
194  req[0] = 0x17;
195  req[1] = 0x01;
196
197  RIE (gt68xx_device_req (dev, req, req));
198
199  if (req[0] == 0x00 && req[1] == 0x17)
200    {
201      if (req[2] == 0 && (req[3] == 0 || req[3] == 2))
202	*moving = SANE_FALSE;
203      else
204	*moving = SANE_TRUE;
205    }
206  else
207    return SANE_STATUS_IO_ERROR;
208
209  return SANE_STATUS_GOOD;
210}
211
212
213SANE_Status
214gt6816_carriage_home (GT68xx_Device * dev)
215{
216  GT68xx_Packet req;
217
218  memset (req, 0, sizeof (req));
219  req[0] = 0x24;
220  req[1] = 0x01;
221
222  return gt68xx_device_req (dev, req, req);
223}
224
225
226SANE_Status
227gt6816_stop_scan (GT68xx_Device * dev)
228{
229  GT68xx_Packet req;
230
231  memset (req, 0, sizeof (req));
232  req[0] = 0x41;
233  req[1] = 0x01;
234
235  return gt68xx_device_small_req (dev, req, req);
236}
237
238SANE_Status
239gt6816_document_present (GT68xx_Device * dev, SANE_Bool * present)
240{
241  SANE_Status status;
242  GT68xx_Packet req;
243
244  memset (req, 0, sizeof (req));
245  req[0] = 0x59;
246  req[1] = 0x01;
247
248  RIE (gt68xx_device_req (dev, req, req));
249
250  if (req[0] == 0x00 && req[1] == 0x59)
251    {
252      if (req[2] == 0)
253	*present = SANE_FALSE;
254      else
255	*present = SANE_TRUE;
256    }
257  else
258    return SANE_STATUS_IO_ERROR;
259
260  return SANE_STATUS_GOOD;
261}
262