2 * TWAIN32 Source Manager
4 * Copyright 2000 Corel Corporation
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
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(twain);
37 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
38 TW_UINT16 TWAIN_CloseDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
44 TW_UINT16 twRC = TWRC_SUCCESS;
45 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
46 activeDS *currentDS = NULL, *prevDS = NULL;
48 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
50 for (currentDS = activeSources; currentDS; currentDS = currentDS->next)
52 if (currentDS->identity.Id == pIdentity->Id)
58 /* Only valid to close a data source if it is in state 4 */
59 if (currentDS->currentState == 4)
61 sane_close (currentDS->deviceHandle);
62 /* remove the data source from active data source list */
64 prevDS->next = currentDS->next;
66 activeSources = currentDS->next;
67 HeapFree (GetProcessHeap(), 0, currentDS);
69 DSM_twCC = TWCC_SUCCESS;
74 DSM_twCC = TWCC_SEQERROR;
87 /* Sane returns device names that are longer than the 32 bytes allowed
88 by TWAIN. However, it colon separates them, and the last bit is
89 the most interesting. So we use the last bit, and add a signature
90 to ensure uniqueness */
92 static void copy_sane_short_name(const char *in, char *out, size_t outsize)
97 if (strlen(in) <= outsize - 1)
103 for (p = in; *p; p++)
106 p = strrchr(in, ':');
112 if (strlen(p) > outsize - 7 - 1)
113 p += strlen(p) - (outsize - 7 - 1);
116 sprintf(out + strlen(out), "(%04X)", signature % 0x10000);
121 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
122 TW_UINT16 TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin, TW_MEMREF pData)
125 DSM_twCC = TWCC_NODS;
128 TW_UINT16 twRC = TWRC_SUCCESS;
129 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
131 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
135 if ((sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
137 DSM_twCC = TWCC_NODS;
142 /* FIXME: the default device is not necessarily the first device. *
143 * Users should be able to choose the default device */
144 if (device_list && device_list[0])
146 pSourceIdentity->Id = DSM_sourceId ++;
147 copy_sane_short_name(device_list[0]->name, pSourceIdentity->ProductName, sizeof(pSourceIdentity->ProductName) - 1);
148 TRACE("got: %s (short [%s]), %s, %s\n", device_list[0]->name, pSourceIdentity->ProductName, device_list[0]->vendor, device_list[0]->model);
149 lstrcpynA (pSourceIdentity->Manufacturer, device_list[0]->vendor, sizeof(pSourceIdentity->Manufacturer) - 1);
150 lstrcpynA (pSourceIdentity->ProductFamily, device_list[0]->model, sizeof(pSourceIdentity->ProductFamily) - 1);
151 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
152 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
155 DSM_twCC = TWCC_SUCCESS;
161 DSM_twCC = TWCC_NODS;
168 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
169 TW_UINT16 TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin, TW_MEMREF pData)
172 DSM_twCC = TWCC_NODS;
175 TW_UINT16 twRC = TWRC_SUCCESS;
176 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
179 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
182 status = sane_get_devices (&device_list, SANE_FALSE);
183 if (status == SANE_STATUS_GOOD)
187 pSourceIdentity->Id = DSM_sourceId ++;
188 copy_sane_short_name(device_list[0]->name, pSourceIdentity->ProductName, sizeof(pSourceIdentity->ProductName) - 1);
189 TRACE("got: %s (short [%s]), %s, %s\n", device_list[0]->name, pSourceIdentity->ProductName, device_list[0]->vendor, device_list[0]->model);
190 lstrcpynA (pSourceIdentity->Manufacturer, device_list[0]->vendor, sizeof(pSourceIdentity->Manufacturer) - 1);
191 lstrcpynA (pSourceIdentity->ProductFamily, device_list[0]->model, sizeof(pSourceIdentity->ProductFamily) - 1);
192 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
193 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
195 DSM_currentDevice = 1;
197 DSM_twCC = TWCC_SUCCESS;
201 TRACE("got empty device list\n");
203 DSM_twCC = TWCC_NODS;
206 else if (status == SANE_STATUS_NO_MEM)
209 DSM_twCC = TWCC_LOWMEMORY;
213 WARN("sane_get_devices() failed: %s\n", sane_strstatus (status));
215 DSM_twCC = TWCC_NODS;
222 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
223 TW_UINT16 TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin, TW_MEMREF pData)
226 DSM_twCC = TWCC_SUCCESS;
227 return TWRC_ENDOFLIST;
229 TW_UINT16 twRC = TWRC_SUCCESS;
230 pTW_IDENTITY pSourceIdentity = (pTW_IDENTITY) pData;
232 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
234 if (device_list && device_list[DSM_currentDevice] &&
235 device_list[DSM_currentDevice]->name &&
236 device_list[DSM_currentDevice]->vendor &&
237 device_list[DSM_currentDevice]->model)
239 pSourceIdentity->Id = DSM_sourceId ++;
240 copy_sane_short_name(device_list[DSM_currentDevice]->name, pSourceIdentity->ProductName, sizeof(pSourceIdentity->ProductName) - 1);
241 TRACE("got: %s (short [%s]), %s, %s\n", device_list[DSM_currentDevice]->name, pSourceIdentity->ProductName, device_list[DSM_currentDevice]->vendor, device_list[DSM_currentDevice]->model);
242 lstrcpynA (pSourceIdentity->Manufacturer, device_list[DSM_currentDevice]->vendor, sizeof(pSourceIdentity->Manufacturer) - 1);
243 lstrcpynA (pSourceIdentity->ProductFamily, device_list[DSM_currentDevice]->model, sizeof(pSourceIdentity->ProductFamily) - 1);
244 pSourceIdentity->ProtocolMajor = TWON_PROTOCOLMAJOR;
245 pSourceIdentity->ProtocolMinor = TWON_PROTOCOLMINOR;
246 DSM_currentDevice ++;
249 DSM_twCC = TWCC_SUCCESS;
253 DSM_twCC = TWCC_SUCCESS;
254 twRC = TWRC_ENDOFLIST;
261 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
262 TW_UINT16 TWAIN_OpenDS (pTW_IDENTITY pOrigin, TW_MEMREF pData)
265 DSM_twCC = TWCC_NODS;
268 TW_UINT16 twRC = TWRC_SUCCESS, i = 0;
269 pTW_IDENTITY pIdentity = (pTW_IDENTITY) pData;
274 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
276 if (DSM_currentState != 3)
278 DSM_twCC = TWCC_SEQERROR;
283 (sane_get_devices (&device_list, SANE_FALSE) != SANE_STATUS_GOOD))
285 DSM_twCC = TWCC_NODS;
289 if (pIdentity->ProductName[0] != '\0')
291 /* Make sure the source to be opened exists in the device list */
292 for (i = 0; device_list[i]; i ++)
294 copy_sane_short_name(device_list[i]->name, shortname, sizeof(shortname) - 1);
295 if (strcmp (shortname, pIdentity->ProductName) == 0)
303 /* the source is found in the device list */
304 newSource = HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS));
307 status = sane_open(device_list[i]->name,&newSource->deviceHandle);
308 if (status == SANE_STATUS_GOOD)
310 /* Assign name and id for the opened data source */
311 lstrcpynA (pIdentity->ProductName, shortname, sizeof(pIdentity->ProductName) - 1);
312 pIdentity->Id = DSM_sourceId ++;
313 /* add the data source to an internal active source list */
314 newSource->next = activeSources;
315 newSource->identity.Id = pIdentity->Id;
316 strcpy (newSource->identity.ProductName, pIdentity->ProductName);
317 newSource->currentState = 4; /*transition into state 4*/
318 newSource->twCC = TWCC_SUCCESS;
319 activeSources = newSource;
321 DSM_twCC = TWCC_SUCCESS;
326 DSM_twCC = TWCC_OPERATIONERROR;
332 DSM_twCC = TWCC_LOWMEMORY;
338 DSM_twCC = TWCC_NODS;
345 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
346 TW_UINT16 TWAIN_UserSelect (pTW_IDENTITY pOrigin, TW_MEMREF pData)
351 TW_UINT16 twRC = TWRC_SUCCESS;
353 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
355 /* FIXME: we should replace xscanimage with our own User Select UI */
356 system("xscanimage");
358 DSM_twCC = TWCC_SUCCESS;
363 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
364 TW_UINT16 TWAIN_CloseDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
369 TW_UINT16 twRC = TWRC_SUCCESS;
370 activeDS *currentDS = activeSources, *nextDS;
372 TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
374 if (DSM_currentState == 3)
377 DSM_initialized = FALSE;
379 DSM_currentState = 2;
381 /* If there are data sources still open, close them now. */
382 while (currentDS != NULL)
384 nextDS = currentDS->next;
385 sane_close (currentDS->deviceHandle);
386 HeapFree (GetProcessHeap(), 0, currentDS);
389 activeSources = NULL;
390 DSM_twCC = TWCC_SUCCESS;
395 DSM_twCC = TWCC_SEQERROR;
403 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
404 TW_UINT16 TWAIN_OpenDSM (pTW_IDENTITY pOrigin, TW_MEMREF pData)
409 TW_UINT16 twRC = TWRC_SUCCESS;
411 SANE_Int version_code;
413 TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
415 if (DSM_currentState == 2)
417 if (!DSM_initialized)
419 DSM_initialized = TRUE;
420 status = sane_init (&version_code, NULL);
422 DSM_currentDevice = 0;
425 DSM_parentHWND = *(TW_HANDLE*)pData;
426 DSM_currentState = 3; /* transition to state 3 */
427 DSM_twCC = TWCC_SUCCESS;
432 /* operation invoked in invalid state */
433 DSM_twCC = TWCC_SEQERROR;
441 /* DG_CONTROL/DAT_STATUS/MSG_GET */
442 TW_UINT16 TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin, TW_MEMREF pData)
444 pTW_STATUS pSourceStatus = (pTW_STATUS) pData;
446 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
448 pSourceStatus->ConditionCode = DSM_twCC;
449 DSM_twCC = TWCC_SUCCESS; /* clear the condition code */