2 * Copyright 2000 Corel Corporation
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define NONAMELESSUNION
20 #define NONAMELESSSTRUCT
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(twain
);
34 static TW_UINT16
get_onevalue(pTW_CAPABILITY pCapability
, TW_UINT16
*type
, TW_UINT32
*value
)
36 if (pCapability
->hContainer
)
38 pTW_ONEVALUE pVal
= GlobalLock (pCapability
->hContainer
);
43 *type
= pVal
->ItemType
;
44 GlobalUnlock (pCapability
->hContainer
);
52 static TW_UINT16
set_onevalue(pTW_CAPABILITY pCapability
, TW_UINT16 type
, TW_UINT32 value
)
54 pCapability
->hContainer
= GlobalAlloc (0, sizeof(TW_ONEVALUE
));
56 if (pCapability
->hContainer
)
58 pTW_ONEVALUE pVal
= GlobalLock (pCapability
->hContainer
);
61 pCapability
->ConType
= TWON_ONEVALUE
;
62 pVal
->ItemType
= type
;
64 GlobalUnlock (pCapability
->hContainer
);
68 return TWCC_LOWMEMORY
;
71 static TW_UINT16
msg_set(pTW_CAPABILITY pCapability
, TW_UINT32
*val
)
73 if (pCapability
->ConType
== TWON_ONEVALUE
)
74 return get_onevalue(pCapability
, NULL
, val
);
76 FIXME("Partial Stub: MSG_SET only supports TW_ONEVALUE\n");
81 static TW_UINT16
msg_get_enum(pTW_CAPABILITY pCapability
, const TW_UINT32
*values
, int value_count
,
82 TW_UINT16 type
, TW_UINT32 current
, TW_UINT32 default_value
)
84 TW_ENUMERATION
*enumv
= NULL
;
89 pCapability
->ConType
= TWON_ENUMERATION
;
90 pCapability
->hContainer
= 0;
92 if (type
== TWTY_INT16
|| type
== TWTY_UINT16
)
93 pCapability
->hContainer
= GlobalAlloc (0, FIELD_OFFSET( TW_ENUMERATION
, ItemList
[value_count
* sizeof(TW_UINT16
)]));
95 if (type
== TWTY_INT32
|| type
== TWTY_UINT32
)
96 pCapability
->hContainer
= GlobalAlloc (0, FIELD_OFFSET( TW_ENUMERATION
, ItemList
[value_count
* sizeof(TW_UINT32
)]));
98 if (pCapability
->hContainer
)
99 enumv
= GlobalLock(pCapability
->hContainer
);
102 return TWCC_LOWMEMORY
;
104 enumv
->ItemType
= type
;
105 enumv
->NumItems
= value_count
;
107 p16
= (TW_UINT16
*) enumv
->ItemList
;
108 p32
= (TW_UINT32
*) enumv
->ItemList
;
109 for (i
= 0; i
< value_count
; i
++)
111 if (values
[i
] == current
)
112 enumv
->CurrentIndex
= i
;
113 if (values
[i
] == default_value
)
114 enumv
->DefaultIndex
= i
;
115 if (type
== TWTY_INT16
|| type
== TWTY_UINT16
)
117 if (type
== TWTY_INT32
|| type
== TWTY_UINT32
)
121 GlobalUnlock(pCapability
->hContainer
);
125 #ifdef SONAME_LIBSANE
126 static TW_UINT16
msg_get_range(pTW_CAPABILITY pCapability
, TW_UINT16 type
,
127 TW_UINT32 minval
, TW_UINT32 maxval
, TW_UINT32 step
, TW_UINT32 def
, TW_UINT32 current
)
129 TW_RANGE
*range
= NULL
;
131 pCapability
->ConType
= TWON_RANGE
;
132 pCapability
->hContainer
= 0;
134 pCapability
->hContainer
= GlobalAlloc (0, sizeof(*range
));
135 if (pCapability
->hContainer
)
136 range
= GlobalLock(pCapability
->hContainer
);
139 return TWCC_LOWMEMORY
;
141 range
->ItemType
= type
;
142 range
->MinValue
= minval
;
143 range
->MaxValue
= maxval
;
144 range
->StepSize
= step
;
145 range
->DefaultValue
= def
;
146 range
->CurrentValue
= current
;
148 GlobalUnlock(pCapability
->hContainer
);
153 static TW_UINT16
TWAIN_GetSupportedCaps(pTW_CAPABILITY pCapability
)
156 static const UINT16 supported_caps
[] = { CAP_SUPPORTEDCAPS
, CAP_XFERCOUNT
, CAP_UICONTROLLABLE
,
157 ICAP_XFERMECH
, ICAP_PIXELTYPE
, ICAP_UNITS
, ICAP_BITDEPTH
, ICAP_COMPRESSION
, ICAP_PIXELFLAVOR
,
158 ICAP_XRESOLUTION
, ICAP_YRESOLUTION
};
160 pCapability
->hContainer
= GlobalAlloc (0, FIELD_OFFSET( TW_ARRAY
, ItemList
[sizeof(supported_caps
)] ));
161 pCapability
->ConType
= TWON_ARRAY
;
163 if (pCapability
->hContainer
)
167 a
= GlobalLock (pCapability
->hContainer
);
168 a
->ItemType
= TWTY_UINT16
;
169 a
->NumItems
= sizeof(supported_caps
) / sizeof(supported_caps
[0]);
170 u
= (UINT16
*) a
->ItemList
;
171 for (i
= 0; i
< a
->NumItems
; i
++)
172 u
[i
] = supported_caps
[i
];
173 GlobalUnlock (pCapability
->hContainer
);
177 return TWCC_LOWMEMORY
;
182 static TW_UINT16
SANE_ICAPXferMech (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
184 static const TW_UINT32 possible_values
[] = { TWSX_NATIVE
, TWSX_MEMORY
};
186 TW_UINT16 twCC
= TWCC_BADCAP
;
188 TRACE("ICAP_XFERMECH\n");
192 case MSG_QUERYSUPPORT
:
193 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
194 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
198 twCC
= msg_get_enum(pCapability
, possible_values
, sizeof(possible_values
) / sizeof(possible_values
[0]),
199 TWTY_UINT16
, activeDS
.capXferMech
, TWSX_NATIVE
);
203 twCC
= msg_set(pCapability
, &val
);
204 if (twCC
== TWCC_SUCCESS
)
206 activeDS
.capXferMech
= (TW_UINT16
) val
;
207 FIXME("Partial Stub: XFERMECH set to %d, but ignored\n", val
);
212 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWSX_NATIVE
);
216 activeDS
.capXferMech
= TWSX_NATIVE
;
217 /* .. fall through intentional .. */
220 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, activeDS
.capXferMech
);
221 FIXME("Partial Stub: XFERMECH of %d not actually used\n", activeDS
.capXferMech
);
229 static TW_UINT16
SANE_CAPXferCount (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
232 TW_UINT16 twCC
= TWCC_BADCAP
;
234 TRACE("CAP_XFERCOUNT\n");
238 case MSG_QUERYSUPPORT
:
239 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
240 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
244 twCC
= set_onevalue(pCapability
, TWTY_INT16
, -1);
245 FIXME("Partial Stub: Reporting only support for transfer all\n");
249 twCC
= msg_set(pCapability
, &val
);
250 if (twCC
== TWCC_SUCCESS
)
251 FIXME("Partial Stub: XFERCOUNT set to %d, but ignored\n", val
);
255 twCC
= set_onevalue(pCapability
, TWTY_INT16
, -1);
259 /* .. fall through intentional .. */
262 twCC
= set_onevalue(pCapability
, TWTY_INT16
, -1);
268 #ifdef SONAME_LIBSANE
269 static BOOL
pixeltype_to_sane_mode(TW_UINT16 pixeltype
, SANE_String mode
, int len
)
271 SANE_String_Const m
= NULL
;
275 m
= SANE_VALUE_SCAN_MODE_GRAY
;
278 m
= SANE_VALUE_SCAN_MODE_COLOR
;
281 m
= SANE_VALUE_SCAN_MODE_LINEART
;
286 if (strlen(m
) >= len
)
291 static BOOL
sane_mode_to_pixeltype(SANE_String_Const mode
, TW_UINT16
*pixeltype
)
293 if (strcmp(mode
, SANE_VALUE_SCAN_MODE_LINEART
) == 0)
294 *pixeltype
= TWPT_BW
;
295 else if (memcmp(mode
, SANE_VALUE_SCAN_MODE_GRAY
, strlen(SANE_VALUE_SCAN_MODE_GRAY
)) == 0)
296 *pixeltype
= TWPT_GRAY
;
297 else if (strcmp(mode
, SANE_VALUE_SCAN_MODE_COLOR
) == 0)
298 *pixeltype
= TWPT_RGB
;
305 static TW_UINT16
sane_status_to_twcc(SANE_Status rc
)
309 case SANE_STATUS_GOOD
:
311 case SANE_STATUS_UNSUPPORTED
:
312 return TWCC_CAPUNSUPPORTED
;
313 case SANE_STATUS_JAMMED
:
314 return TWCC_PAPERJAM
;
315 case SANE_STATUS_NO_MEM
:
316 return TWCC_LOWMEMORY
;
317 case SANE_STATUS_ACCESS_DENIED
:
320 case SANE_STATUS_IO_ERROR
:
321 case SANE_STATUS_NO_DOCS
:
322 case SANE_STATUS_COVER_OPEN
:
323 case SANE_STATUS_EOF
:
324 case SANE_STATUS_INVAL
:
325 case SANE_STATUS_CANCELLED
:
326 case SANE_STATUS_DEVICE_BUSY
:
334 static TW_UINT16
SANE_ICAPPixelType (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
336 TW_UINT16 twCC
= TWCC_BADCAP
;
337 #ifdef SONAME_LIBSANE
338 TW_UINT32 possible_values
[3];
339 int possible_value_count
;
343 SANE_String_Const
*choices
;
344 char current_mode
[64];
345 TW_UINT16 current_pixeltype
= TWPT_BW
;
348 TRACE("ICAP_PIXELTYPE\n");
350 rc
= sane_option_probe_mode(activeDS
.deviceHandle
, &choices
, current_mode
, sizeof(current_mode
));
351 if (rc
!= SANE_STATUS_GOOD
)
353 ERR("Unable to retrieve mode from sane, ICAP_PIXELTYPE unsupported\n");
357 sane_mode_to_pixeltype(current_mode
, ¤t_pixeltype
);
359 /* Sane does not support a concept of a default mode, so we simply cache
360 * the first mode we find */
361 if (! activeDS
.PixelTypeSet
)
363 activeDS
.PixelTypeSet
= TRUE
;
364 activeDS
.defaultPixelType
= current_pixeltype
;
369 case MSG_QUERYSUPPORT
:
370 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
371 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
375 for (possible_value_count
= 0; choices
&& *choices
&& possible_value_count
< 3; choices
++)
378 if (sane_mode_to_pixeltype(*choices
, &pix
))
379 possible_values
[possible_value_count
++] = pix
;
381 twCC
= msg_get_enum(pCapability
, possible_values
, possible_value_count
,
382 TWTY_UINT16
, current_pixeltype
, activeDS
.defaultPixelType
);
386 twCC
= msg_set(pCapability
, &val
);
387 if (twCC
== TWCC_SUCCESS
)
389 TRACE("Setting pixeltype to %d\n", val
);
390 if (! pixeltype_to_sane_mode(val
, mode
, sizeof(mode
)))
391 return TWCC_BADVALUE
;
394 rc
= sane_option_set_str(activeDS
.deviceHandle
, "mode", mode
, &status
);
395 /* Some SANE devices use 'Grayscale' instead of the standard 'Gray' */
396 if (rc
== SANE_STATUS_INVAL
&& strcmp(mode
, SANE_VALUE_SCAN_MODE_GRAY
) == 0)
398 strcpy(mode
, "Grayscale");
399 rc
= sane_option_set_str(activeDS
.deviceHandle
, "mode", mode
, &status
);
401 if (rc
!= SANE_STATUS_GOOD
)
402 return sane_status_to_twcc(rc
);
403 if (status
& SANE_INFO_RELOAD_PARAMS
)
404 psane_get_parameters (activeDS
.deviceHandle
, &activeDS
.sane_param
);
409 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, activeDS
.defaultPixelType
);
413 current_pixeltype
= activeDS
.defaultPixelType
;
414 if (! pixeltype_to_sane_mode(current_pixeltype
, mode
, sizeof(mode
)))
415 return TWCC_BADVALUE
;
418 rc
= sane_option_set_str(activeDS
.deviceHandle
, "mode", mode
, &status
);
419 /* Some SANE devices use 'Grayscale' instead of the standard 'Gray' */
420 if (rc
== SANE_STATUS_INVAL
&& strcmp(mode
, SANE_VALUE_SCAN_MODE_GRAY
) == 0)
422 strcpy(mode
, "Grayscale");
423 rc
= sane_option_set_str(activeDS
.deviceHandle
, "mode", mode
, &status
);
425 if (rc
!= SANE_STATUS_GOOD
)
426 return sane_status_to_twcc(rc
);
427 if (status
& SANE_INFO_RELOAD_PARAMS
)
428 psane_get_parameters (activeDS
.deviceHandle
, &activeDS
.sane_param
);
430 /* .. fall through intentional .. */
433 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, current_pixeltype
);
434 TRACE("Returning current pixeltype of %d\n", current_pixeltype
);
443 static TW_UINT16
SANE_ICAPUnits (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
446 TW_UINT16 twCC
= TWCC_BADCAP
;
448 TRACE("ICAP_UNITS\n");
452 case MSG_QUERYSUPPORT
:
453 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
454 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
458 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWUN_INCHES
);
462 twCC
= msg_set(pCapability
, &val
);
463 if (twCC
== TWCC_SUCCESS
)
465 if (val
!= TWUN_INCHES
)
467 ERR("Sane supports only SANE_UNIT_DPI\n");
468 twCC
= TWCC_BADVALUE
;
475 /* .. fall through intentional .. */
478 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWUN_INCHES
);
486 static TW_UINT16
SANE_ICAPBitDepth(pTW_CAPABILITY pCapability
, TW_UINT16 action
)
488 TW_UINT16 twCC
= TWCC_BADCAP
;
489 #ifdef SONAME_LIBSANE
490 TW_UINT32 possible_values
[1];
492 TRACE("ICAP_BITDEPTH\n");
494 possible_values
[0] = activeDS
.sane_param
.depth
;
498 case MSG_QUERYSUPPORT
:
499 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
500 TWQC_GET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
);
504 twCC
= msg_get_enum(pCapability
, possible_values
, sizeof(possible_values
) / sizeof(possible_values
[0]),
505 TWTY_UINT16
, activeDS
.sane_param
.depth
, activeDS
.sane_param
.depth
);
509 /* .. Fall through intentional .. */
512 TRACE("Returning current bitdepth of %d\n", activeDS
.sane_param
.depth
);
513 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, activeDS
.sane_param
.depth
);
520 /* CAP_UICONTROLLABLE */
521 static TW_UINT16
SANE_CAPUiControllable(pTW_CAPABILITY pCapability
, TW_UINT16 action
)
523 TW_UINT16 twCC
= TWCC_BADCAP
;
525 TRACE("CAP_UICONTROLLABLE\n");
529 case MSG_QUERYSUPPORT
:
530 twCC
= set_onevalue(pCapability
, TWTY_INT32
, TWQC_GET
);
534 twCC
= set_onevalue(pCapability
, TWTY_BOOL
, TRUE
);
541 /* ICAP_COMPRESSION */
542 static TW_UINT16
SANE_ICAPCompression (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
544 static const TW_UINT32 possible_values
[] = { TWCP_NONE
};
546 TW_UINT16 twCC
= TWCC_BADCAP
;
548 TRACE("ICAP_COMPRESSION\n");
552 case MSG_QUERYSUPPORT
:
553 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
554 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
558 twCC
= msg_get_enum(pCapability
, possible_values
, sizeof(possible_values
) / sizeof(possible_values
[0]),
559 TWTY_UINT16
, TWCP_NONE
, TWCP_NONE
);
560 FIXME("Partial stub: We don't attempt to support compression\n");
564 twCC
= msg_set(pCapability
, &val
);
565 if (twCC
== TWCC_SUCCESS
)
566 FIXME("Partial Stub: COMPRESSION set to %d, but ignored\n", val
);
570 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWCP_NONE
);
574 /* .. fall through intentional .. */
577 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWCP_NONE
);
583 /* ICAP_XRESOLUTION, ICAP_YRESOLUTION */
584 static TW_UINT16
SANE_ICAPResolution (pTW_CAPABILITY pCapability
, TW_UINT16 action
, TW_UINT16 cap
)
586 TW_UINT16 twCC
= TWCC_BADCAP
;
587 #ifdef SONAME_LIBSANE
589 SANE_Int current_resolution
;
590 TW_FIX32
*default_res
;
591 const char *best_option_name
;
592 SANE_Int minval
, maxval
, quantval
;
596 TRACE("ICAP_%cRESOLUTION\n", cap
== ICAP_XRESOLUTION
? 'X' : 'Y');
598 /* Some scanners support 'x-resolution', most seem to just support 'resolution' */
599 if (cap
== ICAP_XRESOLUTION
)
601 best_option_name
= "x-resolution";
602 default_res
= &activeDS
.defaultXResolution
;
606 best_option_name
= "y-resolution";
607 default_res
= &activeDS
.defaultYResolution
;
609 if (sane_option_get_int(activeDS
.deviceHandle
, best_option_name
, ¤t_resolution
) != SANE_STATUS_GOOD
)
611 best_option_name
= "resolution";
612 if (sane_option_get_int(activeDS
.deviceHandle
, best_option_name
, ¤t_resolution
) != SANE_STATUS_GOOD
)
616 /* Sane does not support a concept of 'default' resolution, so we have to
617 * cache the resolution the very first time we load the scanner, and use that
619 if (cap
== ICAP_XRESOLUTION
&& ! activeDS
.XResolutionSet
)
621 default_res
->Whole
= current_resolution
;
622 default_res
->Frac
= 0;
623 activeDS
.XResolutionSet
= TRUE
;
626 if (cap
== ICAP_YRESOLUTION
&& ! activeDS
.YResolutionSet
)
628 default_res
->Whole
= current_resolution
;
629 default_res
->Frac
= 0;
630 activeDS
.YResolutionSet
= TRUE
;
635 case MSG_QUERYSUPPORT
:
636 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
637 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
641 sane_rc
= sane_option_probe_resolution(activeDS
.deviceHandle
, best_option_name
, &minval
, &maxval
, &quantval
);
642 if (sane_rc
!= SANE_STATUS_GOOD
)
645 twCC
= msg_get_range(pCapability
, TWTY_FIX32
,
646 minval
, maxval
, quantval
== 0 ? 1 : quantval
, default_res
->Whole
, current_resolution
);
650 twCC
= msg_set(pCapability
, &val
);
651 if (twCC
== TWCC_SUCCESS
)
654 memcpy(&f32
, &val
, sizeof(f32
));
655 sane_rc
= sane_option_set_int(activeDS
.deviceHandle
, best_option_name
, f32
.Whole
, &set_status
);
656 if (sane_rc
!= SANE_STATUS_GOOD
)
658 FIXME("Status of %d not expected or handled\n", sane_rc
);
661 else if (set_status
== SANE_INFO_INEXACT
)
662 twCC
= TWCC_CHECKSTATUS
;
667 twCC
= set_onevalue(pCapability
, TWTY_FIX32
, default_res
->Whole
);
671 sane_rc
= sane_option_set_int(activeDS
.deviceHandle
, best_option_name
, default_res
->Whole
, NULL
);
672 if (sane_rc
!= SANE_STATUS_GOOD
)
675 /* .. fall through intentional .. */
678 twCC
= set_onevalue(pCapability
, TWTY_FIX32
, current_resolution
);
685 /* ICAP_PIXELFLAVOR */
686 static TW_UINT16
SANE_ICAPPixelFlavor (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
688 static const TW_UINT32 possible_values
[] = { TWPF_CHOCOLATE
, TWPF_VANILLA
};
690 TW_UINT16 twCC
= TWCC_BADCAP
;
692 TRACE("ICAP_PIXELFLAVOR\n");
696 case MSG_QUERYSUPPORT
:
697 twCC
= set_onevalue(pCapability
, TWTY_INT32
,
698 TWQC_GET
| TWQC_SET
| TWQC_GETDEFAULT
| TWQC_GETCURRENT
| TWQC_RESET
);
702 twCC
= msg_get_enum(pCapability
, possible_values
, sizeof(possible_values
) / sizeof(possible_values
[0]),
703 TWTY_UINT16
, TWPF_CHOCOLATE
, TWPF_CHOCOLATE
);
707 twCC
= msg_set(pCapability
, &val
);
708 if (twCC
== TWCC_SUCCESS
)
710 FIXME("Stub: PIXELFLAVOR set to %d, but ignored\n", val
);
715 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWPF_CHOCOLATE
);
719 /* .. fall through intentional .. */
722 twCC
= set_onevalue(pCapability
, TWTY_UINT16
, TWPF_CHOCOLATE
);
729 TW_UINT16
SANE_SaneCapability (pTW_CAPABILITY pCapability
, TW_UINT16 action
)
731 TW_UINT16 twCC
= TWCC_CAPUNSUPPORTED
;
733 TRACE("capability=%d action=%d\n", pCapability
->Cap
, action
);
735 switch (pCapability
->Cap
)
737 case CAP_SUPPORTEDCAPS
:
738 if (action
== MSG_GET
)
739 twCC
= TWAIN_GetSupportedCaps(pCapability
);
741 twCC
= TWCC_BADVALUE
;
745 twCC
= SANE_CAPXferCount (pCapability
, action
);
748 case CAP_UICONTROLLABLE
:
749 twCC
= SANE_CAPUiControllable (pCapability
, action
);
753 twCC
= SANE_ICAPPixelType (pCapability
, action
);
757 twCC
= SANE_ICAPUnits (pCapability
, action
);
761 twCC
= SANE_ICAPBitDepth(pCapability
, action
);
765 twCC
= SANE_ICAPXferMech (pCapability
, action
);
768 case ICAP_PIXELFLAVOR
:
769 twCC
= SANE_ICAPPixelFlavor (pCapability
, action
);
772 case ICAP_COMPRESSION
:
773 twCC
= SANE_ICAPCompression(pCapability
, action
);
776 case ICAP_XRESOLUTION
:
777 twCC
= SANE_ICAPResolution(pCapability
, action
, pCapability
->Cap
);
780 case ICAP_YRESOLUTION
:
781 twCC
= SANE_ICAPResolution(pCapability
, action
, pCapability
->Cap
);
785 /* Twain specifies that you should return a 0 in response to QUERYSUPPORT,
786 * even if you don't formally support the capability */
787 if (twCC
== TWCC_CAPUNSUPPORTED
&& action
== MSG_QUERYSUPPORT
)
788 twCC
= set_onevalue(pCapability
, 0, TWTY_INT32
);
790 if (twCC
== TWCC_CAPUNSUPPORTED
)
791 TRACE("capability 0x%x/action=%d being reported as unsupported\n", pCapability
->Cap
, action
);