xref: /third_party/backends/backend/canon-scsi.c (revision 141cc406)
1/* sane - Scanner Access Now Easy.
2   Copyright (C) 1997 BYTEC GmbH Germany
3   Written by Helmut Koeberle, Email: helmut.koeberle@bytec.de
4   Modified by Manuel Panea <Manuel.Panea@rzg.mpg.de>
5   and Markus Mertinat <Markus.Mertinat@Physik.Uni-Augsburg.DE>
6
7   This file is part of the SANE package.
8
9   This program is free software; you can redistribute it and/or
10   modify it under the terms of the GNU General Public License as
11   published by the Free Software Foundation; either version 2 of the
12   License, or (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
22   As a special exception, the authors of SANE give permission for
23   additional uses of the libraries contained in this release of SANE.
24
25   The exception is that, if you link a SANE library with other files
26   to produce an executable, this does not by itself cause the
27   resulting executable to be covered by the GNU General Public
28   License.  Your use of that executable is in no way restricted on
29   account of linking the SANE library code into it.
30
31   This exception does not, however, invalidate any other reasons why
32   the executable file might be covered by the GNU General Public
33   License.
34
35   If you submit changes to SANE to the maintainers to be included in
36   a subsequent release, you agree by submitting the changes that
37   those changes may be distributed with this exception intact.
38
39   If you write modifications of your own for SANE, it is your choice
40   whether to permit this exception to apply to your modifications.
41   If you do not wish that, delete this exception notice. */
42
43/* This file implements the low-level scsi-commands.  */
44
45static SANE_Status
46test_unit_ready (int fd)
47{
48  static u_char cmd[6];
49  int status;
50  DBG (31, ">> test_unit_ready\n");
51
52  memset (cmd, 0, sizeof (cmd));
53  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
54
55  DBG (31, "<< test_unit_ready\n");
56  return (status);
57}
58
59#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS
60static SANE_Status
61request_sense (int fd, void *buf, size_t *buf_size)
62{
63  static u_char cmd[6];
64  int status;
65  DBG (31, ">> request_sense\n");
66
67  memset (cmd, 0, sizeof (cmd));
68  cmd[0] = 0x03;
69  cmd[4] = 14;
70  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
71
72  DBG (31, "<< request_sense\n");
73  return (status);
74}
75#endif
76
77static SANE_Status
78inquiry (int fd, int evpd, void *buf, size_t *buf_size)
79{
80  static u_char cmd[6];
81  int status;
82  DBG (31, ">> inquiry\n");
83
84  memset (cmd, 0, sizeof (cmd));
85  cmd[0] = 0x12;
86  cmd[1] = evpd;
87  cmd[2] = evpd ? 0xf0 : 0;
88  cmd[4] = evpd ? 74 : 36;
89  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
90
91  DBG (31, "<< inquiry\n");
92  return (status);
93}
94
95#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS
96static SANE_Status
97mode_select (int fd)
98{
99  static u_char cmd[6 + 12];
100  int status;
101  DBG (31, ">> mode_select\n");
102
103  memset (cmd, 0, sizeof (cmd));
104  cmd[0] = 0x15;
105  cmd[1] = 16;
106  cmd[4] = 12;
107  cmd[6 + 4] = 3;
108  cmd[6 + 5] = 6;
109  cmd[6 + 8] = 0x02;
110  cmd[6 + 9] = 0x58;
111  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), NULL, NULL);
112
113  DBG (31, "<< mode_select\n");
114  return (status);
115}
116#endif
117
118static SANE_Status
119reserve_unit (int fd)
120{
121  static u_char cmd[6];
122  int status;
123  DBG (31, ">> reserve_unit\n");
124
125  memset (cmd, 0, sizeof (cmd));
126  cmd[0] = 0x16;
127  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
128
129  DBG (31, "<< reserve_unit\n");
130  return (status);
131}
132
133#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS
134static SANE_Status
135release_unit (int fd)
136{
137  static u_char cmd[6];
138  int status;
139  DBG (31, ">> release_unit\n");
140
141  memset (cmd, 0, sizeof (cmd));
142  cmd[0] = 0x17;
143  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
144
145  DBG (31, "<< release_unit\n");
146  return (status);
147}
148#endif
149
150static SANE_Status
151mode_sense (int fd, void *buf, size_t *buf_size)
152{
153  static u_char cmd[6];
154  int status;
155  DBG (31, ">> mode_sense\n");
156
157  memset (cmd, 0, sizeof (cmd));
158  cmd[0] = 0x1a;
159  cmd[2] = 3;
160  cmd[4] = 12;
161  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
162
163  DBG (31, "<< mode_sense\n");
164  return (status);
165}
166
167static SANE_Status
168scan (int fd)
169{
170  static u_char cmd[6 + 1];
171  int status;
172  DBG (31, ">> scan\n");
173
174  memset (cmd, 0, sizeof (cmd));
175  cmd[0] = 0x1b;
176  cmd[4] = 1;
177  status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), NULL, NULL);
178
179  DBG (31, "<< scan\n");
180  return (status);
181}
182
183static SANE_Status
184send_diagnostic (int fd)
185{
186  static u_char cmd[6];
187  int status;
188  DBG (31, ">> send_diagnostic\n");
189
190  memset (cmd, 0, sizeof (cmd));
191  cmd[0] = 0x1d;
192  cmd[1] = 4;
193  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
194
195  DBG (31, "<< send_diagnostic\n");
196  return (status);
197}
198
199static SANE_Status
200set_window (int fd, void *data)
201{
202  static u_char cmd[10];
203  int status;
204  DBG (31, ">> set_window\n");
205
206  memset (cmd, 0, sizeof (cmd));
207  cmd[0] = 0x24;
208  cmd[8] = 72;
209  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), data, 72, NULL, NULL);
210
211  DBG (31, "<< set_window\n");
212  return (status);
213}
214
215static SANE_Status
216get_window (int fd, void *buf, size_t *buf_size)
217{
218  static u_char cmd[10];
219  int status;
220  DBG (31, ">> get_window\n");
221
222  memset (cmd, 0, sizeof (cmd));
223  cmd[0] = 0x25;
224  cmd[1] = 1;
225  cmd[8] = 72;
226  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
227
228  DBG (31, "<< get_window\n");
229  return (status);
230}
231
232static SANE_Status
233read_data (int fd, void *buf, size_t *buf_size)
234{
235  static u_char cmd[10];
236  int status;
237  DBG (31, ">> read_data\n");
238
239  memset (cmd, 0, sizeof (cmd));
240  cmd[0] = 0x28;
241  cmd[6] = *buf_size >> 16;
242  cmd[7] = *buf_size >> 8;
243  cmd[8] = *buf_size;
244  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
245
246  DBG (31, "<< read_data\n");
247  return (status);
248}
249
250static SANE_Status
251medium_position (int fd)
252{
253  static u_char cmd[10];
254  int status;
255  DBG (31, ">> medium_position\n");
256
257  memset (cmd, 0, sizeof (cmd));
258  cmd[0] = 0x31;
259  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
260
261  DBG (31, "<< medium_position\n");
262  return (status);
263}
264
265#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS
266static SANE_Status
267execute_shading (int fd)
268{
269  static u_char cmd[10];
270  int status;
271  DBG (31, ">> execute shading\n");
272
273  memset (cmd, 0, sizeof (cmd));
274  cmd[0] = 0xe2;
275  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
276
277  DBG (31, "<< execute shading\n");
278  return (status);
279}
280#endif
281
282static SANE_Status
283execute_auto_focus (int fd, int AF, int speed, int AE, int count)
284{
285  static u_char cmd[10];
286  int status;
287  DBG (7, ">> execute_auto_focus\n");
288  DBG (7, ">> focus: mode='%d', speed='%d', AE='%d', count='%d'\n",
289       AF, speed, AE, count);
290
291  memset (cmd, 0, sizeof (cmd));
292  cmd[0] = 0xe0;
293  cmd[1] = (u_char) AF;
294  cmd[2] = (u_char) ((speed << 7) | AE);
295#if 1
296  cmd[4] = (u_char) count;		/* seems to work, but may be unsafe */
297#else					/* The Canon software uses this: */
298  cmd[4] = (u_char) (28 * ((int) (count / 28.5)) + 16);
299#endif
300  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
301
302  DBG (7, "<< execute_auto_focus\n");
303  return (status);
304}
305
306static SANE_Status
307set_adf_mode (int fd, u_char priority)
308{
309  static u_char cmd[6];
310  int status;
311
312  memset (cmd, 0, sizeof (cmd));
313  cmd[0] = 0xd4;
314  cmd[4] = 0x01;
315
316  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), &priority, 1, NULL, NULL);
317
318  return (status);
319}
320
321static SANE_Status
322get_scan_mode (int fd, u_char page, void *buf, size_t *buf_size)
323{
324  static u_char cmd[6];
325  int status;
326  int PageLen = 0x00;
327
328  memset (cmd, 0, sizeof (cmd));
329  cmd[0] = 0xd5;
330  cmd[2] = page;
331
332  switch (page)
333    {
334    case AUTO_DOC_FEEDER_UNIT:
335    case TRANSPARENCY_UNIT:
336      cmd[4] = 0x0c + PageLen;
337      break;
338
339    case SCAN_CONTROL_CONDITIONS:
340      cmd[4] = 0x14 + PageLen;
341      break;
342
343    case SCAN_CONTROL_CON_FB1200:
344      cmd[2] = 0x20;
345      cmd[4] = 0x17 + PageLen;
346      break;
347
348    default:
349      cmd[4] = 0x24 + PageLen;
350      break;
351    }
352
353  DBG (31, "get scan mode: cmd[4]='0x%0X'\n", cmd[4]);
354  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
355
356  DBG (31, "<< get scan mode\n");
357  return (status);
358}
359
360static SANE_Status
361define_scan_mode (int fd, u_char page, void *data)
362{
363  static u_char cmd[6];
364  u_char pdata[36];
365  size_t i;
366  int status, pdatalen;
367  DBG (31, ">> define scan mode\n");
368
369  memset (cmd, 0, sizeof (cmd));
370  memset (pdata, 0, sizeof (pdata));
371  cmd[0] = 0xd6;
372  cmd[1] = 0x10;
373  cmd[4] = (page == TRANSPARENCY_UNIT) ? 0x0c
374    : (page == TRANSPARENCY_UNIT_FB1200) ? 0x0c
375    : (page == SCAN_CONTROL_CONDITIONS) ? 0x14
376    : (page == SCAN_CONTROL_CON_FB1200) ? 0x17 : 0x24;
377
378  memcpy (pdata + 4, data, (page == TRANSPARENCY_UNIT) ? 8
379    : (page == TRANSPARENCY_UNIT_FB1200) ? 10
380    : (page == SCAN_CONTROL_CONDITIONS) ? 16
381    : (page == SCAN_CONTROL_CON_FB1200) ? 19 : 32);
382
383  for (i = 0; i < sizeof (cmd); i++)
384    DBG (31, "define scan mode: cmd[%d]='0x%0X'\n", (int) i,
385    cmd[i]);
386
387  for (i = 0; i < sizeof (pdata); i++)
388    DBG (31, "define scan mode: pdata[%d]='0x%0X'\n", (int) i,
389    pdata[i]);
390
391  pdatalen = (page == TRANSPARENCY_UNIT) ? 12
392    : (page == TRANSPARENCY_UNIT_FB1200) ? 14
393    : (page == SCAN_CONTROL_CONDITIONS) ? 20
394    : (page == SCAN_CONTROL_CON_FB1200) ? 23 : 36;
395
396  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), pdata, pdatalen, NULL,
397    NULL);
398  DBG (31, "<< define scan mode\n");
399  return (status);
400}
401
402static SANE_Status
403get_density_curve (int fd, int component, void *buf, size_t *buf_size,
404		   int transfer_data_type)
405{
406  static u_char cmd[10];
407  int status;
408  DBG (31, ">> get_density_curve\n");
409
410  memset (cmd, 0, sizeof (cmd));
411  cmd[0] = 0x28;
412  cmd[2] = transfer_data_type;
413  cmd[4] = component;
414  cmd[5] = 0;
415  cmd[6] = ((*buf_size) >> 16) & 0xff;
416  cmd[7] = ((*buf_size) >> 8) & 0xff;
417  cmd[8] = (*buf_size) & 0xff;
418  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
419
420  DBG (31, "<< get_density_curve\n");
421  return (status);
422}
423
424#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS
425static SANE_Status
426get_density_curve_data_format (int fd, void *buf, size_t *buf_size)
427{
428  static u_char cmd[10];
429  int status;
430  DBG (31, ">> get_density_curve_data_format\n");
431
432  memset (cmd, 0, sizeof (cmd));
433  cmd[0] = 0x28;
434  cmd[2] = 0x03;
435  cmd[4] = 0xff;
436  cmd[5] = 0;
437  cmd[6] = 0;
438  cmd[7] = 0;
439  cmd[8] = 14;
440  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
441
442  DBG (31, "<< get_density_curve_data_format\n");
443  return (status);
444}
445#endif
446
447static SANE_Status
448set_density_curve (int fd, int component, void *buf, size_t *buf_size,
449		   int transfer_data_type)
450{
451  static u_char cmd[10];
452  int status;
453  DBG (31, ">> set_density_curve\n");
454
455  memset (cmd, 0, sizeof (cmd));
456  cmd[0] = 0x2a;
457  cmd[2] = transfer_data_type;
458  cmd[4] = component;
459  cmd[5] = 0;
460  cmd[6] = ((*buf_size) >> 16) & 0xff;
461  cmd[7] = ((*buf_size) >> 8) & 0xff;
462  cmd[8] = (*buf_size) & 0xff;
463
464  status =
465    sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), buf, *buf_size, NULL, NULL);
466
467  DBG (31, "<< set_density_curve\n");
468  return (status);
469}
470
471
472/* static SANE_Status */
473/* set_density_curve_data_format (int fd, void *buf, size_t *buf_size) */
474/* { */
475/*   static u_char cmd[10]; */
476/*   int status, i; */
477/*   DBG (31, ">> set_density_curve_data_format\n"); */
478
479/*   memset (cmd, 0, sizeof (cmd)); */
480/*   cmd[0] = 0x2a; */
481/*   cmd[2] = 0x03; */
482/*   cmd[4] = 0xff; */
483/*   cmd[5] = 0; */
484/*   cmd[6] = 0; */
485/*   cmd[7] = 0; */
486/*   cmd[8] = 14; */
487/*   status = sanei_scsi_cmd (fd, cmd, sizeof (cmd), buf, buf_size); */
488
489/*   DBG (31, "<< set_density_curve_data_format\n"); */
490/*   return (status); */
491/* } */
492
493#ifdef IMPLEMENT_ALL_SCANNER_SCSI_COMMANDS
494static SANE_Status
495get_power_on_timer (int fd, void *buf, size_t *buf_size)
496{
497  static u_char cmd[10];
498  int status;
499  DBG (31, ">> get power on timer\n");
500
501  memset (cmd, 0, sizeof (cmd));
502  cmd[0] = 0xe3;
503  cmd[6] = 1;
504  cmd[7] = 0;
505  cmd[8] = 0;
506  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
507
508  DBG (31, "<< get power on timer\n");
509  return (status);
510}
511#endif
512
513static SANE_Status
514get_film_status (int fd, void *buf, size_t *buf_size)
515{
516  static u_char cmd[10];
517  int status;
518  DBG (31, ">> get film status\n");
519
520  memset (cmd, 0, sizeof (cmd));
521  cmd[0] = 0xe1;
522  cmd[6] = 0;
523  cmd[7] = 0;
524  cmd[8] = 4;
525  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
526
527  DBG (31, "<< get film status\n");
528  return (status);
529}
530
531static SANE_Status
532get_data_status (int fd, void *buf, size_t *buf_size)
533{
534  static u_char cmd[10];
535  int status;
536  DBG (31, ">> get_data_status\n");
537
538  memset (cmd, 0, sizeof (cmd));
539  cmd[0] = 0x34;
540  cmd[8] = 28;
541  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
542
543  DBG (31, "<< get_data_status\n");
544  return (status);
545}
546
547/*************** modification for FB620S ***************/
548static SANE_Status
549reset_scanner (int fd)
550{
551  static u_char cmd[6];
552  int status;
553  DBG (31, ">> reset_scanner\n");
554
555  memset (cmd, 0, sizeof (cmd));
556  cmd[0] = 0xc1;
557  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
558
559  DBG (31, "<< reset_scanner \n");
560  return (status);
561}
562
563static SANE_Status
564execute_calibration (int fd)
565{
566  static u_char cmd[6];
567  u_char data[2];
568  int status;
569  DBG (31, ">> execute_calibration\n");
570
571  memset (cmd, 0, sizeof (cmd));
572  memset (data, 0, sizeof (data));
573  cmd[0] = 0xc2;
574  cmd[4] = 2;
575  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), data, sizeof (data),
576			    NULL, NULL);
577
578  DBG (31, "<< execute_calibration\n");
579  return (status);
580}
581
582static SANE_Status
583get_calibration_status (int fd, void *buf, size_t *buf_size)
584{
585  static u_char cmd[6];
586  int status;
587  DBG (31, ">> get_calibration_status\n");
588
589  memset (cmd, 0, sizeof (cmd));
590  cmd[0] = 0xc3;
591  cmd[4] = *buf_size;
592  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
593
594  DBG (31, "<< get_calibration_status\n");
595  return (status);
596}
597
598#if 0
599static SANE_Status
600get_switch_status (int fd, void *buf, size_t *buf_size)
601{
602  static u_char cmd[6];
603  int status;
604  DBG (31, ">> get_switch_status\n");
605
606  memset (cmd, 0, sizeof (cmd));
607  cmd[0] = 0xc4;
608  cmd[4] = 2;
609  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, buf, buf_size);
610
611  DBG (31, "<< get_switch_status\n");
612  return (status);
613}
614
615static SANE_Status
616wait_ready(int fd)
617{
618  SANE_Status status;
619  int retry = 0;
620
621  while ((status = test_unit_ready (fd)) != SANE_STATUS_GOOD)
622    {
623      DBG(5, "wait_ready failed (%d)\n", retry);
624      if (retry++ > 15)
625	return SANE_STATUS_IO_ERROR;
626      sleep(3);
627    }
628  return(status);
629}
630#endif
631
632/*************** modification for FB1200S ***************/
633static SANE_Status
634cancel (int fd)
635{
636  static u_char cmd[10];
637  int status;
638  DBG (31, ">> cancel_FB1200S\n");
639
640  memset (cmd, 0, sizeof (cmd));
641  cmd[0] = 0xe4;
642  status = sanei_scsi_cmd2 (fd, cmd, sizeof (cmd), NULL, 0, NULL, NULL);
643
644  DBG (31, "<< cancel_FB1200S \n");
645  return (status);
646}
647
648/**************************************************************************/
649/* As long as we do not know how this scanner stores its density curves,
650   we do the gamma correction with a 8 <--> 12 bit translation table
651   stored in the CANON_Scanner structure. */
652
653static SANE_Status
654get_density_curve_fs2710 (SANE_Handle handle, int component, u_char *buf,
655			  size_t *buf_size)
656{
657  CANON_Scanner *s = handle;
658  int i;
659
660  for (i = 0; i < 256; i++)
661    *buf++ = s->gamma_map[component][i << 4];
662  *buf_size = 256;
663  return (SANE_STATUS_GOOD);
664}
665
666static SANE_Status
667set_density_curve_fs2710 (SANE_Handle handle, int component, u_char *buf)
668{
669  CANON_Scanner *s = handle;
670  int i, j, hi, lo;
671  u_char *p;
672
673  for (i = 1, hi = *buf++, p = &s->gamma_map[component][0]; i <= 256; i++)
674    {
675      lo = hi;
676      hi = (i < 256) ? *buf++ : 2 * *(buf - 1) - *(buf - 2);
677      if (hi > 255)
678	hi = 255;
679      for (j = 0; j < 16; j++)		/* do a linear interpolation */
680	*p++ = (u_char) (lo + ((double) ((hi - lo) * j)) / 16.0 + 0.5);
681    }
682  return (SANE_STATUS_GOOD);
683}
684
685static SANE_Status
686set_parameters_fs2710 (SANE_Handle handle)
687{
688  CANON_Scanner *s = handle;
689  int i, j, shadow[4], hilite[4];
690  double x, b, c;
691
692  shadow[1] = s->ShadowR << 4;
693  shadow[2] = s->ShadowG << 4;
694  shadow[3] = s->ShadowB << 4;
695  hilite[1] = s->HiliteR << 4;
696  hilite[2] = s->HiliteG << 4;
697  hilite[3] = s->HiliteB << 4;
698  c = ((double) s->contrast) / 128.0;
699  b = ((double) (s->brightness - 128)) / 128.0;
700
701  for (i = 1; i < 4; i++)
702    {
703      for (j = 0; j < 4096; j++)
704	{
705	  if (j <= shadow[i])
706	    s->gamma_map[i][j] = (u_char) ((s->brightness >= 128) ?
707	      2 * s->brightness - 256 : 0);
708	  else if (j < hilite[i])
709	    {
710	      x = ((double) (j - shadow[i]))
711		/ ((double) (hilite[i] - shadow[i]));
712	      /* first do the contrast correction */
713	      x = (x <= 0.5) ? 0.5 * pow (2 * x, c)
714		: 1.0 - 0.5 * pow (2 * (1.0 - x), c);
715	      x = pow (x, 0.5);		/* default gamma correction */
716	      x += b;			/* brightness correction */
717	      s->gamma_map[i][j] = (u_char) MAX (0, MIN (255,
718		(int) (255.0 * x)));
719	    }
720	  else
721	    s->gamma_map[i][j] = (u_char) ((s->brightness >= 128) ?
722	      255 : 2 * s->brightness);
723	}
724    }
725
726  return (SANE_STATUS_GOOD);
727}
728
729/**************************************************************************/
730