1141cc406Sopenharmony_ci/* SANE - Scanner Access Now Easy.
2141cc406Sopenharmony_ci * For limitations, see function sanei_usb_get_vendor_product().
3141cc406Sopenharmony_ci
4141cc406Sopenharmony_ci   Copyright (C) 2011-2020 Rolf Bensch <rolf at bensch hyphen online dot de>
5141cc406Sopenharmony_ci   Copyright (C) 2006-2007 Wittawat Yamwong <wittawat@web.de>
6141cc406Sopenharmony_ci
7141cc406Sopenharmony_ci   This file is part of the SANE package.
8141cc406Sopenharmony_ci
9141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
10141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
11141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
12141cc406Sopenharmony_ci   License, or (at your option) any later version.
13141cc406Sopenharmony_ci
14141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
15141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
16141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17141cc406Sopenharmony_ci   General Public License for more details.
18141cc406Sopenharmony_ci
19141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
20141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
21141cc406Sopenharmony_ci
22141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
23141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
24141cc406Sopenharmony_ci
25141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
26141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
27141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
28141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
29141cc406Sopenharmony_ci   account of linking the SANE library code into it.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
32141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
33141cc406Sopenharmony_ci   License.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
36141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
37141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
38141cc406Sopenharmony_ci
39141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
40141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
41141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
42141cc406Sopenharmony_ci */
43141cc406Sopenharmony_ci#include "../include/sane/config.h"
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_ci#include <string.h>
46141cc406Sopenharmony_ci#include <stdlib.h>
47141cc406Sopenharmony_ci#include <stdio.h>
48141cc406Sopenharmony_ci#include <limits.h>		/* INT_MAX */
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#include "pixma_rename.h"
51141cc406Sopenharmony_ci#include "pixma_common.h"
52141cc406Sopenharmony_ci#include "pixma_io.h"
53141cc406Sopenharmony_ci#include "pixma_bjnp.h"
54141cc406Sopenharmony_ci
55141cc406Sopenharmony_ci#include "../include/sane/sanei_usb.h"
56141cc406Sopenharmony_ci#include "../include/sane/sane.h"
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci
59141cc406Sopenharmony_ci#ifdef __GNUC__
60141cc406Sopenharmony_ci# define UNUSED(v) (void) v
61141cc406Sopenharmony_ci#else
62141cc406Sopenharmony_ci# define UNUSED(v)
63141cc406Sopenharmony_ci#endif
64141cc406Sopenharmony_ci
65141cc406Sopenharmony_ci/* MAC OS X does not support timeouts in darwin/libusb interrupt reads
66141cc406Sopenharmony_ci * This is a very basic turnaround for MAC OS X
67141cc406Sopenharmony_ci * Button scan will not work with this wrapper */
68141cc406Sopenharmony_ci#ifdef __APPLE__
69141cc406Sopenharmony_ci# define sanei_usb_read_int sanei_usb_read_bulk
70141cc406Sopenharmony_ci#endif
71141cc406Sopenharmony_ci
72141cc406Sopenharmony_ci
73141cc406Sopenharmony_cistruct pixma_io_t
74141cc406Sopenharmony_ci{
75141cc406Sopenharmony_ci  pixma_io_t *next;
76141cc406Sopenharmony_ci  int interface;
77141cc406Sopenharmony_ci  SANE_Int dev;
78141cc406Sopenharmony_ci};
79141cc406Sopenharmony_ci
80141cc406Sopenharmony_citypedef struct scanner_info_t
81141cc406Sopenharmony_ci{
82141cc406Sopenharmony_ci  struct scanner_info_t *next;
83141cc406Sopenharmony_ci  char *devname;
84141cc406Sopenharmony_ci  int interface;
85141cc406Sopenharmony_ci  const pixma_config_t *cfg;
86141cc406Sopenharmony_ci  char serial[PIXMA_MAX_ID_LEN + 1];	/* "xxxxyyyy_zzzzzzz..."
87141cc406Sopenharmony_ci					   x = vid, y = pid, z = serial */
88141cc406Sopenharmony_ci} scanner_info_t;
89141cc406Sopenharmony_ci
90141cc406Sopenharmony_ci#define INT_USB 0
91141cc406Sopenharmony_ci#define INT_BJNP 1
92141cc406Sopenharmony_ci
93141cc406Sopenharmony_cistatic scanner_info_t *first_scanner = NULL;
94141cc406Sopenharmony_cistatic pixma_io_t *first_io = NULL;
95141cc406Sopenharmony_cistatic unsigned nscanners;
96141cc406Sopenharmony_ci
97141cc406Sopenharmony_ci
98141cc406Sopenharmony_cistatic scanner_info_t *
99141cc406Sopenharmony_ciget_scanner_info (unsigned devnr)
100141cc406Sopenharmony_ci{
101141cc406Sopenharmony_ci  scanner_info_t *si;
102141cc406Sopenharmony_ci  for (si = first_scanner; si && devnr != 0; --devnr, si = si->next)
103141cc406Sopenharmony_ci    {
104141cc406Sopenharmony_ci    }
105141cc406Sopenharmony_ci  return si;
106141cc406Sopenharmony_ci}
107141cc406Sopenharmony_ci
108141cc406Sopenharmony_cistatic SANE_Status
109141cc406Sopenharmony_ciattach (SANE_String_Const devname)
110141cc406Sopenharmony_ci{
111141cc406Sopenharmony_ci  scanner_info_t *si;
112141cc406Sopenharmony_ci
113141cc406Sopenharmony_ci  si = (scanner_info_t *) calloc (1, sizeof (*si));
114141cc406Sopenharmony_ci  if (!si)
115141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
116141cc406Sopenharmony_ci  si->devname = strdup (devname);
117141cc406Sopenharmony_ci  if (!si->devname)
118141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
119141cc406Sopenharmony_ci  si -> interface = INT_USB;
120141cc406Sopenharmony_ci  si->next = first_scanner;
121141cc406Sopenharmony_ci  first_scanner = si;
122141cc406Sopenharmony_ci  nscanners++;
123141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
124141cc406Sopenharmony_ci}
125141cc406Sopenharmony_ci
126141cc406Sopenharmony_ci
127141cc406Sopenharmony_cistatic SANE_Status
128141cc406Sopenharmony_ciattach_bjnp (SANE_String_Const devname,
129141cc406Sopenharmony_ci             SANE_String_Const serial,
130141cc406Sopenharmony_ci             const struct pixma_config_t *cfg)
131141cc406Sopenharmony_ci{
132141cc406Sopenharmony_ci  scanner_info_t *si;
133141cc406Sopenharmony_ci
134141cc406Sopenharmony_ci  si = (scanner_info_t *) calloc (1, sizeof (*si));
135141cc406Sopenharmony_ci  if (!si)
136141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
137141cc406Sopenharmony_ci  si->devname = strdup (devname);
138141cc406Sopenharmony_ci  if (!si->devname)
139141cc406Sopenharmony_ci    return SANE_STATUS_NO_MEM;
140141cc406Sopenharmony_ci
141141cc406Sopenharmony_ci  si->cfg = cfg;
142141cc406Sopenharmony_ci  sprintf(si->serial, "%s_%s", cfg->model, serial);
143141cc406Sopenharmony_ci  si -> interface = INT_BJNP;
144141cc406Sopenharmony_ci  si->next = first_scanner;
145141cc406Sopenharmony_ci  first_scanner = si;
146141cc406Sopenharmony_ci  nscanners++;
147141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
148141cc406Sopenharmony_ci}
149141cc406Sopenharmony_ci
150141cc406Sopenharmony_cistatic void
151141cc406Sopenharmony_ciclear_scanner_list (void)
152141cc406Sopenharmony_ci{
153141cc406Sopenharmony_ci  scanner_info_t *si = first_scanner;
154141cc406Sopenharmony_ci  while (si)
155141cc406Sopenharmony_ci    {
156141cc406Sopenharmony_ci      scanner_info_t *temp = si;
157141cc406Sopenharmony_ci      free (si->devname);
158141cc406Sopenharmony_ci      si = si->next;
159141cc406Sopenharmony_ci      free (temp);
160141cc406Sopenharmony_ci    }
161141cc406Sopenharmony_ci  nscanners = 0;
162141cc406Sopenharmony_ci  first_scanner = NULL;
163141cc406Sopenharmony_ci}
164141cc406Sopenharmony_ci
165141cc406Sopenharmony_cistatic SANE_Status
166141cc406Sopenharmony_ciget_descriptor (SANE_Int dn, SANE_Int type, SANE_Int descidx,
167141cc406Sopenharmony_ci		SANE_Int index, SANE_Int length, SANE_Byte * data)
168141cc406Sopenharmony_ci{
169141cc406Sopenharmony_ci  return sanei_usb_control_msg (dn, 0x80, USB_REQ_GET_DESCRIPTOR,
170141cc406Sopenharmony_ci				((type & 0xff) << 8) | (descidx & 0xff),
171141cc406Sopenharmony_ci				index, length, data);
172141cc406Sopenharmony_ci}
173141cc406Sopenharmony_ci
174141cc406Sopenharmony_cistatic SANE_Status
175141cc406Sopenharmony_ciget_string_descriptor (SANE_Int dn, SANE_Int index, SANE_Int lang,
176141cc406Sopenharmony_ci		       SANE_Int length, SANE_Byte * data)
177141cc406Sopenharmony_ci{
178141cc406Sopenharmony_ci  return get_descriptor (dn, USB_DT_STRING, index, lang, length, data);
179141cc406Sopenharmony_ci}
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_cistatic void
182141cc406Sopenharmony_ciu16tohex (uint16_t x, char *str)
183141cc406Sopenharmony_ci{
184141cc406Sopenharmony_ci  static const char hdigit[16] =
185141cc406Sopenharmony_ci    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
186141cc406Sopenharmony_ci    'E', 'F'
187141cc406Sopenharmony_ci    };
188141cc406Sopenharmony_ci  str[0] = hdigit[(x >> 12) & 0xf];
189141cc406Sopenharmony_ci  str[1] = hdigit[(x >> 8) & 0xf];
190141cc406Sopenharmony_ci  str[2] = hdigit[(x >> 4) & 0xf];
191141cc406Sopenharmony_ci  str[3] = hdigit[x & 0xf];
192141cc406Sopenharmony_ci  str[4] = '\0';
193141cc406Sopenharmony_ci}
194141cc406Sopenharmony_ci
195141cc406Sopenharmony_cistatic void
196141cc406Sopenharmony_ciread_serial_number (scanner_info_t * si)
197141cc406Sopenharmony_ci{
198141cc406Sopenharmony_ci  uint8_t unicode[2 * (PIXMA_MAX_ID_LEN - 9) + 2];
199141cc406Sopenharmony_ci  uint8_t ddesc[18];
200141cc406Sopenharmony_ci  int iSerialNumber;
201141cc406Sopenharmony_ci  SANE_Int usb;
202141cc406Sopenharmony_ci  char *serial = si->serial;
203141cc406Sopenharmony_ci
204141cc406Sopenharmony_ci  u16tohex (si->cfg->vid, serial);
205141cc406Sopenharmony_ci  u16tohex (si->cfg->pid, serial + 4);
206141cc406Sopenharmony_ci
207141cc406Sopenharmony_ci  if (SANE_STATUS_GOOD != sanei_usb_open (si->devname, &usb))
208141cc406Sopenharmony_ci    return;
209141cc406Sopenharmony_ci  if (get_descriptor (usb, USB_DT_DEVICE, 0, 0, 18, ddesc)
210141cc406Sopenharmony_ci      != SANE_STATUS_GOOD)
211141cc406Sopenharmony_ci    goto done;
212141cc406Sopenharmony_ci  iSerialNumber = ddesc[16];
213141cc406Sopenharmony_ci  if (iSerialNumber != 0)
214141cc406Sopenharmony_ci    {
215141cc406Sopenharmony_ci      int i, len;
216141cc406Sopenharmony_ci      SANE_Status status;
217141cc406Sopenharmony_ci
218141cc406Sopenharmony_ci      /*int iSerialNumber = ddesc[16];*/
219141cc406Sopenharmony_ci      /* Read the first language code. Assumed that there is at least one. */
220141cc406Sopenharmony_ci      if (get_string_descriptor (usb, 0, 0, 4, unicode) != SANE_STATUS_GOOD)
221141cc406Sopenharmony_ci        goto done;
222141cc406Sopenharmony_ci      /* Read the serial number string. */
223141cc406Sopenharmony_ci      status = get_string_descriptor (usb, iSerialNumber,
224141cc406Sopenharmony_ci                                      unicode[3] * 256 + unicode[2],
225141cc406Sopenharmony_ci                                      sizeof (unicode), unicode);
226141cc406Sopenharmony_ci      if (status != SANE_STATUS_GOOD)
227141cc406Sopenharmony_ci        goto done;
228141cc406Sopenharmony_ci      /* Assumed charset: Latin1 */
229141cc406Sopenharmony_ci      len = unicode[0];
230141cc406Sopenharmony_ci      if (len > (int) sizeof (unicode))
231141cc406Sopenharmony_ci        {
232141cc406Sopenharmony_ci          len = sizeof (unicode);
233141cc406Sopenharmony_ci          PDBG (pixma_dbg (1, "WARNING:Truncated serial number\n"));
234141cc406Sopenharmony_ci        }
235141cc406Sopenharmony_ci            serial[8] = '_';
236141cc406Sopenharmony_ci            for (i = 2; i < len; i += 2)
237141cc406Sopenharmony_ci        {
238141cc406Sopenharmony_ci          serial[9 + i / 2 - 1] = unicode[i];
239141cc406Sopenharmony_ci        }
240141cc406Sopenharmony_ci      serial[9 + i / 2 - 1] = '\0';
241141cc406Sopenharmony_ci    }
242141cc406Sopenharmony_ci  else
243141cc406Sopenharmony_ci    {
244141cc406Sopenharmony_ci      PDBG (pixma_dbg (1, "WARNING:No serial number\n"));
245141cc406Sopenharmony_ci    }
246141cc406Sopenharmony_cidone:
247141cc406Sopenharmony_ci  sanei_usb_close (usb);
248141cc406Sopenharmony_ci}
249141cc406Sopenharmony_ci
250141cc406Sopenharmony_cistatic int
251141cc406Sopenharmony_cimap_error (SANE_Status ss)
252141cc406Sopenharmony_ci{
253141cc406Sopenharmony_ci  switch (ss)
254141cc406Sopenharmony_ci    {
255141cc406Sopenharmony_ci    case SANE_STATUS_GOOD:
256141cc406Sopenharmony_ci      return 0;
257141cc406Sopenharmony_ci    case SANE_STATUS_UNSUPPORTED:
258141cc406Sopenharmony_ci      return PIXMA_ENODEV;
259141cc406Sopenharmony_ci    case SANE_STATUS_DEVICE_BUSY:
260141cc406Sopenharmony_ci      return PIXMA_EBUSY;
261141cc406Sopenharmony_ci    case SANE_STATUS_INVAL:
262141cc406Sopenharmony_ci      return PIXMA_EINVAL;
263141cc406Sopenharmony_ci    case SANE_STATUS_IO_ERROR:
264141cc406Sopenharmony_ci      return PIXMA_EIO;
265141cc406Sopenharmony_ci    case SANE_STATUS_NO_MEM:
266141cc406Sopenharmony_ci      return PIXMA_ENOMEM;
267141cc406Sopenharmony_ci    case SANE_STATUS_ACCESS_DENIED:
268141cc406Sopenharmony_ci      return PIXMA_EACCES;
269141cc406Sopenharmony_ci    case SANE_STATUS_CANCELLED:
270141cc406Sopenharmony_ci      return PIXMA_ECANCELED;
271141cc406Sopenharmony_ci    case SANE_STATUS_JAMMED:
272141cc406Sopenharmony_ci       return PIXMA_EPAPER_JAMMED;
273141cc406Sopenharmony_ci    case SANE_STATUS_COVER_OPEN:
274141cc406Sopenharmony_ci       return PIXMA_ECOVER_OPEN;
275141cc406Sopenharmony_ci    case SANE_STATUS_NO_DOCS:
276141cc406Sopenharmony_ci       return PIXMA_ENO_PAPER;
277141cc406Sopenharmony_ci    case SANE_STATUS_EOF:
278141cc406Sopenharmony_ci       return PIXMA_EOF;
279141cc406Sopenharmony_ci#ifdef SANE_STATUS_HW_LOCKED
280141cc406Sopenharmony_ci    case SANE_STATUS_HW_LOCKED:       /* unused by pixma */
281141cc406Sopenharmony_ci#endif
282141cc406Sopenharmony_ci#ifdef SANE_STATUS_WARMING_UP
283141cc406Sopenharmony_ci    case SANE_STATUS_WARMING_UP:      /* unused by pixma */
284141cc406Sopenharmony_ci#endif
285141cc406Sopenharmony_ci      break;
286141cc406Sopenharmony_ci    }
287141cc406Sopenharmony_ci  PDBG (pixma_dbg (1, "BUG:Unmapped SANE Status code %d\n", ss));
288141cc406Sopenharmony_ci  return PIXMA_EIO;		/* should not happen */
289141cc406Sopenharmony_ci}
290141cc406Sopenharmony_ci
291141cc406Sopenharmony_ci
292141cc406Sopenharmony_ciint
293141cc406Sopenharmony_cipixma_io_init (void)
294141cc406Sopenharmony_ci{
295141cc406Sopenharmony_ci  sanei_usb_init ();
296141cc406Sopenharmony_ci  sanei_bjnp_init();
297141cc406Sopenharmony_ci  nscanners = 0;
298141cc406Sopenharmony_ci  return 0;
299141cc406Sopenharmony_ci}
300141cc406Sopenharmony_ci
301141cc406Sopenharmony_civoid
302141cc406Sopenharmony_cipixma_io_cleanup (void)
303141cc406Sopenharmony_ci{
304141cc406Sopenharmony_ci  while (first_io)
305141cc406Sopenharmony_ci    pixma_disconnect (first_io);
306141cc406Sopenharmony_ci  clear_scanner_list ();
307141cc406Sopenharmony_ci}
308141cc406Sopenharmony_ci
309141cc406Sopenharmony_ciunsigned
310141cc406Sopenharmony_cipixma_collect_devices (const char **conf_devices,
311141cc406Sopenharmony_ci                       const struct pixma_config_t *const pixma_devices[], SANE_Bool local_only)
312141cc406Sopenharmony_ci{
313141cc406Sopenharmony_ci  unsigned i, j;
314141cc406Sopenharmony_ci  struct scanner_info_t *si;
315141cc406Sopenharmony_ci  const struct pixma_config_t *cfg;
316141cc406Sopenharmony_ci
317141cc406Sopenharmony_ci  clear_scanner_list ();
318141cc406Sopenharmony_ci  j = 0;
319141cc406Sopenharmony_ci  for (i = 0; pixma_devices[i]; i++)
320141cc406Sopenharmony_ci    {
321141cc406Sopenharmony_ci      for (cfg = pixma_devices[i]; cfg->name; cfg++)
322141cc406Sopenharmony_ci        {
323141cc406Sopenharmony_ci          sanei_usb_find_devices (cfg->vid, cfg->pid, attach);
324141cc406Sopenharmony_ci          si = first_scanner;
325141cc406Sopenharmony_ci          while (j < nscanners)
326141cc406Sopenharmony_ci            {
327141cc406Sopenharmony_ci              PDBG (pixma_dbg (3, "pixma_collect_devices() found %s at %s\n",
328141cc406Sopenharmony_ci                   cfg->name, si->devname));
329141cc406Sopenharmony_ci              si->cfg = cfg;
330141cc406Sopenharmony_ci              read_serial_number (si);
331141cc406Sopenharmony_ci              si = si->next;
332141cc406Sopenharmony_ci              j++;
333141cc406Sopenharmony_ci            }
334141cc406Sopenharmony_ci        }
335141cc406Sopenharmony_ci    }
336141cc406Sopenharmony_ci  if (! local_only)
337141cc406Sopenharmony_ci    sanei_bjnp_find_devices(conf_devices, attach_bjnp, pixma_devices);
338141cc406Sopenharmony_ci
339141cc406Sopenharmony_ci  si = first_scanner;
340141cc406Sopenharmony_ci  while (j < nscanners)
341141cc406Sopenharmony_ci    {
342141cc406Sopenharmony_ci      PDBG (pixma_dbg (3, "pixma_collect_devices() found %s at %s\n",
343141cc406Sopenharmony_ci               si->cfg->name, si->devname));
344141cc406Sopenharmony_ci      si = si->next;
345141cc406Sopenharmony_ci      j++;
346141cc406Sopenharmony_ci
347141cc406Sopenharmony_ci    }
348141cc406Sopenharmony_ci  return nscanners;
349141cc406Sopenharmony_ci}
350141cc406Sopenharmony_ci
351141cc406Sopenharmony_ciconst pixma_config_t *
352141cc406Sopenharmony_cipixma_get_device_config (unsigned devnr)
353141cc406Sopenharmony_ci{
354141cc406Sopenharmony_ci  const scanner_info_t *si = get_scanner_info (devnr);
355141cc406Sopenharmony_ci  return (si) ? si->cfg : NULL;
356141cc406Sopenharmony_ci}
357141cc406Sopenharmony_ci
358141cc406Sopenharmony_ciconst char *
359141cc406Sopenharmony_cipixma_get_device_id (unsigned devnr)
360141cc406Sopenharmony_ci{
361141cc406Sopenharmony_ci  const scanner_info_t *si = get_scanner_info (devnr);
362141cc406Sopenharmony_ci  return (si) ? si->serial : NULL;
363141cc406Sopenharmony_ci}
364141cc406Sopenharmony_ci
365141cc406Sopenharmony_ciint
366141cc406Sopenharmony_cipixma_connect (unsigned devnr, pixma_io_t ** handle)
367141cc406Sopenharmony_ci{
368141cc406Sopenharmony_ci  pixma_io_t *io;
369141cc406Sopenharmony_ci  SANE_Int dev;
370141cc406Sopenharmony_ci  const scanner_info_t *si;
371141cc406Sopenharmony_ci  int error;
372141cc406Sopenharmony_ci
373141cc406Sopenharmony_ci  *handle = NULL;
374141cc406Sopenharmony_ci  si = get_scanner_info (devnr);
375141cc406Sopenharmony_ci  if (!si)
376141cc406Sopenharmony_ci    return PIXMA_EINVAL;
377141cc406Sopenharmony_ci  if (si-> interface == INT_BJNP)
378141cc406Sopenharmony_ci    error = map_error (sanei_bjnp_open (si->devname, &dev));
379141cc406Sopenharmony_ci  else
380141cc406Sopenharmony_ci    error = map_error (sanei_usb_open (si->devname, &dev));
381141cc406Sopenharmony_ci
382141cc406Sopenharmony_ci  if (error < 0)
383141cc406Sopenharmony_ci    return error;
384141cc406Sopenharmony_ci  io = (pixma_io_t *) calloc (1, sizeof (*io));
385141cc406Sopenharmony_ci  if (!io)
386141cc406Sopenharmony_ci    {
387141cc406Sopenharmony_ci      if (si -> interface == INT_BJNP)
388141cc406Sopenharmony_ci        sanei_bjnp_close (dev);
389141cc406Sopenharmony_ci      else
390141cc406Sopenharmony_ci        sanei_usb_close (dev);
391141cc406Sopenharmony_ci      return PIXMA_ENOMEM;
392141cc406Sopenharmony_ci    }
393141cc406Sopenharmony_ci  io->next = first_io;
394141cc406Sopenharmony_ci  first_io = io;
395141cc406Sopenharmony_ci  io->dev = dev;
396141cc406Sopenharmony_ci  io->interface = si->interface;
397141cc406Sopenharmony_ci  *handle = io;
398141cc406Sopenharmony_ci  return 0;
399141cc406Sopenharmony_ci}
400141cc406Sopenharmony_ci
401141cc406Sopenharmony_ci
402141cc406Sopenharmony_civoid
403141cc406Sopenharmony_cipixma_disconnect (pixma_io_t * io)
404141cc406Sopenharmony_ci{
405141cc406Sopenharmony_ci  pixma_io_t **p;
406141cc406Sopenharmony_ci
407141cc406Sopenharmony_ci  if (!io)
408141cc406Sopenharmony_ci    return;
409141cc406Sopenharmony_ci  for (p = &first_io; *p && *p != io; p = &((*p)->next))
410141cc406Sopenharmony_ci    {
411141cc406Sopenharmony_ci    }
412141cc406Sopenharmony_ci  PASSERT (*p);
413141cc406Sopenharmony_ci  if (!(*p))
414141cc406Sopenharmony_ci    return;
415141cc406Sopenharmony_ci  if (io-> interface == INT_BJNP)
416141cc406Sopenharmony_ci    sanei_bjnp_close (io->dev);
417141cc406Sopenharmony_ci  else
418141cc406Sopenharmony_ci    sanei_usb_close (io->dev);
419141cc406Sopenharmony_ci  *p = io->next;
420141cc406Sopenharmony_ci  free (io);
421141cc406Sopenharmony_ci}
422141cc406Sopenharmony_ci
423141cc406Sopenharmony_ciint pixma_activate (pixma_io_t * io)
424141cc406Sopenharmony_ci{
425141cc406Sopenharmony_ci  int error;
426141cc406Sopenharmony_ci  if (io->interface == INT_BJNP)
427141cc406Sopenharmony_ci    {
428141cc406Sopenharmony_ci      error = map_error(sanei_bjnp_activate (io->dev));
429141cc406Sopenharmony_ci    }
430141cc406Sopenharmony_ci  else
431141cc406Sopenharmony_ci    /* noop for USB interface */
432141cc406Sopenharmony_ci    error = 0;
433141cc406Sopenharmony_ci  return error;
434141cc406Sopenharmony_ci}
435141cc406Sopenharmony_ci
436141cc406Sopenharmony_ciint pixma_deactivate (pixma_io_t * io)
437141cc406Sopenharmony_ci{
438141cc406Sopenharmony_ci  int error;
439141cc406Sopenharmony_ci  if (io->interface == INT_BJNP)
440141cc406Sopenharmony_ci    {
441141cc406Sopenharmony_ci      error = map_error(sanei_bjnp_deactivate (io->dev));
442141cc406Sopenharmony_ci    }
443141cc406Sopenharmony_ci  else
444141cc406Sopenharmony_ci    /* noop for USB interface */
445141cc406Sopenharmony_ci    error = 0;
446141cc406Sopenharmony_ci  return error;
447141cc406Sopenharmony_ci
448141cc406Sopenharmony_ci}
449141cc406Sopenharmony_ci
450141cc406Sopenharmony_ciint
451141cc406Sopenharmony_cipixma_reset_device (pixma_io_t * io)
452141cc406Sopenharmony_ci{
453141cc406Sopenharmony_ci  UNUSED (io);
454141cc406Sopenharmony_ci  return PIXMA_ENOTSUP;
455141cc406Sopenharmony_ci}
456141cc406Sopenharmony_ci
457141cc406Sopenharmony_ciint
458141cc406Sopenharmony_cipixma_write (pixma_io_t * io, const void *cmd, unsigned len)
459141cc406Sopenharmony_ci{
460141cc406Sopenharmony_ci  size_t count = len;
461141cc406Sopenharmony_ci  int error;
462141cc406Sopenharmony_ci
463141cc406Sopenharmony_ci  if (io->interface == INT_BJNP)
464141cc406Sopenharmony_ci    {
465141cc406Sopenharmony_ci    sanei_bjnp_set_timeout (io->dev, PIXMA_BULKOUT_TIMEOUT);
466141cc406Sopenharmony_ci    error = map_error (sanei_bjnp_write_bulk (io->dev, cmd, &count));
467141cc406Sopenharmony_ci    }
468141cc406Sopenharmony_ci  else
469141cc406Sopenharmony_ci    {
470141cc406Sopenharmony_ci#ifdef HAVE_SANEI_USB_SET_TIMEOUT
471141cc406Sopenharmony_ci    sanei_usb_set_timeout (PIXMA_BULKOUT_TIMEOUT);
472141cc406Sopenharmony_ci#endif
473141cc406Sopenharmony_ci    error = map_error (sanei_usb_write_bulk (io->dev, cmd, &count));
474141cc406Sopenharmony_ci    }
475141cc406Sopenharmony_ci  if (error == PIXMA_EIO)
476141cc406Sopenharmony_ci    error = PIXMA_ETIMEDOUT;	/* FIXME: SANE doesn't have ETIMEDOUT!! */
477141cc406Sopenharmony_ci  if (count != len)
478141cc406Sopenharmony_ci    {
479141cc406Sopenharmony_ci      PDBG (pixma_dbg (1, "WARNING:pixma_write(): count(%u) != len(%u)\n",
480141cc406Sopenharmony_ci		       (unsigned) count, len));
481141cc406Sopenharmony_ci      error = PIXMA_EIO;
482141cc406Sopenharmony_ci    }
483141cc406Sopenharmony_ci  if (error >= 0)
484141cc406Sopenharmony_ci    error = count;
485141cc406Sopenharmony_ci  PDBG (pixma_dump (10, "OUT ", cmd, error, len, 128));
486141cc406Sopenharmony_ci  return error;
487141cc406Sopenharmony_ci}
488141cc406Sopenharmony_ci
489141cc406Sopenharmony_ciint
490141cc406Sopenharmony_cipixma_read (pixma_io_t * io, void *buf, unsigned size)
491141cc406Sopenharmony_ci{
492141cc406Sopenharmony_ci  size_t count = size;
493141cc406Sopenharmony_ci  int error;
494141cc406Sopenharmony_ci
495141cc406Sopenharmony_ci  if (io-> interface == INT_BJNP)
496141cc406Sopenharmony_ci    {
497141cc406Sopenharmony_ci    sanei_bjnp_set_timeout (io->dev, PIXMA_BULKIN_TIMEOUT);
498141cc406Sopenharmony_ci    error = map_error (sanei_bjnp_read_bulk (io->dev, buf, &count));
499141cc406Sopenharmony_ci    }
500141cc406Sopenharmony_ci  else
501141cc406Sopenharmony_ci    {
502141cc406Sopenharmony_ci#ifdef HAVE_SANEI_USB_SET_TIMEOUT
503141cc406Sopenharmony_ci      sanei_usb_set_timeout (PIXMA_BULKIN_TIMEOUT);
504141cc406Sopenharmony_ci#endif
505141cc406Sopenharmony_ci      error = map_error (sanei_usb_read_bulk (io->dev, buf, &count));
506141cc406Sopenharmony_ci    }
507141cc406Sopenharmony_ci
508141cc406Sopenharmony_ci  if (error == PIXMA_EIO)
509141cc406Sopenharmony_ci    error = PIXMA_ETIMEDOUT;	/* FIXME: SANE doesn't have ETIMEDOUT!! */
510141cc406Sopenharmony_ci  if (error >= 0)
511141cc406Sopenharmony_ci    error = count;
512141cc406Sopenharmony_ci  PDBG (pixma_dump (10, "IN  ", buf, error, -1, 128));
513141cc406Sopenharmony_ci  return error;
514141cc406Sopenharmony_ci}
515141cc406Sopenharmony_ci
516141cc406Sopenharmony_ciint
517141cc406Sopenharmony_cipixma_wait_interrupt (pixma_io_t * io, void *buf, unsigned size, int timeout)
518141cc406Sopenharmony_ci{
519141cc406Sopenharmony_ci  size_t count = size;
520141cc406Sopenharmony_ci  int error;
521141cc406Sopenharmony_ci
522141cc406Sopenharmony_ci  /* FIXME: What is the meaning of "timeout" in sanei_usb? */
523141cc406Sopenharmony_ci  if (timeout < 0)
524141cc406Sopenharmony_ci    timeout = INT_MAX;
525141cc406Sopenharmony_ci  else if (timeout < 100)
526141cc406Sopenharmony_ci    timeout = 100;
527141cc406Sopenharmony_ci  if (io-> interface == INT_BJNP)
528141cc406Sopenharmony_ci    {
529141cc406Sopenharmony_ci      sanei_bjnp_set_timeout (io->dev, timeout);
530141cc406Sopenharmony_ci      error = map_error (sanei_bjnp_read_int (io->dev, buf, &count));
531141cc406Sopenharmony_ci    }
532141cc406Sopenharmony_ci  else
533141cc406Sopenharmony_ci    {
534141cc406Sopenharmony_ci#ifdef HAVE_SANEI_USB_SET_TIMEOUT
535141cc406Sopenharmony_ci      sanei_usb_set_timeout (timeout);
536141cc406Sopenharmony_ci#endif
537141cc406Sopenharmony_ci      error = map_error (sanei_usb_read_int (io->dev, buf, &count));
538141cc406Sopenharmony_ci    }
539141cc406Sopenharmony_ci  if (error == PIXMA_EIO ||
540141cc406Sopenharmony_ci      (io->interface == INT_BJNP && error == PIXMA_EOF))     /* EOF is a bjnp timeout error! */
541141cc406Sopenharmony_ci    error = PIXMA_ETIMEDOUT;	/* FIXME: SANE doesn't have ETIMEDOUT!! */
542141cc406Sopenharmony_ci  if (error == 0)
543141cc406Sopenharmony_ci    error = count;
544141cc406Sopenharmony_ci  if (error != PIXMA_ETIMEDOUT)
545141cc406Sopenharmony_ci    PDBG (pixma_dump (10, "INTR", buf, error, -1, -1));
546141cc406Sopenharmony_ci  return error;
547141cc406Sopenharmony_ci}
548141cc406Sopenharmony_ci
549141cc406Sopenharmony_ciint
550141cc406Sopenharmony_cipixma_set_interrupt_mode (pixma_io_t * s, int background)
551141cc406Sopenharmony_ci{
552141cc406Sopenharmony_ci  UNUSED (s);
553141cc406Sopenharmony_ci  return (background) ? PIXMA_ENOTSUP : 0;
554141cc406Sopenharmony_ci}
555