1/* @configure_input@ */
2
3/*----------------------------------------------------------------------
4 * (C) 1998-2009 3Dconnexion. All rights reserved.
5 * Permission to use, copy, modify, and distribute this software for all
6 * purposes and without fees is hereby grated provided that this copyright
7 * notice appears in all copies.  Permission to modify this software is granted
8 * and 3Dconnexion will support such modifications only is said modifications are
9 * approved by 3Dconnexion.
10 *
11 */
12/*
13 * The module contains interface routines to the Si library routines contained
14 * in the associated Dynamic Link Library.  The DLL is loaded explicitly when
15 * Si is initialized.  When the DLL is loaded, the initialization routine finds
16 * the addresses of the routines that it exposes to the world.  Once this is
17 * done the library routines are used as if they were part of the original
18 * source code.
19 */
20
21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif /* HAVE_CONFIG_H */
24
25#ifdef HAVE_WIN32_API /* Only compile this file when the Win32 API is available */
26
27#define SPW_DEFINE_COPYRIGHT
28#define SPW_DEFINE_GLOBALS
29
30#include <windows.h>
31#include <Inventor/@Gui@/devices/spwinput_win32.h>
32
33
34/* DLL library name */
35
36static LPCTSTR DllLibrary = "siappdll";
37
38
39/* names of DLL variables used in DLL */
40
41static LPCSTR strDLLRetVal          = "SpwErrorVal";
42
43/*typedef enum SpwRetVal SpwReturnValue;*/
44/* Names of functions contained in DLL; used to find their addresses at load
45   time */
46
47static LPCSTR fnSiBeep              = "SiBeep";
48static LPCSTR fnSiInitialize        = "SiInitialize";
49static LPCSTR fnSiTerminate         = "SiTerminate";
50static LPCSTR fnSiGetDeviceID       = "SiGetDeviceID";
51static LPCSTR fnSiGetNumDevices     = "SiGetNumDevices";
52static LPCSTR fnSiDeviceIndex       = "SiDeviceIndex";
53static LPCSTR fnSiDispatch          = "SiDispatch";
54static LPCSTR fnSiIsSpaceWareEvent  = "SiIsSpaceWareEvent";
55static LPCSTR fnSiOpenWinInit       = "SiOpenWinInit";
56static LPCSTR fnSiOpen              = "SiOpen";
57static LPCSTR fnSiClose             = "SiClose";
58static LPCSTR fnSiGetEventWinInit   = "SiGetEventWinInit";
59static LPCSTR fnSiGetEvent          = "SiGetEvent";
60static LPCSTR fnSiRezero            = "SiRezero";
61static LPCSTR fnSiGrabDevice        = "SiGrabDevice";
62static LPCSTR fnSiReleaseDevice     = "SiReleaseDevice";
63static LPCSTR fnSiButtonPressed     = "SiButtonPressed";
64static LPCSTR fnSiButtonReleased    = "SiButtonReleased";
65static LPCSTR fnSiSetUIMode         = "SiSetUiMode";
66static LPCSTR fnSiGetDevicePort     = "SiGetDevicePort";
67static LPCSTR fnSiGetDriverInfo     = "SiGetDriverInfo";
68static LPCSTR fnSiGetLibraryInfo    = "SiGetLibraryInfo";
69static LPCSTR fnSiGetDeviceInfo     = "SiGetDeviceInfo";
70static LPCSTR fnSpwErrorString      = "SpwErrorString";
71
72/* DLL initialization status */
73static enum InitResult gInitStatus = NOT_LOADED;
74
75/* DLL handle */
76HINSTANCE ghDll;
77enum SpwRetVal SpwErrorVal;
78
79/* Device handle */
80SiHdl Spw_DeviceHandle = SI_NO_HANDLE;
81
82/* Check to see if we can open a device handle to the spaceball */
83int SPW_SpaceBallExistsWin32(void)
84{
85  SiOpenData oData;
86  SiOpenWinInit(&oData,NULL);
87  return (SiOpen("", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData) != SI_NO_HANDLE) ? TRUE : FALSE;
88}
89
90/* check if can open a handle to the spaceball, load the driver functions
91   and start receiving input from the spaceball */
92int SPW_CheckForSpaceballWin32(void * win)
93{
94  char classname[25];
95  SiOpenData oData;
96
97  if (Spw_DeviceHandle == SI_NO_HANDLE) {
98    if (SiInitialize() != SPW_DLL_LOAD_ERROR) {
99      GetClassName((HWND)win, classname, sizeof(classname));
100      SiOpenWinInit(&oData, (HWND)win);
101
102      Spw_DeviceHandle = SiOpen(classname, SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData);
103
104      if (Spw_DeviceHandle != SI_NO_HANDLE) {
105        SiSetUiMode(Spw_DeviceHandle, SI_UI_ALL_CONTROLS);
106        return TRUE;
107      }
108      else {
109        SiTerminate();
110        return FALSE;
111      }
112    }
113    else return FALSE;
114  }
115  else return TRUE;
116}
117
118/* translates a Win32 event to a SPW_InputEvent. */
119int SPW_TranslateEventWin32(MSG * msg, SPW_InputEvent * sbEvent)
120{
121  SiSpwEvent spwEvent;
122  SiGetEventData eventdata;
123
124  if (Spw_DeviceHandle != SI_NO_HANDLE) {
125
126    SiGetEventWinInit (&eventdata, msg->message, msg->wParam, msg->lParam);
127    if (SiGetEvent (Spw_DeviceHandle, 0, &eventdata, &spwEvent) == SI_IS_EVENT) {
128
129      int i;
130      switch(spwEvent.type) {
131        case SI_MOTION_EVENT:
132          sbEvent->type = SPW_InputMotionEvent;
133          for(i=0; i<6; i++) {
134            sbEvent->sData[i] = (short)spwEvent.u.spwData.mData[i];
135          }
136          break;
137        case SI_BUTTON_EVENT:
138          sbEvent->type = SPW_InputButtonPressEvent;
139          sbEvent->buttonState.pressed = (SiButtonPressed(&spwEvent) != SI_NO_BUTTON);
140          sbEvent->buttonState.released = (SiButtonReleased(&spwEvent) != SI_NO_BUTTON);
141          break;
142      }
143      return TRUE;
144    }
145  }
146  return FALSE;
147}
148
149/* Stop receiving input from the spaceball */
150void SPW_disableSpaceBallWin32(void)
151{
152  SiClose(Spw_DeviceHandle);
153  SiTerminate();
154  Spw_DeviceHandle = SI_NO_HANDLE;
155}
156
157
158/*-----------------------------------------------------------------------------
159 *
160 *  void __SiAppInitialize(void)
161 *
162 *  Args:
163 *    None
164 *
165 *  Return Value:
166 *    None
167 *
168 *  Description:
169 *    This function opens up the DLL library and, if successful, loads a
170 *  function pointer table with exported UAPI functions contained in the DLL.
171 *
172 *---------------------------------------------------------------------------*/
173int __SiAppInitialize(void)
174{
175   enum InitResult nResult;      /* intialization result code */
176   enum ErrorCode nErrorCode;    /* function return code */
177
178   /* attempt to load the DLL */
179   if ((ghDll = LoadLibrary (DllLibrary)) != NULL)
180      {
181      /* preset variables and hope for success */
182      nResult = LOADED;
183      nErrorCode = NO_DLL_ERROR;
184
185      /* load up the global variable used by the DLL to return error info */
186
187      if ((pDllSpwRetVal = (enum SpwRetVal *)
188                           GetProcAddress(ghDll, strDLLRetVal)) == NULL)
189         {
190         nResult = FAILED;
191         nErrorCode = DLL_VAR_LOAD_FAILURE;
192         }
193
194      /* load up function pointer table */
195      if ((pfnSiBeep = (PFNSI_BEEP)
196                           GetProcAddress(ghDll, fnSiBeep)) == NULL)
197         {
198         nResult = FAILED;
199         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
200         }
201
202      if ((pfnSiInit = (PFNSI_INIT)
203                           GetProcAddress(ghDll, fnSiInitialize)) == NULL)
204         {
205         nResult = FAILED;
206         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
207         }
208
209      if ((pfnSiTerminate = (PFNSI_TERMINATE)
210                           GetProcAddress(ghDll, fnSiTerminate)) == NULL)
211         {
212         nResult = FAILED;
213         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
214         }
215
216      if ((pfnSiGetNumDevices = (PFNSI_GETNUMDEVICES)
217                           GetProcAddress(ghDll, fnSiGetNumDevices)) == NULL)
218         {
219         nResult = FAILED;
220         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
221         }
222
223      if ((pfnSiGetDeviceID = (PFNSI_GETDEVICEID)
224                           GetProcAddress(ghDll, fnSiGetDeviceID)) == NULL)
225         {
226         nResult = FAILED;
227         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
228         }
229
230      if ((pfnSiDeviceIndex = (PFNSI_DEVICEINDEX)
231                           GetProcAddress(ghDll, fnSiDeviceIndex)) == NULL)
232         {
233         nResult = FAILED;
234         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
235         }
236
237      if ((pfnSiDispatch = (PFNSI_DISPATCH)
238                           GetProcAddress(ghDll, fnSiDispatch)) == NULL)
239         {
240         nResult = FAILED;
241         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
242         }
243
244      if ((pfnSiOpenWinInit = (PFNSI_OPENWININIT)
245                           GetProcAddress(ghDll, fnSiOpenWinInit)) == NULL)
246         {
247         nResult = FAILED;
248         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
249         }
250
251      if ((pfnSiOpen = (PFNSI_OPEN)
252                           GetProcAddress(ghDll, fnSiOpen)) == NULL)
253         {
254         nResult = FAILED;
255         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
256         }
257
258      if ((pfnSiClose = (PFNSI_CLOSE)
259                           GetProcAddress(ghDll, fnSiClose)) == NULL)
260         {
261         nResult = FAILED;
262         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
263         }
264
265      if ((pfnSiGetEventWinInit = (PFNSI_GETEVENTWININIT)
266                           GetProcAddress(ghDll, fnSiGetEventWinInit)) == NULL)
267         {
268         nResult = FAILED;
269         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
270         }
271
272      if ((pfnSiIsSpaceWareEvent = (PFNSI_ISSPACEWAREEVENT)
273                           GetProcAddress(ghDll, fnSiIsSpaceWareEvent)) == NULL)
274         {
275         nResult = FAILED;
276         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
277         }
278
279      if ((pfnSiGetEvent = (PFNSI_GETEVENT)
280                           GetProcAddress(ghDll, fnSiGetEvent)) == NULL)
281         {
282         nResult = FAILED;
283         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
284         }
285
286      if ((pfnSiRezero = (PFNSI_REZERO)
287                           GetProcAddress(ghDll, fnSiRezero)) == NULL)
288         {
289         nResult = FAILED;
290         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
291         }
292
293      if ((pfnSiGrabDevice = (PFNSI_GRABDEVICE)
294                           GetProcAddress(ghDll, fnSiGrabDevice)) == NULL)
295         {
296         nResult = FAILED;
297         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
298         }
299
300      if ((pfnSiReleaseDevice = (PFNSI_RELEASEDEVICE)
301                           GetProcAddress(ghDll, fnSiReleaseDevice)) == NULL)
302         {
303         nResult = FAILED;
304         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
305         }
306
307      if ((pfnSiButtonPressed = (PFNSI_BUTTONPRESSED)
308                           GetProcAddress(ghDll, fnSiButtonPressed)) == NULL)
309         {
310         nResult = FAILED;
311         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
312         }
313
314      if ((pfnSiButtonReleased = (PFNSI_BUTTONRELEASED)
315                           GetProcAddress(ghDll, fnSiButtonReleased)) == NULL)
316         {
317         nResult = FAILED;
318         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
319         }
320
321      if ((pfnSiSetUiMode = (PFNSI_SETUIMODE)
322                           GetProcAddress(ghDll, fnSiSetUIMode)) == NULL)
323         {
324         nResult = FAILED;
325         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
326         }
327
328      if ((pfnSiGetDevicePort = (PFNSI_GETDEVICEPORT)
329                           GetProcAddress(ghDll, fnSiGetDevicePort)) == NULL)
330         {
331         nResult = FAILED;
332         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
333         }
334
335      if ((pfnSiGetDriverInfo = (PFNSI_GETDRIVERINFO)
336                           GetProcAddress(ghDll, fnSiGetDriverInfo)) == NULL)
337         {
338         nResult = FAILED;
339         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
340         }
341
342      if ((pfnSiGetLibraryInfo = (PFNSI_GETLIBRARYINFO)
343                           GetProcAddress(ghDll, fnSiGetLibraryInfo)) == NULL)
344         {
345         nResult = FAILED;
346         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
347         }
348
349      if ((pfnSiGetDeviceInfo = (PFNSI_GETDEVICEINFO)
350                           GetProcAddress(ghDll, fnSiGetDeviceInfo)) == NULL)
351         {
352         nResult = FAILED;
353         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
354         }
355
356      if ((pfnSpwErrorString = (PFNSPW_ERRORSTRING)
357                           GetProcAddress(ghDll, fnSpwErrorString)) == NULL)
358         {
359         nResult = FAILED;
360         nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
361         }
362      }
363   else  /* couldn't load DLL */
364      {
365      nResult = FAILED;
366      nErrorCode = DLL_LOAD_FAILURE;
367      }
368
369   /* set the global variable */
370
371   gInitStatus = nResult;
372
373   return nErrorCode;
374}
375
376
377/*-----------------------------------------------------------------------------
378 *
379 * enum SpwRetVal SiInitialize (void)
380 *
381 * Args:
382 *
383 * Return Value:
384 *    SPW_NO_ERROR      No error
385 *    SPW_ERROR         Initialization error
386 *
387 * Description:
388 *    This function initializes the SpaceWare input library.  Since most input
389 *    functions require that the library be initialized, this function should
390 *    be called before any other input functions are called.
391 *
392 *---------------------------------------------------------------------------*/
393
394enum SpwRetVal
395SiInitialize(void)
396{
397   enum SpwRetVal tmpRetVal;  /* temporary return value */
398
399   if (gInitStatus != LOADED)
400      {
401      __SiAppInitialize();
402      if (gInitStatus == FAILED)
403         {
404         return SPW_DLL_LOAD_ERROR;
405         }
406      }
407
408   tmpRetVal = pfnSiInit();
409   SpwErrorVal = *pDllSpwRetVal;
410   return tmpRetVal;
411}
412
413/*-----------------------------------------------------------------------------
414 *
415 * void SiTerminate (void)
416 *
417 * Args:
418 *   None
419 *
420 * Return Value:
421 *   None
422 *
423 * Description:
424 *    This function must be called to properly shut down the SpaceWare input
425 *    library.  No other input functions (except SiInit) should be called
426 *    afterwards.
427 *
428 *---------------------------------------------------------------------------*/
429
430void
431SiTerminate(void)
432{
433   /* It is unlikely that the function table will not have been loaded by the
434      time this is called, but we'll cover the bases anyhow */
435   if (gInitStatus != LOADED)
436      {
437      SiInitialize();
438      if (gInitStatus == FAILED)
439         {
440         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
441         return;
442         }
443
444      /* if we weren't returning void, we'd do error handling here */
445      }
446
447   pfnSiTerminate();
448   SpwErrorVal = *pDllSpwRetVal;
449
450   /* Unload the DLL to prevent memory leaks */
451   FreeLibrary(ghDll);
452
453   /* change status in case someone reinitializes */
454   gInitStatus = NOT_LOADED;
455}
456
457/*-----------------------------------------------------------------------------
458 *
459 * int SiGetNumDevices (void)
460 *
461 * Args:
462 *
463 * Return Value:
464 *    If the SpaceWare input library is initialized, the number of devices is
465 *    returned and SpwErrorVal is set to SPW_NO_ERROR.  Otherwise, the return
466 *    code is -1 and SpwErrorVal is set to either SI_UNINITIALIZED or one of
467 *    the other standard error codes.
468 *
469 * Description:
470 *    This function returns the number of input devices detected by the
471 *    driver.
472 *
473 *---------------------------------------------------------------------------*/
474
475int
476SiGetNumDevices (void)
477{
478   int tmpRetVal;  /* temporary return value */
479
480   if (gInitStatus != LOADED)
481      {
482      SiInitialize();
483      if (gInitStatus == FAILED)
484         {
485         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
486         return -1;
487         }
488      }
489
490   tmpRetVal = pfnSiGetNumDevices();
491   SpwErrorVal = *pDllSpwRetVal;
492   return tmpRetVal;
493}
494
495/*-----------------------------------------------------------------------------
496 *
497 * SiDevID SiGetDeviceID (SiHdl hdl)
498 *
499 * Args:
500 *    hdl      (r/o) SpaceWare handle
501 *
502 * Return Value:
503 *    If there is no error, the device ID is returned and SpwErrorVal is set
504 *    to SPW_NO_ERROR.  Otherwise, the return value is SI_NO_DEVICE and
505 *    SpwErrorVal is set to either SI_BAD_HANDLE (if the SpaceWare handle is
506 *    invalid) or one of the other standard error codes.
507 *
508 * Description:
509 *    Given a SpaceWare handle, this function returns the ID of the
510 *    associated device.
511 *
512 *---------------------------------------------------------------------------*/
513
514SiDevID
515SiGetDeviceID (SiHdl hdl)
516{
517   SiDevID tmpRetVal;  /* temporary return value */
518
519   if (gInitStatus != LOADED)
520      {
521      SiInitialize();
522      if (gInitStatus == FAILED)
523         {
524         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
525         return SI_NO_DEVICE;
526         }
527      }
528
529   tmpRetVal = pfnSiGetDeviceID(hdl);
530   SpwErrorVal = *pDllSpwRetVal;
531   return tmpRetVal;
532}
533
534/*-----------------------------------------------------------------------------
535 *
536 * SiDevID SiDeviceIndex (int idx)
537 *
538 * Args:
539 *    idx   (r/o) Device index (zero relative)
540 *
541 * Return Value:
542 *    If there is no error, the device ID is returned and SpwErrorVal is set
543 *    to SPW_NO_ERROR.  Otherwise, the return value is SI_NO_DEVICE and
544 *    SpwErrorVal is set to either SPW_ERROR (if the device index is invalid),
545 *    SI_UNINITIALIZED, or SI_NO_DRIVER.
546 *
547 * Description:
548 *    Given a device index, SiDeviceIndex returns the associated device ID.
549 *    This routine is particularly useful with the function SiGetDevicePort.
550 *
551 *---------------------------------------------------------------------------*/
552
553SiDevID
554SiDeviceIndex (int idx)
555{
556   SiDevID tmpRetVal;  /* temporary return value */
557
558   if (gInitStatus != LOADED)
559      {
560      SiInitialize();
561      if (gInitStatus == FAILED)
562         {
563         SpwErrorVal = SPW_DLL_LOAD_ERROR;  /* global variable */
564         return SI_NO_DEVICE;
565         }
566      }
567
568   tmpRetVal = pfnSiDeviceIndex(idx);
569   SpwErrorVal = *pDllSpwRetVal;
570   return tmpRetVal;
571}
572
573/*-----------------------------------------------------------------------------
574 *
575 * int SiDispatch (SiHdl hdl, SiGetEventData *pData, SiSpwEvent *pEvent,
576 *    SiSpwHandlers *pHandlers)
577 *
578 * Args:
579 *    hdl         (r/o) SpaceWare handle
580 *    pData       (r/o) Pntr to platform specific data (as passed to SiGetEvent)
581 *    pEvent      (r/o) Pntr to SpaceWare event (as returned by SiGetEvent)
582 *    pHandlers   (r/o) Pntr to SpaceWare event handlers
583 *
584 * Return Value:
585 *    Value returned by called event handler or zero if handler not defined.
586 *
587 * Description:
588 *    Provided as a companion to SiGetEvent, this function calls the appro-
589 *    priate handler to process the SpaceWare event returned by SiGetEvent.
590 *    The SiSpwHandlers structure contains one handler for each event type.
591 *    An event type can be ignored by setting the func member of the appro-
592 *    priate SiEventHandler structure to NULL.  Unlike the handler for
593 *    SiGetEvent, there is no specific use for the function return value of
594 *    these handlers -- the interpretation is entirely the caller's.
595 *
596 *---------------------------------------------------------------------------*/
597
598int
599SiDispatch (SiHdl hdl, SiGetEventData *pData,
600                SiSpwEvent *pEvent, SiSpwHandlers *pDHandlers)
601{
602   int tmpRetVal;  /* temporary return value */
603
604   if (gInitStatus != LOADED)
605      {
606      SiInitialize();
607      if (gInitStatus == FAILED)
608         {
609         return 0;
610         }
611      }
612
613   tmpRetVal = pfnSiDispatch(hdl, pData, pEvent, pDHandlers);
614   SpwErrorVal = *pDllSpwRetVal;
615   return tmpRetVal;
616}
617
618/*-----------------------------------------------------------------------------
619 *
620 * void SiOpenWinInit (SiOpenData *pData, HWND hWnd)
621 *
622 * Args:
623 *    pData (w/o) Pointer to storage for returned platform specific data
624 *    hWnd  (r/o) Window handle
625 *
626 * Return Value:
627 *    Nothing
628 *
629 * Description:
630 *    This function initializes the Windows platform specific data for a
631 *    subsequent call to SiOpen.
632 *
633 *---------------------------------------------------------------------------*/
634
635void
636SiOpenWinInit (SiOpenData *pData, HWND hWnd)
637{
638   if (gInitStatus != LOADED)
639      {
640      SiInitialize();
641      if (gInitStatus == FAILED)
642         {
643         pData = NULL;
644         hWnd = NULL;
645         return;
646         }
647      }
648
649   pfnSiOpenWinInit(pData, hWnd);
650   SpwErrorVal = *pDllSpwRetVal;
651}
652
653/*-----------------------------------------------------------------------------
654 *
655 * SiHdl SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
656 *    SiOpenData *pData)
657 *
658 * Args:
659 *    pAppName (r/o) Pointer to application name
660 *    devID    (r/o) Device ID or SI_ANY_DEVICE
661 *    pTMask   (r/o) Pointer to device type mask or SI_NO_MASK
662 *    mode     (r/o) SpaceWare event retrieval method:  SI_EVENT or SI_POLL
663 *    pData    (r/o) Pointer to platform specific data if mode is SI_EVENT
664 *
665 * Return Value:
666 *    SpaceWare handle or SI_NO_HANDLE if error.  SpwErrorVal is set to one
667 *    of the following:
668 *
669 *    SPW_NO_ERROR      No error
670 *    SPW_ERROR         Device could not be opened
671 *    SI_BAD_ID         Invalid device ID
672 *    SI_BAD_VALUE      Invalid argument
673 *    SI_UNSUPPORTED    Specified retrieval method is unsupported
674 *
675 * Description:
676 *    SiOpen is called to open a device for input and (sometimes) output
677 *    access.  The device in which to open is indicated via the device ID
678 *    (devID) and a device type mask (pTMask).  If the ID of a particular
679 *    device is known, it is passed in devID.  If the ID is not known or the
680 *    application simply doesn't care which device is selected, devID is passed
681 *    as SI_ANY_DEVICE.
682 *
683 *    Irrespective of the device ID, the device type mask indicates which
684 *    device types are permitted.  The type may be constrained to particular
685 *    devices, classes, or any combination thereof.  The mask is created via
686 *    the function SiSetTypeMask (see the definition of that function for more
687 *    information).  If the application doesn't wish to constrain the selection
688 *    to any particular types or classes, pTMask may be passed as SI_NO_MASK.
689 *    This is the equivalent of passing a mask set to SI_ALL_TYPES.
690 *
691 *    The following table shows how a device is selected based on the device ID
692 *    and type mask.  In those cases where SI_ANY_DEVICE is specified, the
693 *    order in which the devices are searched is the same order as indexed by
694 *    the function SiDevIndex.
695 *
696 *    devID            pTMask          Device selected
697 *
698 *    SI_ANY_DEVICE    SI_NO_MASK      The first available device in the list.
699 *
700 *    A device ID      SI_NO_MASK      The device matching the specified ID if
701 *                                     it's available.
702 *
703 *    SI_ANY_DEVICE    A type mask     The first available device in the list
704 *                                     with a type or class that is specified
705 *                                     in the mask.
706 *
707 *    A device ID      A type mask     The device matching the specified ID if
708 *                                     its type or class matches one specified
709 *                                     in the mask and it's available.
710 *
711 *    Note that some SpaceWare implementations will run only if all of the
712 *    configured devices are attached and working properly.  Thus, all of the
713 *    devices are available.  Other implementations may run with some devices
714 *    not working.  These constitute unavailable devices.
715 *
716 *    The mode argument specifies how the application intends to retrieve
717 *    data from the device.  SI_EVENT indicates that the application should
718 *    be informed, via a system event message, whenever device data is
719 *    pending.  The message is acknowledged by a call to SiGetEvent. When
720 *    this mode is selected, pData points to the platform specific informa-
721 *    tion necessary for the API to generate system event messages.  The mode
722 *    SI_POLL indicates that the application will check for data from the
723 *    device by calling SiGetEvent regularly.  For this mode, pData is passed
724 *    as NULL.
725 *
726 *---------------------------------------------------------------------------*/
727
728SiHdl
729SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
730              SiOpenData *pData)
731{
732   SiHdl tmpRetVal;  /* temporary return value */
733
734   if (gInitStatus != LOADED)
735      {
736      SiInitialize();
737      if (gInitStatus == FAILED)
738         {
739         SpwErrorVal = SPW_DLL_LOAD_ERROR;
740         return NULL;
741         }
742      }
743
744   tmpRetVal = pfnSiOpen(pAppName, devID, pTMask, mode, pData);
745   SpwErrorVal = *pDllSpwRetVal;
746   return tmpRetVal;
747
748}
749
750/*-----------------------------------------------------------------------------
751 *
752 * enum SpwRetVal SiClose (SiHdl hdl)
753 *
754 * Args:
755 *    hdl   (r/o) SpaceWare handle
756 *
757 * Return Value:
758 *    SPW_NO_ERROR      No error
759 *    SPW_ERROR         Close error
760 *    SI_BAD_HANDL      Invalid SpaceWare handle
761 *
762 * Description:
763 *    This function closes a device.   Once closed, the SpaceWare handle is
764 *    no longer valid.
765 *
766 *---------------------------------------------------------------------------*/
767
768enum
769SpwRetVal SiClose (SiHdl hdl)
770{
771   enum SpwRetVal tmpRetVal;  /* temporary return value */
772
773   if (gInitStatus != LOADED)
774      {
775      SiInitialize();
776      if (gInitStatus == FAILED)
777         {
778         return SPW_DLL_LOAD_ERROR;
779         }
780      }
781
782   tmpRetVal = pfnSiClose(hdl);
783   SpwErrorVal = *pDllSpwRetVal;
784   return tmpRetVal;
785
786}
787
788/*-----------------------------------------------------------------------------
789 *
790 * SPWbool SiIsSpaceWareEvent (SiGetEventData *pData, SiHdl *pHdl)
791 *
792 * Args:
793 *    pData (r/o) Pointer to platform specific data
794 *    pHdl  (w/o) Pointer to storage for returned SpaceWare handle
795 *
796 * Return Value:
797 *    SPW_TRUE if pData refers to a SpaceWare event, otherwise SPW_FALSE.
798 *
799 * Description:
800 *    This function determines whether or not the data addressed by pData per-
801 *    tains to a SpaceWare event.  If so, the handle for which the event is
802 *    intended is returned.
803 *
804 * Notes:
805 *    NULL may be passed for pHdl if the return of the intended handle is not
806 *    required.
807 *
808 *---------------------------------------------------------------------------*/
809
810SPWbool
811SiIsSpaceWareEvent(SiGetEventData *pData, SiHdl *pHdl)
812{
813   SPWbool tmpRetVal;  /* temporary return value */
814
815   if (gInitStatus != LOADED)
816      {
817      SiInitialize();
818      if (gInitStatus == FAILED)
819         {
820         return SPW_FALSE;
821         }
822      }
823
824   tmpRetVal = pfnSiIsSpaceWareEvent(pData, pHdl);
825   SpwErrorVal = *pDllSpwRetVal;
826   return tmpRetVal;
827}
828
829/*-----------------------------------------------------------------------------
830 *
831 * void SiGetEventWinInit (SiGetEventData *pData,
832 *    UINT msg, WPARAM wParam, LPARAM lParam)
833 *
834 * Args:
835 *    pData    (w/o) Pointer to storage for returned platform specific data
836 *    msg      (r/o) Windows message
837 *    wParam   (r/o) Parameter #1
838 *    lParam   (r/o) Parameter #2
839 *
840 * Return Value:
841 *    Nothing
842 *
843 * Description:
844 *    This function initializes the Windows platform specific data for a
845 *    subsequent call to SiGetEvent.
846 *
847 *---------------------------------------------------------------------------*/
848
849void
850SiGetEventWinInit (SiGetEventData *pData, UINT msg, WPARAM wParam,
851                   LPARAM lParam)
852{
853   if (gInitStatus != LOADED)
854      {
855      SiInitialize();
856      if (gInitStatus == FAILED)
857         {
858         return;
859         }
860      }
861
862   pfnSiGetEventWinInit(pData, msg, wParam, lParam);
863   SpwErrorVal = *pDllSpwRetVal;
864}
865
866/*-----------------------------------------------------------------------------
867 *
868 * enum SpwRetVal SiGetEvent (SiHdl hdl, int flags,
869 *    SiGetEventData *pData, SiSpwEvent *pEvent)
870 *
871 * Args:
872 *    hdl      (r/o) SpaceWare handle
873 *    flags    (r/o) Processing flags
874 *    pData    (r/o) Pointer to platform specific data
875 *    pEvent   (w/o) Pointer to storage for returned SpaceWare event
876 *
877 * Return Value:
878 *    SI_BAD_HANDLE     Invalid SpaceWare handle
879 *    SI_NOT_EVENT      The event is not a SpaceWare event or no event pending
880 *    SI_IS_EVENT       The event is a SpaceWare event
881 *    SI_SKIP_EVENT     The event is a SpaceWare event but it should be skipped
882 *
883 * Description:
884 *    This function determines if device data is pending and if so, returns
885 *    the data as a SpaceWare event.  See the "SpaceWare Universal API"
886 *    specification for a complete description of this function.
887 *
888 *---------------------------------------------------------------------------*/
889
890enum SpwRetVal
891SiGetEvent (SiHdl hdl, int flags, SiGetEventData *pData,
892                           SiSpwEvent *pEvent)
893{
894   enum SpwRetVal tmpRetVal;  /* temporary return value */
895
896   if (gInitStatus != LOADED)
897      {
898      SiInitialize();
899      if (gInitStatus == FAILED)
900         {
901         return SPW_DLL_LOAD_ERROR;
902         }
903      }
904
905   tmpRetVal = pfnSiGetEvent(hdl, flags, pData, pEvent);
906   SpwErrorVal = *pDllSpwRetVal;
907   return tmpRetVal;
908}
909
910/*-----------------------------------------------------------------------------
911 *
912 * enum SpwRetVal SiBeep (SiHdl hdl, char *pString)
913 *
914 * Args:
915 *    hdl      (r/o) SpaceWare handle
916 *    pString  (r/o) Pointer to beep description string
917 *
918 * Return Value:
919 *    SPW_NO_ERROR      No error
920 *    SI_BAD_HANDLE     Invalid SpaceWare handle
921 *    SI_BAD_VALUE      Bad string
922 *
923 * Description:
924 *    If supported, this function causes the input device to emit a sequence
925 *    of tones and pauses.  Each character of the string represents either a
926 *    tone or a delay.  Lowercase letters [a-z] represent a tone, uppercase
927 *    letters [A-Z] represent a pause.  The closer the letter is to the
928 *    beginning of the alphabet the shorter the pause or tone ('a' or 'A' is
929 *    1/32 second, 'b' or 'B' is 2/32 second, etc).  Up to 14 characters in
930 *    a string are processed, additional characters are ignored.
931 *
932 *---------------------------------------------------------------------------*/
933
934enum SpwRetVal
935SiBeep(SiHdl hdl, char *pString)
936{
937   enum SpwRetVal tmpRetVal;  /* temporary return value */
938
939   if (gInitStatus != LOADED)
940      {
941      SiInitialize();
942      if (gInitStatus == FAILED)
943         {
944         return SPW_DLL_LOAD_ERROR;
945         }
946      }
947
948   tmpRetVal = pfnSiBeep(hdl, pString);
949   SpwErrorVal = *pDllSpwRetVal;
950   return tmpRetVal;
951}
952
953/*-----------------------------------------------------------------------------
954 *
955 * enum SpwRetVal SiRezero (SiHdl hdl)
956 *
957 * Args:
958 *    hdl   (r/o) SpaceWare handle
959 *
960 * Return Value:
961 *    SPW_NO_ERROR      No error
962 *    SI_BAD_HANDLE     Invalid SpaceWare handle
963 *
964 * Description:
965 *    This function causes the input device's current setting to be defined
966 *    as the rest position.  Movement away from this position will cause
967 *    motion events. This can be used to eliminate drift or to set up a
968 *    constant motion.
969 *
970 *---------------------------------------------------------------------------*/
971
972enum SpwRetVal
973SiRezero (SiHdl hdl)
974{
975   enum SpwRetVal tmpRetVal;  /* temporary return value */
976
977   if (gInitStatus != LOADED)
978      {
979      SiInitialize();
980      if (gInitStatus == FAILED)
981         {
982         return SPW_DLL_LOAD_ERROR;
983         }
984      }
985
986   tmpRetVal = pfnSiRezero(hdl);
987   SpwErrorVal = *pDllSpwRetVal;
988   return tmpRetVal;
989}
990
991/*-----------------------------------------------------------------------------
992 *
993 * enum SpwRetVal SiGrabDevice (SiHdl hdl, SPWbool exclusive)
994 *
995 * Args:
996 *    hdl         (r/o) SpaceWare handle
997 *    exclusive   (r/o) Exclusive grab flag
998 *
999 * Return Value:
1000 *    SPW_NO_ERROR      No error
1001 *    SPW_ERROR         Grab failed
1002 *    SI_BAD_HANDLE     Invalid SpaceWare handle
1003 *
1004 * Description:
1005 *    This function is used to "grab" or capture a device in multi-tasking
1006 *    environments.  For an exclusive capture, the application retains control
1007 *    of the device regardless of which window has the focus.  For a non-
1008 *    exclusive capture, the application retains control of the device only if
1009 *    no other application, sharing the same device, has the focus.  Some
1010 *    SpaceWare implementations only allow one non-exclusive grab.  Others
1011 *    allow multiple non-exclusive grabs and provide an interface for inter-
1012 *    actively selecting the current non-exclusive grab application.  An exclu-
1013 *    sive grab fails if another application has already exclusively captured
1014 *    the device.  A non-exclusive grab fails if the SpaceWare implementation
1015 *    only allows one non-exclusive grab and another application has already
1016 *    non-exclusively captured the device.  Note that an exclusive grab should
1017 *    be used sparingly if at all.
1018 *
1019 *---------------------------------------------------------------------------*/
1020
1021enum SpwRetVal
1022SiGrabDevice (SiHdl hdl, SPWbool exclusive)
1023{
1024   enum SpwRetVal tmpRetVal;  /* temporary return value */
1025
1026   if (gInitStatus != LOADED)
1027      {
1028      SiInitialize();
1029      if (gInitStatus == FAILED)
1030         {
1031         return SPW_DLL_LOAD_ERROR;
1032         }
1033      }
1034
1035   tmpRetVal = pfnSiGrabDevice(hdl, exclusive);
1036   SpwErrorVal = *pDllSpwRetVal;
1037   return tmpRetVal;
1038}
1039
1040/*-----------------------------------------------------------------------------
1041 *
1042 * enum SpwRetVal SiReleaseDevice (SiHdl hdl)
1043 *
1044 * Args:
1045 *    hdl   (r/o) SpaceWare handle
1046 *
1047 * Return Value:
1048 *    SPW_NO_ERROR      No error
1049 *    SPW_ERROR         Device not captured
1050 *    SI_BAD_HANDLE     Invalid SpaceWare handle
1051 *
1052 * Description:
1053 *    This function releases a device that has been captured via the routine
1054 *    SiGrabDevice.  A captured device is automatically released when closed.
1055 *
1056 *---------------------------------------------------------------------------*/
1057
1058enum SpwRetVal
1059SiReleaseDevice (SiHdl hdl)
1060{
1061   enum SpwRetVal tmpRetVal;  /* temporary return value */
1062
1063   if (gInitStatus != LOADED)
1064      {
1065      SiInitialize();
1066      if (gInitStatus == FAILED)
1067         {
1068         return SPW_DLL_LOAD_ERROR;
1069         }
1070      }
1071
1072   tmpRetVal = pfnSiReleaseDevice(hdl);
1073   SpwErrorVal = *pDllSpwRetVal;
1074   return tmpRetVal;
1075}
1076
1077/*-----------------------------------------------------------------------------
1078 *
1079 * int SiButtonPressed (SiSpwEvent *pEvent)
1080 *
1081 * Args:
1082 *    pEvent   (r/o) Pointer to SpaceWare event
1083 *
1084 * Return Value:
1085 *    Button number or SI_NO_BUTTON if not a button or combo event or no
1086 *    button was pressed.  If it's not a button or combo event, SpwErrorVal
1087 *    is set to SPW_ERROR otherwise SpwErrorVal is SPW_NO_ERROR.
1088 *
1089 * Description:
1090 *    Given a button or combo event, this function returns the number of the
1091 *    button pressed.  In the event that multiple buttons are pressed, the
1092 *    lowest button number is returned.
1093 *
1094 *---------------------------------------------------------------------------*/
1095
1096int
1097SiButtonPressed (SiSpwEvent *pEvent)
1098{
1099   int tmpRetVal;  /* temporary return value */
1100
1101   if (gInitStatus != LOADED)
1102      {
1103      SiInitialize();
1104      if (gInitStatus == FAILED)
1105         {
1106         SpwErrorVal = SPW_DLL_LOAD_ERROR;
1107         return SI_NO_BUTTON;
1108         }
1109      }
1110
1111   tmpRetVal = pfnSiButtonPressed(pEvent);
1112   SpwErrorVal = *pDllSpwRetVal;
1113   return tmpRetVal;
1114}
1115
1116/*-----------------------------------------------------------------------------
1117 *
1118 * int SiButtonReleased (SiSpwEvent *pEvent)
1119 *
1120 * Args:
1121 *    pEvent   (r/o) Pointer to SpaceWare event
1122 *
1123 * Return Value:
1124 *    Button number or SI_NO_BUTTON if not a button or combo event or no
1125 *    button was released. If it's not a button or combo event, SpwErrorVal
1126 *    is set to SPW_ERROR otherwise SpwErrorVal is SPW_NO_ERROR.
1127 *
1128 * Description:
1129 *    Given a button or combo event, this function returns the number of the
1130 *    button released.  In the event that multiple buttons are released, the
1131 *    lowest button number is returned.
1132 *
1133 *---------------------------------------------------------------------------*/
1134
1135int
1136SiButtonReleased (SiSpwEvent *pEvent)
1137{
1138   int tmpRetVal;  /* temporary return value */
1139
1140   if (gInitStatus != LOADED)
1141      {
1142      SiInitialize();
1143      if (gInitStatus == FAILED)
1144         {
1145         SpwErrorVal = SPW_DLL_LOAD_ERROR;
1146         return SI_NO_BUTTON;
1147         }
1148      }
1149
1150   tmpRetVal = pfnSiButtonReleased(pEvent);
1151   SpwErrorVal = *pDllSpwRetVal;
1152   return tmpRetVal;
1153}
1154
1155/*-----------------------------------------------------------------------------
1156 *
1157 * enum SpwRetVal SiSetUiMode (SiHdl hdl, SPWuint32 mode)
1158 *
1159 * Args:
1160 *    hdl   (r/o) SpaceWare handle or SI_ALL_HANDLES
1161 *    mode  (r/o) UI mode
1162 *
1163 * Return Value:
1164 *    SPW_NO_ERROR      No error
1165 *    SI_BAD_HANDLE     Invalid SpaceWare handle
1166 *
1167 * Description:
1168 *    This function sets the current User Interface (UI) mode bit mask for a
1169 *    specified device.  If hdl is SI_ALL_HANDLES, the mask for each open
1170 *    device is set.  This option is useful if an app uses the same UI mode
1171 *    for more than one device.  Each set bit in the mask indicates that a
1172 *    particular feature is enabled.  The bits are defined as follows.
1173 *
1174 *       SI_UI_ALL_CONTROLS      All controls
1175 *       SI_UI_NO_CONTROLS       No controls
1176 *       SI_UI_FILTERS           Filter controls
1177 *       SI_UI_FUNC_BUTTONS      Function buttons
1178 *       SI_UI_RESET_BUTTONS     Reset buttons
1179 *       SI_UI_SENSITIVITY       Sensitivity control
1180 *       SI_UI_TUNING            Tuning control
1181 *       SI_UI_DIALOG_POPUP      Dialog popup button (on device)
1182 *
1183 *    Note that for SI_UI_ALL_CONTROLS, all bits are set; for SI_UI_NO_CONTROLS,
1184 *    no bits are set.
1185 *
1186 *---------------------------------------------------------------------------*/
1187
1188enum SpwRetVal
1189SiSetUiMode (SiHdl hdl, SPWuint32 mode)
1190{
1191   enum SpwRetVal tmpRetVal;  /* temporary return value */
1192
1193   if (gInitStatus != LOADED)
1194      {
1195      SiInitialize();
1196      if (gInitStatus == FAILED)
1197         {
1198         return SPW_DLL_LOAD_ERROR;
1199         }
1200      }
1201
1202   tmpRetVal = pfnSiSetUiMode(hdl, mode);
1203   SpwErrorVal = *pDllSpwRetVal;
1204   return tmpRetVal;
1205}
1206
1207/*-----------------------------------------------------------------------------
1208 *
1209 * enum SpwRetVal SiSetTypeMask (SiTypeMask *pTMask, int type1, ...,
1210 *    SI_END_ARGS)
1211 *
1212 * Args:
1213 *    pTMask   (w/o) Pointer to storage for returned device type mask
1214 *    type1    (r/o) First device type
1215 *    ...      (r/o) Additional device types
1216 *
1217 * Return Value:
1218 *    SPW_NO_ERROR   No error
1219 *
1220 * Description:
1221 *   This function provides compatibility with older software.
1222 *
1223 *---------------------------------------------------------------------------*/
1224
1225enum SpwRetVal
1226SiSetTypeMask (SiTypeMask *pTMask, int type1, ...)
1227{
1228   if (gInitStatus != LOADED)
1229      {
1230      SiInitialize();
1231      if (gInitStatus == FAILED)
1232         {
1233         return SPW_DLL_LOAD_ERROR;
1234         }
1235      }
1236
1237   /* stub function -> return a happy value */
1238   return SPW_NO_ERROR;
1239}
1240
1241/*-----------------------------------------------------------------------------
1242 *
1243 * enum SpwRetVal SiGetDevicePort (SiDevID devID, SiDevPort *pPort)
1244 *
1245 * Args:
1246 *    devID (r/o) Device ID
1247 *    pPort (w/o) Pointer to storage for returned device port info
1248 *
1249 * Return Value:
1250 *    SPW_NO_ERROR      No error
1251 *    SI_BAD_ID         Invalid device ID
1252 *
1253 * Description:
1254 *    The purpose of this function is to provide a correlation between the
1255 *    devices and the system ports to which they are connected.  Each call
1256 *    to SiGetDevicePort returns information for one device.
1257 *
1258 *---------------------------------------------------------------------------*/
1259
1260enum SpwRetVal
1261SiGetDevicePort (SiDevID devID, SiDevPort *pPort)
1262{
1263   enum SpwRetVal tmpRetVal;  /* temporary return value */
1264
1265   if (gInitStatus != LOADED)
1266      {
1267      SiInitialize();
1268      if (gInitStatus == FAILED)
1269         {
1270         return SPW_DLL_LOAD_ERROR;
1271         }
1272      }
1273
1274   tmpRetVal = pfnSiGetDevicePort(devID, pPort);
1275   SpwErrorVal = *pDllSpwRetVal;
1276   return tmpRetVal;
1277}
1278
1279/*-----------------------------------------------------------------------------
1280 *
1281 * enum SpwRetVal SiGetDriverInfo (SiVerInfo *pInfo)
1282 *
1283 * Args:
1284 *    pInfo (w/o) Pointer to storage for returned driver version info
1285 *
1286 * Return Value:
1287 *    SPW_NO_ERROR  No error
1288 *    SPW_ERROR     This version of the SpaceWare library does not use a driver
1289 *
1290 * Description:
1291 *    SiGetDriverInfo returns driver version information.
1292 *
1293 *---------------------------------------------------------------------------*/
1294
1295enum SpwRetVal
1296SiGetDriverInfo (SiVerInfo *pInfo)
1297{
1298   enum SpwRetVal tmpRetVal;  /* temporary return value */
1299
1300   if (gInitStatus != LOADED)
1301      {
1302      SiInitialize();
1303      if (gInitStatus == FAILED)
1304         {
1305         return SPW_DLL_LOAD_ERROR;
1306         }
1307      }
1308
1309   tmpRetVal = pfnSiGetDriverInfo(pInfo);
1310   SpwErrorVal = *pDllSpwRetVal;
1311   return tmpRetVal;
1312}
1313
1314/*-----------------------------------------------------------------------------
1315 *
1316 * void SiGetLibraryInfo (SiVerInfo *pInfo)
1317 *
1318 * Args:
1319 *    pInfo (w/o) Pointer to storage for returned library version info
1320 *
1321 * Return Value:
1322 *    Nothing.  SpwErrorVal is always set to SPW_NO_ERROR by this function.
1323 *
1324 * Description:
1325 *    SiGetLibraryInfo returns library version information.
1326 *
1327 *---------------------------------------------------------------------------*/
1328
1329void
1330SiGetLibraryInfo (SiVerInfo *pInfo)
1331{
1332   if (gInitStatus != LOADED)
1333      {
1334      SiInitialize();
1335      if (gInitStatus == FAILED)
1336         {
1337         pInfo = NULL;
1338         return;
1339         }
1340
1341      }
1342
1343   pfnSiGetLibraryInfo(pInfo);
1344   SpwErrorVal = *pDllSpwRetVal;
1345}
1346
1347/*-----------------------------------------------------------------------------
1348 *
1349 * enum SpwRetVal SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo)
1350 *
1351 * Args:
1352 *    hdl   (r/o) SpaceWare handle
1353 *    pInfo (w/o) Pointer to storage for returned device information
1354 *
1355 * Return Value:
1356 *    SPW_NO_ERROR      No error
1357 *    SI_BAD_HANDLE     Invalid SpaceWare handle
1358 *
1359 * Description:
1360 *    This function returns all sorts of information on the specified device.
1361 *
1362 *---------------------------------------------------------------------------*/
1363
1364enum SpwRetVal
1365SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo)
1366{
1367   enum SpwRetVal tmpRetVal;  /* temporary return value */
1368
1369   if (gInitStatus != LOADED)
1370      {
1371      SiInitialize();
1372      if (gInitStatus == FAILED)
1373         {
1374         return SPW_DLL_LOAD_ERROR;
1375         }
1376   }
1377
1378   tmpRetVal = pfnSiGetDeviceInfo(hdl, pInfo);
1379   SpwErrorVal = *pDllSpwRetVal;
1380   return tmpRetVal;
1381}
1382
1383/*-----------------------------------------------------------------------------
1384 *
1385 * char *SpwErrorString (enum SpwRetVal val)
1386 *
1387 * Parameters:
1388 *    val   (r/o) Error value
1389 *
1390 * Return:
1391 *    Pointer to string containing error message.
1392 *
1393 * Description:
1394 *    This function returns a pointer to the error message string associated
1395 *    with the given error value.  Note that the returned pointer points to
1396 *    static memory that is overridden each time SpwErrorString is called.
1397 *
1398 *---------------------------------------------------------------------------*/
1399
1400char *
1401SpwErrorString (enum SpwRetVal val)
1402{
1403
1404   if (gInitStatus != LOADED)
1405      {
1406      SiInitialize();
1407      if (gInitStatus == FAILED)
1408         {
1409         return NULL;
1410         }
1411      }
1412
1413   return (char *) pfnSpwErrorString(val);
1414}
1415
1416#endif /* HAVE_WIN32_API */
1417
1418
1419