4 * Copyright 2000 Shi Quan He <shiquan@cyberdude.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(twain);
34 HINSTANCE SANE_instance;
36 BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
38 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
42 case DLL_PROCESS_ATTACH: {
45 SANE_Int version_code;
46 status = sane_init (&version_code, NULL);
48 SANE_instance = hinstDLL;
49 DisableThreadLibraryCalls(hinstDLL);
52 case DLL_PROCESS_DETACH:
54 FIXME("calling sane_Exit()\n");
65 static TW_UINT16 SANE_GetIdentity( pTW_IDENTITY, pTW_IDENTITY);
66 static TW_UINT16 SANE_OpenDS( pTW_IDENTITY, pTW_IDENTITY);
69 TW_UINT16 SANE_SourceControlHandler (
75 TW_UINT16 twRC = TWRC_SUCCESS;
84 sane_close (activeDS.deviceHandle);
89 twRC = SANE_OpenDS( pOrigin, (pTW_IDENTITY)pData);
96 twRC = SANE_GetIdentity( pOrigin, (pTW_IDENTITY)pData);
107 twRC = SANE_CapabilityGet (pOrigin, pData);
110 twRC = SANE_CapabilityGetCurrent (pOrigin, pData);
113 twRC = SANE_CapabilityGetDefault (pOrigin, pData);
115 case MSG_QUERYSUPPORT:
116 twRC = SANE_CapabilityQuerySupport (pOrigin, pData);
119 twRC = SANE_CapabilityReset (pOrigin, pData);
122 twRC = SANE_CapabilitySet (pOrigin, pData);
126 FIXME("unrecognized opertion triplet\n");
130 case DAT_CUSTOMDSDATA:
134 twRC = SANE_CustomDSDataGet (pOrigin, pData);
137 twRC = SANE_CustomDSDataSet (pOrigin, pData);
147 /*case MSG_AUTOMATICCAPTUREDIRECTORY:
148 twRC = SANE_AutomaticCaptureDirectory
151 case MSG_CHANGEDIRECTORY:
152 twRC = SANE_ChangeDirectory (pOrigin, pData);
155 twRC = SANE_FileSystemCopy (pOrigin, pData);
157 case MSG_CREATEDIRECTORY:
158 twRC = SANE_CreateDirectory (pOrigin, pData);
161 twRC = SANE_FileSystemDelete (pOrigin, pData);
163 case MSG_FORMATMEDIA:
164 twRC = SANE_FormatMedia (pOrigin, pData);
167 twRC = SANE_FileSystemGetClose (pOrigin, pData);
169 case MSG_GETFIRSTFILE:
170 twRC = SANE_FileSystemGetFirstFile (pOrigin, pData);
173 twRC = SANE_FileSystemGetInfo (pOrigin, pData);
175 case MSG_GETNEXTFILE:
176 twRC = SANE_FileSystemGetNextFile (pOrigin, pData);
179 twRC = SANE_FileSystemRename (pOrigin, pData);
188 if (MSG == MSG_PROCESSEVENT)
189 twRC = SANE_ProcessEvent (pOrigin, pData);
195 if (MSG == MSG_PASSTHRU)
196 twRC = SANE_PassThrough (pOrigin, pData);
201 case DAT_PENDINGXFERS:
205 twRC = SANE_PendingXfersEndXfer (pOrigin, pData);
208 twRC = SANE_PendingXfersGet (pOrigin, pData);
211 twRC = SANE_PendingXfersReset (pOrigin, pData);
213 /*case MSG_STOPFEEDER:
214 twRC = SANE_PendingXfersStopFeeder (pOrigin, pData);
221 case DAT_SETUPFILEXFER:
225 twRC = SANE_SetupFileXferGet (pOrigin, pData);
228 twRC = SANE_SetupFileXferGetDefault (pOrigin, pData);
231 twRC = SANE_SetupFileXferReset (pOrigin, pData);
234 twRC = SANE_SetupFileXferSet (pOrigin, pData);
242 /*case DAT_SETUPFILEXFER2:
246 twRC = SANE_SetupFileXfer2Get (pOrigin, pData);
249 twRC = SANE_SetupFileXfer2GetDefault (pOrigin, pData);
252 twRC = SANE_SetupFileXfer2Reset (pOrigin, pData);
255 twRC = SANE_SetupFileXfer2Set (pOrigin, pData);
259 case DAT_SETUPMEMXFER:
261 twRC = SANE_SetupMemXferGet (pOrigin, pData);
268 twRC = SANE_GetDSStatus (pOrigin, pData);
273 case DAT_USERINTERFACE:
277 twRC = SANE_DisableDSUserInterface (pOrigin, pData);
280 twRC = SANE_EnableDSUserInterface (pOrigin, pData);
282 case MSG_ENABLEDSUIONLY:
283 twRC = SANE_EnableDSUIOnly (pOrigin, pData);
295 twRC = SANE_XferGroupGet (pOrigin, pData);
298 twRC = SANE_XferGroupSet (pOrigin, pData);
307 FIXME("code unknown: %d\n", DAT);
316 TW_UINT16 SANE_ImageGroupHandler (
317 pTW_IDENTITY pOrigin,
322 TW_UINT16 twRC = TWRC_SUCCESS;
328 twRC = SANE_CIEColorGet (pOrigin, pData);
333 case DAT_EXTIMAGEINFO:
335 twRC = SANE_ExtImageInfoGet (pOrigin, pData);
340 case DAT_GRAYRESPONSE:
344 twRC = SANE_GrayResponseReset (pOrigin, pData);
347 twRC = SANE_GrayResponseSet (pOrigin, pData);
351 activeDS.twCC = TWCC_BADPROTOCOL;
352 FIXME("unrecognized operation triplet\n");
356 case DAT_IMAGEFILEXFER:
358 twRC = SANE_ImageFileXferGet (pOrigin, pData);
365 twRC = SANE_ImageInfoGet (pOrigin, pData);
370 case DAT_IMAGELAYOUT:
374 twRC = SANE_ImageLayoutGet (pOrigin, pData);
377 twRC = SANE_ImageLayoutGetDefault (pOrigin, pData);
380 twRC = SANE_ImageLayoutReset (pOrigin, pData);
383 twRC = SANE_ImageLayoutSet (pOrigin, pData);
387 activeDS.twCC = TWCC_BADPROTOCOL;
388 ERR("unrecognized operation triplet\n");
393 case DAT_IMAGEMEMXFER:
395 twRC = SANE_ImageMemXferGet (pOrigin, pData);
400 case DAT_IMAGENATIVEXFER:
402 twRC = SANE_ImageNativeXferGet (pOrigin, pData);
407 case DAT_JPEGCOMPRESSION:
411 twRC = SANE_JPEGCompressionGet (pOrigin, pData);
414 twRC = SANE_JPEGCompressionGetDefault (pOrigin, pData);
417 twRC = SANE_JPEGCompressionReset (pOrigin, pData);
420 twRC = SANE_JPEGCompressionSet (pOrigin, pData);
424 activeDS.twCC = TWCC_BADPROTOCOL;
425 WARN("unrecognized operation triplet\n");
434 twRC = SANE_Palette8Get (pOrigin, pData);
437 twRC = SANE_Palette8GetDefault (pOrigin, pData);
440 twRC = SANE_Palette8Reset (pOrigin, pData);
443 twRC = SANE_Palette8Set (pOrigin, pData);
447 activeDS.twCC = TWCC_BADPROTOCOL;
448 WARN("unrecognized operation triplet\n");
452 case DAT_RGBRESPONSE:
456 twRC = SANE_RGBResponseReset (pOrigin, pData);
459 twRC = SANE_RGBResponseSet (pOrigin, pData);
463 activeDS.twCC = TWCC_BADPROTOCOL;
464 WARN("unrecognized operation triplet\n");
471 activeDS.twCC = TWCC_BADPROTOCOL;
472 FIXME("unrecognized DG type %d\n", DAT);
477 /* Main entry point for the TWAIN library */
479 DS_Entry ( pTW_IDENTITY pOrigin,
485 TW_UINT16 twRC = TWRC_SUCCESS; /* Return Code */
487 TRACE("(DG=%ld DAT=%d MSG=%d)\n", DG, DAT, MSG);
492 twRC = SANE_SourceControlHandler (pOrigin,DAT,MSG,pData);
495 twRC = SANE_ImageGroupHandler (pOrigin,DAT,MSG,pData);
498 FIXME("Audio group of controls not implemented yet.\n");
500 activeDS.twCC = TWCC_BADPROTOCOL;
508 /* Sane returns device names that are longer than the 32 bytes allowed
509 by TWAIN. However, it colon separates them, and the last bit is
510 the most interesting. So we use the last bit, and add a signature
511 to ensure uniqueness */
512 static void copy_sane_short_name(const char *in, char *out, size_t outsize)
517 if (strlen(in) <= outsize - 1)
523 for (p = in; *p; p++)
526 p = strrchr(in, ':');
532 if (strlen(p) > outsize - 7 - 1)
533 p += strlen(p) - (outsize - 7 - 1);
536 sprintf(out + strlen(out), "(%04X)", signature % 0x10000);
540 static const SANE_Device **sane_devlist;
543 detect_sane_devices() {
544 if (sane_devlist && sane_devlist[0]) return;
545 TRACE("detecting sane...\n");
546 if (sane_get_devices (&sane_devlist, SANE_FALSE) != SANE_STATUS_GOOD)
551 SANE_GetIdentity( pTW_IDENTITY pOrigin, pTW_IDENTITY self) {
552 static int cursanedev = 0;
554 detect_sane_devices();
555 if (!sane_devlist[cursanedev])
557 self->ProtocolMajor = TWON_PROTOCOLMAJOR;
558 self->ProtocolMinor = TWON_PROTOCOLMINOR;
559 copy_sane_short_name(sane_devlist[cursanedev]->name, self->ProductName, sizeof(self->ProductName) - 1);
560 lstrcpynA (self->Manufacturer, sane_devlist[cursanedev]->vendor, sizeof(self->Manufacturer) - 1);
561 lstrcpynA (self->ProductFamily, sane_devlist[cursanedev]->model, sizeof(self->ProductFamily) - 1);
564 if (!sane_devlist[cursanedev] ||
565 !sane_devlist[cursanedev]->model ||
566 !sane_devlist[cursanedev]->vendor ||
567 !sane_devlist[cursanedev]->name
569 cursanedev = 0; /* wrap to begin */
573 static TW_UINT16 SANE_OpenDS( pTW_IDENTITY pOrigin, pTW_IDENTITY self) {
577 detect_sane_devices();
578 if (!sane_devlist[0]) {
579 ERR("No scanners? We should not get to OpenDS?\n");
583 for (i=0; sane_devlist[i] && sane_devlist[i]->model; i++) {
586 /* To make string as short as above */
587 lstrcpynA(name, sane_devlist[i]->vendor, sizeof(name)-1);
588 if (strcmp(name, self->Manufacturer))
590 lstrcpynA(name, sane_devlist[i]->model, sizeof(name)-1);
591 if (strcmp(name, self->ProductFamily))
593 copy_sane_short_name(sane_devlist[i]->name, name, sizeof(name) - 1);
594 if (strcmp(name, self->ProductName))
598 if (!sane_devlist[i]) {
599 FIXME("Scanner not found? Using first one!\n");
602 status = sane_open(sane_devlist[i]->name,&activeDS.deviceHandle);
603 if (status == SANE_STATUS_GOOD) {
604 activeDS.currentState = 4;
605 activeDS.twCC = TWRC_SUCCESS;
608 FIXME("sane_open(%s): %s\n", sane_devlist[i]->name, sane_strstatus (status));