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
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(twain
);
36 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
37 TW_UINT16
TWAIN_CloseDS (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
43 TW_UINT16 twRC
= TWRC_SUCCESS
;
44 pTW_IDENTITY pIdentity
= (pTW_IDENTITY
) pData
;
45 activeDS
*currentDS
= NULL
, *prevDS
= NULL
;
47 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
49 for (currentDS
= activeSources
; currentDS
; currentDS
= currentDS
->next
)
51 if (currentDS
->identity
.Id
== pIdentity
->Id
)
57 /* Only valid to close a data source if it is in state 4 */
58 if (currentDS
->currentState
== 4)
60 sane_close (currentDS
->deviceHandle
);
61 /* remove the data source from active data source list */
63 prevDS
->next
= currentDS
->next
;
65 activeSources
= currentDS
->next
;
66 HeapFree (GetProcessHeap(), 0, currentDS
);
68 DSM_twCC
= TWCC_SUCCESS
;
73 DSM_twCC
= TWCC_SEQERROR
;
86 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
87 TW_UINT16
TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
93 TW_UINT16 twRC
= TWRC_SUCCESS
;
94 pTW_IDENTITY pSourceIdentity
= (pTW_IDENTITY
) pData
;
96 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
100 if ((sane_get_devices (&device_list
, SANE_FALSE
) != SANE_STATUS_GOOD
))
102 DSM_twCC
= TWCC_NODS
;
107 /* FIXME: the default device is not necessarily the first device. *
108 * Users should be able to choose the default device */
109 if (device_list
&& device_list
[0])
111 pSourceIdentity
->Id
= DSM_sourceId
++;
112 strcpy (pSourceIdentity
->ProductName
, device_list
[0]->name
);
113 strcpy (pSourceIdentity
->Manufacturer
, device_list
[0]->vendor
);
114 strcpy (pSourceIdentity
->ProductFamily
, device_list
[0]->model
);
115 pSourceIdentity
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
116 pSourceIdentity
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
119 DSM_twCC
= TWCC_SUCCESS
;
124 DSM_twCC
= TWCC_NODS
;
131 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
132 TW_UINT16
TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
135 DSM_twCC
= TWCC_NODS
;
138 TW_UINT16 twRC
= TWRC_SUCCESS
;
139 pTW_IDENTITY pSourceIdentity
= (pTW_IDENTITY
) pData
;
142 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
144 status
= sane_get_devices (&device_list
, SANE_FALSE
);
145 if (status
== SANE_STATUS_GOOD
)
149 TRACE("got: %s, %s, %s\n", device_list
[0]->name
, device_list
[0]->vendor
, device_list
[0]->model
);
150 pSourceIdentity
->Id
= DSM_sourceId
++;
151 strcpy (pSourceIdentity
->ProductName
, device_list
[0]->name
);
152 strcpy (pSourceIdentity
->Manufacturer
, device_list
[0]->vendor
);
153 strcpy (pSourceIdentity
->ProductFamily
, device_list
[0]->model
);
154 pSourceIdentity
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
155 pSourceIdentity
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
157 DSM_currentDevice
= 1;
159 DSM_twCC
= TWCC_SUCCESS
;
163 TRACE("got empty device list\n");
165 DSM_twCC
= TWCC_NODS
;
168 else if (status
== SANE_STATUS_NO_MEM
)
171 DSM_twCC
= TWCC_LOWMEMORY
;
175 WARN("sane_get_devices() failed: %s\n", sane_strstatus (status
));
177 DSM_twCC
= TWCC_NODS
;
184 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
185 TW_UINT16
TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
188 DSM_twCC
= TWCC_SUCCESS
;
189 return TWRC_ENDOFLIST
;
191 TW_UINT16 twRC
= TWRC_SUCCESS
;
192 pTW_IDENTITY pSourceIdentity
= (pTW_IDENTITY
) pData
;
194 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
196 if (device_list
&& device_list
[DSM_currentDevice
] &&
197 device_list
[DSM_currentDevice
]->name
&&
198 device_list
[DSM_currentDevice
]->vendor
&&
199 device_list
[DSM_currentDevice
]->model
)
201 pSourceIdentity
->Id
= DSM_sourceId
++;
202 strcpy (pSourceIdentity
->ProductName
, device_list
[DSM_currentDevice
]->name
);
203 strcpy (pSourceIdentity
->Manufacturer
, device_list
[DSM_currentDevice
]->vendor
);
204 strcpy (pSourceIdentity
->ProductFamily
, device_list
[DSM_currentDevice
]->model
);
205 pSourceIdentity
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
206 pSourceIdentity
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
207 DSM_currentDevice
++;
210 DSM_twCC
= TWCC_SUCCESS
;
214 DSM_twCC
= TWCC_SUCCESS
;
215 twRC
= TWRC_ENDOFLIST
;
222 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
223 TW_UINT16
TWAIN_OpenDS (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
226 DSM_twCC
= TWCC_NODS
;
229 TW_UINT16 twRC
= TWRC_SUCCESS
, i
= 0;
230 pTW_IDENTITY pIdentity
= (pTW_IDENTITY
) pData
;
234 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
236 if (DSM_currentState
!= 3)
238 DSM_twCC
= TWCC_SEQERROR
;
243 (sane_get_devices (&device_list
, SANE_FALSE
) != SANE_STATUS_GOOD
))
245 DSM_twCC
= TWCC_NODS
;
249 if (pIdentity
->ProductName
[0] != '\0')
251 /* Make sure the source to be opened exists in the device list */
252 for (i
= 0; device_list
[i
]; i
++)
254 if (strcmp (device_list
[i
]->name
, pIdentity
->ProductName
) == 0)
261 /* the source is found in the device list */
262 newSource
= HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS
));
265 status
= sane_open(device_list
[i
]->name
,&newSource
->deviceHandle
);
266 if (status
== SANE_STATUS_GOOD
)
268 /* Assign name and id for the opened data source */
269 strcpy (pIdentity
->ProductName
, device_list
[i
]->name
);
270 pIdentity
->Id
= DSM_sourceId
++;
271 /* add the data source to an internal active source list */
272 newSource
->next
= activeSources
;
273 newSource
->identity
.Id
= pIdentity
->Id
;
274 strcpy (newSource
->identity
.ProductName
, pIdentity
->ProductName
);
275 newSource
->currentState
= 4; /*transition into state 4*/
276 newSource
->twCC
= TWCC_SUCCESS
;
277 activeSources
= newSource
;
279 DSM_twCC
= TWCC_SUCCESS
;
284 DSM_twCC
= TWCC_OPERATIONERROR
;
290 DSM_twCC
= TWCC_LOWMEMORY
;
296 DSM_twCC
= TWCC_NODS
;
303 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
304 TW_UINT16
TWAIN_UserSelect (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
309 TW_UINT16 twRC
= TWRC_SUCCESS
;
311 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
313 /* FIXME: we should replace xscanimage with our own User Select UI */
314 system("xscanimage");
316 DSM_twCC
= TWCC_SUCCESS
;
321 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
322 TW_UINT16
TWAIN_CloseDSM (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
327 TW_UINT16 twRC
= TWRC_SUCCESS
;
328 activeDS
*currentDS
= activeSources
, *nextDS
;
330 TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
332 if (DSM_currentState
== 3)
335 DSM_initialized
= FALSE
;
337 DSM_currentState
= 2;
339 /* If there are data sources still open, close them now. */
340 while (currentDS
!= NULL
)
342 nextDS
= currentDS
->next
;
343 sane_close (currentDS
->deviceHandle
);
344 HeapFree (GetProcessHeap(), 0, currentDS
);
347 activeSources
= NULL
;
348 DSM_twCC
= TWCC_SUCCESS
;
353 DSM_twCC
= TWCC_SEQERROR
;
361 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
362 TW_UINT16
TWAIN_OpenDSM (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
367 TW_UINT16 twRC
= TWRC_SUCCESS
;
369 SANE_Int version_code
;
371 TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
373 if (DSM_currentState
== 2)
375 if (!DSM_initialized
)
377 DSM_initialized
= TRUE
;
378 status
= sane_init (&version_code
, NULL
);
380 DSM_currentDevice
= 0;
383 DSM_parentHWND
= *(TW_HANDLE
*)pData
;
384 DSM_currentState
= 3; /* transition to state 3 */
385 DSM_twCC
= TWCC_SUCCESS
;
390 /* operation invoked in invalid state */
391 DSM_twCC
= TWCC_SEQERROR
;
399 /* DG_CONTROL/DAT_STATUS/MSG_GET */
400 TW_UINT16
TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
402 pTW_STATUS pSourceStatus
= (pTW_STATUS
) pData
;
404 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
406 pSourceStatus
->ConditionCode
= DSM_twCC
;
407 DSM_twCC
= TWCC_SUCCESS
; /* clear the condition code */