Moving non-Windows platform-specific code lower in the file again to avoid declaratio...
[freeglut] / src / mswin / freeglut_joystick_mswin.c
1 /*\r
2  * freeglut_joystick_mswin.c\r
3  *\r
4  * The Windows-specific mouse cursor related stuff.\r
5  *\r
6  * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.\r
7  * Written by John F. Fay, <fayjf@sourceforge.net>\r
8  * Creation date: Sat Jan 28, 2012\r
9  *\r
10  * Permission is hereby granted, free of charge, to any person obtaining a\r
11  * copy of this software and associated documentation files (the "Software"),\r
12  * to deal in the Software without restriction, including without limitation\r
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
14  * and/or sell copies of the Software, and to permit persons to whom the\r
15  * Software is furnished to do so, subject to the following conditions:\r
16  *\r
17  * The above copyright notice and this permission notice shall be included\r
18  * in all copies or substantial portions of the Software.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
23  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
24  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
25  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
26  */\r
27 \r
28 #include <GL/freeglut.h>\r
29 #include "../Common/freeglut_internal.h"\r
30 \r
31 \r
32 #if !defined(_WIN32_WCE)\r
33 #    include <windows.h>\r
34 #    include <mmsystem.h>\r
35 #    include <regstr.h>\r
36 \r
37 \r
38 \r
39 /* Inspired by\r
40    http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp\r
41  */\r
42 #  if FREEGLUT_LIB_PRAGMAS\r
43 #      pragma comment (lib, "advapi32.lib")\r
44 #  endif\r
45 \r
46 static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz )\r
47 {\r
48     char buffer [ 256 ];\r
49 \r
50     char OEMKey [ 256 ];\r
51 \r
52     HKEY  hKey;\r
53     DWORD dwcb;\r
54     LONG  lr;\r
55 \r
56     if ( joy->error )\r
57         return 0;\r
58 \r
59     /* Open .. MediaResources\CurrentJoystickSettings */\r
60     _snprintf ( buffer, sizeof(buffer), "%s\\%s\\%s",\r
61                 REGSTR_PATH_JOYCONFIG, joy->jsCaps.szRegKey,\r
62                 REGSTR_KEY_JOYCURR );\r
63 \r
64     lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);\r
65 \r
66     if ( lr != ERROR_SUCCESS ) return 0;\r
67 \r
68     /* Get OEM Key name */\r
69     dwcb = sizeof(OEMKey);\r
70 \r
71     /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */\r
72     _snprintf ( buffer, sizeof(buffer), "Joystick%d%s", joy->js_id + 1, REGSTR_VAL_JOYOEMNAME );\r
73 \r
74     lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb);\r
75     RegCloseKey ( hKey );\r
76 \r
77     if ( lr != ERROR_SUCCESS ) return 0;\r
78 \r
79     /* Open OEM Key from ...MediaProperties */\r
80     _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );\r
81 \r
82     lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey );\r
83 \r
84     if ( lr != ERROR_SUCCESS ) return 0;\r
85 \r
86     /* Get OEM Name */\r
87     dwcb = buf_sz;\r
88 \r
89     lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf,\r
90                              &dwcb );\r
91     RegCloseKey ( hKey );\r
92 \r
93     if ( lr != ERROR_SUCCESS ) return 0;\r
94 \r
95     return 1;\r
96 }\r
97 \r
98 \r
99 void fgPlatformJoystickOpen( SFG_Joystick* joy )\r
100 {\r
101         int i = 0;\r
102 \r
103     joy->js.dwFlags = JOY_RETURNALL;\r
104     joy->js.dwSize  = sizeof( joy->js );\r
105 \r
106     memset( &joy->jsCaps, 0, sizeof( joy->jsCaps ) );\r
107 \r
108     joy->error =\r
109         ( joyGetDevCaps( joy->js_id, &joy->jsCaps, sizeof( joy->jsCaps ) ) !=\r
110           JOYERR_NOERROR );\r
111 \r
112     if( joy->jsCaps.wNumAxes == 0 )\r
113     {\r
114         joy->num_axes = 0;\r
115         joy->error = GL_TRUE;\r
116     }\r
117     else\r
118     {\r
119         /* Device name from jsCaps is often "Microsoft PC-joystick driver",\r
120          * at least for USB.  Try to get the real name from the registry.\r
121          */\r
122         if ( ! fghJoystickGetOEMProductName( joy, joy->name,\r
123                                              sizeof( joy->name ) ) )\r
124         {\r
125             fgWarning( "JS: Failed to read joystick name from registry" );\r
126             strncpy( joy->name, joy->jsCaps.szPname, sizeof( joy->name ) );\r
127         }\r
128 \r
129         /* Windows joystick drivers may provide any combination of\r
130          * X,Y,Z,R,U,V,POV - not necessarily the first n of these.\r
131          */\r
132         if( joy->jsCaps.wCaps & JOYCAPS_HASPOV )\r
133         {\r
134             joy->num_axes = _JS_MAX_AXES;\r
135             joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0;  /* POV Y */\r
136             joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0;  /* POV X */\r
137         }\r
138         else\r
139             joy->num_axes = 6;\r
140 \r
141         joy->min[ 5 ] = ( float )joy->jsCaps.wVmin;\r
142         joy->max[ 5 ] = ( float )joy->jsCaps.wVmax;\r
143         joy->min[ 4 ] = ( float )joy->jsCaps.wUmin;\r
144         joy->max[ 4 ] = ( float )joy->jsCaps.wUmax;\r
145         joy->min[ 3 ] = ( float )joy->jsCaps.wRmin;\r
146         joy->max[ 3 ] = ( float )joy->jsCaps.wRmax;\r
147         joy->min[ 2 ] = ( float )joy->jsCaps.wZmin;\r
148         joy->max[ 2 ] = ( float )joy->jsCaps.wZmax;\r
149         joy->min[ 1 ] = ( float )joy->jsCaps.wYmin;\r
150         joy->max[ 1 ] = ( float )joy->jsCaps.wYmax;\r
151         joy->min[ 0 ] = ( float )joy->jsCaps.wXmin;\r
152         joy->max[ 0 ] = ( float )joy->jsCaps.wXmax;\r
153     }\r
154 \r
155     /* Guess all the rest judging on the axes extremals */\r
156     for( i = 0; i < joy->num_axes; i++ )\r
157     {\r
158         joy->center   [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f;\r
159         joy->dead_band[ i ] = 0.0f;\r
160         joy->saturate [ i ] = 1.0f;\r
161     }\r
162 }\r
163 \r
164 \r
165 \r
166 void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )\r
167 {\r
168     switch( ident )\r
169     {\r
170     case 0:\r
171         fgJoystick[ ident ]->js_id = JOYSTICKID1;\r
172         fgJoystick[ ident ]->error = GL_FALSE;\r
173         break;\r
174     case 1:\r
175         fgJoystick[ ident ]->js_id = JOYSTICKID2;\r
176         fgJoystick[ ident ]->error = GL_FALSE;\r
177         break;\r
178     default:\r
179         fgJoystick[ ident ]->num_axes = 0;\r
180         fgJoystick[ ident ]->error = GL_TRUE;\r
181         return;\r
182     }\r
183 }\r
184 \r
185 \r
186 \r
187 void fgPlatformJoystickClose ( int ident )\r
188 {\r
189     /* Do nothing special */\r
190 }\r
191 #endif\r
192 \r