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
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(twain
);
34 /* DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS */
35 TW_UINT16
TWAIN_CloseDS (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
41 TW_UINT16 twRC
= TWRC_SUCCESS
;
42 pTW_IDENTITY pIdentity
= (pTW_IDENTITY
) pData
;
43 activeDS
*currentDS
= NULL
, *prevDS
= NULL
;
45 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_CLOSEDS\n");
47 for (currentDS
= activeSources
; currentDS
; currentDS
= currentDS
->next
)
49 if (currentDS
->identity
.Id
== pIdentity
->Id
)
55 /* Only valid to close a data source if it is in state 4 */
56 if (currentDS
->currentState
== 4)
58 sane_close (currentDS
->deviceHandle
);
59 /* remove the data source from active data source list */
61 prevDS
->next
= currentDS
->next
;
63 activeSources
= currentDS
->next
;
64 HeapFree (GetProcessHeap(), 0, currentDS
);
66 DSM_twCC
= TWCC_SUCCESS
;
71 DSM_twCC
= TWCC_SEQERROR
;
84 /* DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT */
85 TW_UINT16
TWAIN_IdentityGetDefault (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
91 TW_UINT16 twRC
= TWRC_SUCCESS
;
92 pTW_IDENTITY pSourceIdentity
= (pTW_IDENTITY
) pData
;
94 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETDEFAULT\n");
98 if ((sane_get_devices (&device_list
, SANE_FALSE
) != SANE_STATUS_GOOD
))
100 DSM_twCC
= TWCC_NODS
;
105 /* FIXME: the default device is not necessarily the first device. *
106 * Users should be able to choose the default device */
107 if (device_list
&& device_list
[0])
109 pSourceIdentity
->Id
= DSM_sourceId
++;
110 strcpy (pSourceIdentity
->ProductName
, device_list
[0]->name
);
111 strcpy (pSourceIdentity
->Manufacturer
, device_list
[0]->vendor
);
112 strcpy (pSourceIdentity
->ProductFamily
, device_list
[0]->model
);
113 pSourceIdentity
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
114 pSourceIdentity
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
117 DSM_twCC
= TWCC_SUCCESS
;
122 DSM_twCC
= TWCC_NODS
;
129 /* DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST */
130 TW_UINT16
TWAIN_IdentityGetFirst (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
133 DSM_twCC
= TWCC_NODS
;
136 TW_UINT16 twRC
= TWRC_SUCCESS
;
137 pTW_IDENTITY pSourceIdentity
;/* = (pTW_IDENTITY) pData;*/
140 TRACE ("DG_CONTROL/DAT_IDENTITY/MSG_GETFIRST\n");
142 status
= sane_get_devices (&device_list
, SANE_FALSE
);
143 if (status
== SANE_STATUS_GOOD
)
147 pSourceIdentity
->Id
= DSM_sourceId
++;
148 strcpy (pSourceIdentity
->ProductName
, device_list
[0]->name
);
149 strcpy (pSourceIdentity
->Manufacturer
, device_list
[0]->vendor
);
150 strcpy (pSourceIdentity
->ProductFamily
, device_list
[0]->model
);
151 pSourceIdentity
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
152 pSourceIdentity
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
154 DSM_currentDevice
= 1;
156 DSM_twCC
= TWCC_SUCCESS
;
158 else if (status
== SANE_STATUS_NO_MEM
)
161 DSM_twCC
= TWCC_LOWMEMORY
;
165 WARN("sane_get_devices() failed: %s\n", sane_strstatus (status
));
167 DSM_twCC
= TWCC_NODS
;
174 /* DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT */
175 TW_UINT16
TWAIN_IdentityGetNext (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
178 DSM_twCC
= TWCC_SUCCESS
;
179 return TWRC_ENDOFLIST
;
181 TW_UINT16 twRC
= TWRC_SUCCESS
;
182 pTW_IDENTITY pSourceIdentity
= (pTW_IDENTITY
) pData
;
184 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_GETNEXT\n");
186 if (device_list
&& device_list
[DSM_currentDevice
])
188 pSourceIdentity
->Id
= DSM_sourceId
++;
189 strcpy (pSourceIdentity
->ProductName
, device_list
[DSM_currentDevice
]->name
);
190 strcpy (pSourceIdentity
->Manufacturer
, device_list
[DSM_currentDevice
]->vendor
);
191 strcpy (pSourceIdentity
->ProductFamily
, device_list
[DSM_currentDevice
]->model
);
192 pSourceIdentity
->ProtocolMajor
= TWON_PROTOCOLMAJOR
;
193 pSourceIdentity
->ProtocolMinor
= TWON_PROTOCOLMINOR
;
194 DSM_currentDevice
++;
197 DSM_twCC
= TWCC_SUCCESS
;
201 DSM_twCC
= TWCC_SUCCESS
;
202 twRC
= TWRC_ENDOFLIST
;
209 /* DG_CONTROL/DAT_IDENTITY/MSG_OPENDS */
210 TW_UINT16
TWAIN_OpenDS (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
213 DSM_twCC
= TWCC_NODS
;
216 TW_UINT16 twRC
= TWRC_SUCCESS
, i
= 0;
217 pTW_IDENTITY pIdentity
= (pTW_IDENTITY
) pData
;
221 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_OPENDS\n");
223 if (DSM_currentState
!= 3)
225 DSM_twCC
= TWCC_SEQERROR
;
230 (sane_get_devices (&device_list
, SANE_FALSE
) != SANE_STATUS_GOOD
))
232 DSM_twCC
= TWCC_NODS
;
236 if (pIdentity
->ProductName
[0] != '\0')
238 /* Make sure the source to be open exists in the device list */
239 for (i
= 0; device_list
[i
]; i
++)
241 if (strcmp (device_list
[i
]->name
, pIdentity
->ProductName
) == 0)
248 /* the source is found in the device list */
249 newSource
= HeapAlloc (GetProcessHeap(), 0, sizeof (activeDS
));
252 status
= sane_open(device_list
[i
]->name
,&newSource
->deviceHandle
);
253 if (status
== SANE_STATUS_GOOD
)
255 /* Assign name and id for the opened data source */
256 strcpy (pIdentity
->ProductName
, device_list
[i
]->name
);
257 pIdentity
->Id
= DSM_sourceId
++;
258 /* add the data source to an internal active source list */
259 newSource
->next
= activeSources
;
260 newSource
->identity
.Id
= pIdentity
->Id
;
261 strcpy (newSource
->identity
.ProductName
, pIdentity
->ProductName
);
262 newSource
->currentState
= 4; /*transition into state 4*/
263 newSource
->twCC
= TWCC_SUCCESS
;
264 activeSources
= newSource
;
266 DSM_twCC
= TWCC_SUCCESS
;
271 DSM_twCC
= TWCC_OPERATIONERROR
;
277 DSM_twCC
= TWCC_LOWMEMORY
;
283 DSM_twCC
= TWCC_NODS
;
290 /* DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT */
291 TW_UINT16
TWAIN_UserSelect (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
296 TW_UINT16 twRC
= TWRC_SUCCESS
;
298 TRACE("DG_CONTROL/DAT_IDENTITY/MSG_USERSELECT\n");
300 /* FIXME: we should replace xscanimage with our own User Select UI */
301 system("xscanimage");
303 DSM_twCC
= TWCC_SUCCESS
;
308 /* DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM */
309 TW_UINT16
TWAIN_CloseDSM (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
314 TW_UINT16 twRC
= TWRC_SUCCESS
;
315 activeDS
*currentDS
= activeSources
, *nextDS
;
317 TRACE("DG_CONTROL/DAT_PARENT/MSG_CLOSEDSM\n");
319 if (DSM_currentState
== 3)
322 DSM_initialized
= FALSE
;
324 DSM_currentState
= 2;
326 /* If there are data sources still open, close them now. */
327 while (currentDS
!= NULL
)
329 nextDS
= currentDS
->next
;
330 sane_close (currentDS
->deviceHandle
);
331 HeapFree (GetProcessHeap(), 0, currentDS
);
334 activeSources
= NULL
;
335 DSM_twCC
= TWCC_SUCCESS
;
340 DSM_twCC
= TWCC_SEQERROR
;
348 /* DG_CONTROL/DAT_PARENT/MSG_OPENDSM */
349 TW_UINT16
TWAIN_OpenDSM (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
354 TW_UINT16 twRC
= TWRC_SUCCESS
;
356 SANE_Int version_code
;
358 TRACE("DG_CONTROL/DAT_PARENT/MSG_OPENDSM\n");
360 if (DSM_currentState
== 2)
362 if (!DSM_initialized
)
364 DSM_initialized
= TRUE
;
365 status
= sane_init (&version_code
, NULL
);
367 DSM_currentDevice
= 0;
370 DSM_parentHWND
= *(TW_HANDLE
*)pData
;
371 DSM_currentState
= 3; /* transition to state 3 */
372 DSM_twCC
= TWCC_SUCCESS
;
377 /* operation invoked in invalid state */
378 DSM_twCC
= TWCC_SEQERROR
;
386 /* DG_CONTROL/DAT_STATUS/MSG_GET */
387 TW_UINT16
TWAIN_GetDSMStatus (pTW_IDENTITY pOrigin
, TW_MEMREF pData
)
389 pTW_STATUS pSourceStatus
= (pTW_STATUS
) pData
;
391 TRACE ("DG_CONTROL/DAT_STATUS/MSG_GET\n");
393 pSourceStatus
->ConditionCode
= DSM_twCC
;
394 DSM_twCC
= TWCC_SUCCESS
; /* clear the condition code */