1 /** \file joy-osx-hidutil.c
2 * \brief Mac OS X joystick support using HID Utility Library
3 *
4 * \author Christian Vogelgsang <chris@vogelgsang.org>
5 */
6
7 /*
8 * This file is part of VICE, the Versatile Commodore Emulator.
9 * See README for copyright notice.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 * 02111-1307 USA.
25 *
26 */
27
28 #define JOY_INTERNAL
29
30 #include "vice.h"
31
32 #ifdef MACOSX_SUPPORT
33
34 #include "joy.h"
35 #include "log.h"
36 #include "lib.h"
37
38 #ifdef HAS_JOYSTICK
39 #ifndef HAS_HIDMGR
40
41 /* ----- Helpers ----- */
42
is_joystick(pRecDevice device)43 static int is_joystick(pRecDevice device)
44 {
45 return (device->usage == kHIDUsage_GD_Joystick) ||
46 (device->usage == kHIDUsage_GD_GamePad);
47 }
48
count_joysticks(void)49 static int count_joysticks(void)
50 {
51 pRecDevice device;
52 int num_devices = 0;
53
54 /* iterate through all devices */
55 for (device = HIDGetFirstDevice();
56 device != NULL;
57 device = HIDGetNextDevice(device)) {
58 /* check if its a joystick or game pad device */
59 if (is_joystick(device)) {
60 num_devices ++;
61 }
62 }
63 return num_devices;
64 }
65
build_device_list(joy_hid_device_array_t * array)66 static void build_device_list(joy_hid_device_array_t *array)
67 {
68 pRecDevice device;
69 int num_devices = count_joysticks();
70
71 array->num_devices = num_devices;
72 array->devices = NULL;
73
74 if(num_devices == 0)
75 return;
76
77 /* alloc dev array */
78 joy_hid_device_t *devices = lib_malloc(sizeof(joy_hid_device_t) * num_devices);
79 if(devices == NULL) {
80 array->num_devices = 0;
81 return;
82 }
83 array->devices = devices;
84
85 /* iterate through all devices */
86 joy_hid_device_t *d = devices;
87 for (device = HIDGetFirstDevice();
88 device != NULL;
89 device = HIDGetNextDevice(device)) {
90 /* check if its a joystick or game pad device */
91 if (is_joystick(device)) {
92
93 d->internal_device = device;
94 d->vendor_id = (int)device->vendorID;
95 d->product_id = (int)device->productID;
96 d->serial = 0; /* will be filled in later */
97 d->product_name = device->product;
98
99 d++;
100 }
101 }
102 }
103
104 /* ----- API ----- */
105
joy_hidlib_init(void)106 int joy_hidlib_init(void)
107 {
108 return 0;
109 }
110
joy_hidlib_exit(void)111 void joy_hidlib_exit(void)
112 {
113 }
114
joy_hidlib_enumerate_devices(void)115 joy_hid_device_array_t *joy_hidlib_enumerate_devices(void)
116 {
117 /* build device list */
118 HIDBuildDeviceList(kHIDPage_GenericDesktop, 0);
119
120 /* no device list? -> no joysticks! */
121 if (!HIDHaveDeviceList()) {
122 return NULL;
123 }
124
125 /* alloc device array */
126 joy_hid_device_array_t *array = lib_malloc(sizeof(joy_hid_device_array_t));
127 if(array == NULL) {
128 /* cleanup device list */
129 HIDReleaseDeviceList();
130 return NULL;
131 }
132
133 build_device_list(array);
134
135 array->driver_name = "HIDUtils";
136 return array;
137 }
138
joy_hidlib_free_devices(joy_hid_device_array_t * devices)139 void joy_hidlib_free_devices(joy_hid_device_array_t *devices)
140 {
141 if(devices == NULL) {
142 return;
143 }
144
145 int num_devices = devices->num_devices;
146 int i;
147 for(i = 0; i<num_devices; i++) {
148 joy_hidlib_free_elements(&devices->devices[i]);
149 }
150
151 if(devices != NULL) {
152 lib_free(devices);
153 devices = NULL;
154 }
155
156 HIDReleaseDeviceList();
157 }
158
joy_hidlib_open_device(joy_hid_device_t * device)159 int joy_hidlib_open_device(joy_hid_device_t *device)
160 {
161 return 0;
162 }
163
joy_hidlib_close_device(joy_hid_device_t * device)164 void joy_hidlib_close_device(joy_hid_device_t *device)
165 {
166 }
167
joy_hidlib_enumerate_elements(joy_hid_device_t * device)168 int joy_hidlib_enumerate_elements(joy_hid_device_t *device)
169 {
170 pRecElement element;
171 int num_elements = 0;
172
173 pRecDevice d = device->internal_device;
174 for (element = HIDGetFirstDeviceElement(d, kHIDElementTypeInput);
175 element != NULL;
176 element = HIDGetNextDeviceElement(element, kHIDElementTypeInput)) {
177 num_elements++;
178 }
179
180 device->num_elements = num_elements;
181 if(num_elements == 0) {
182 device->elements = NULL;
183 return 0;
184 }
185
186 /* alloc my elements */
187 joy_hid_element_t *elements = lib_malloc(sizeof(joy_hid_element_t) * num_elements);
188 device->elements = elements;
189 if(elements == NULL) {
190 device->num_elements = 0;
191 return -1;
192 }
193
194 /* fill my elements */
195 joy_hid_element_t *e = elements;
196 for (element = HIDGetFirstDeviceElement(d, kHIDElementTypeInput);
197 element != NULL;
198 element = HIDGetNextDeviceElement(element, kHIDElementTypeInput)) {
199
200 e->usage_page = (int)element->usagePage;
201 e->usage = (int)element->usage;
202 e->min_pvalue = (int)element->min;
203 e->max_pvalue = (int)element->max;
204 e->min_lvalue = (int)element->scaledMin;
205 e->max_lvalue = (int)element->scaledMax;
206 e->internal_element = element;
207
208 e++;
209 }
210 return 0;
211 }
212
joy_hidlib_free_elements(joy_hid_device_t * device)213 void joy_hidlib_free_elements(joy_hid_device_t *device)
214 {
215 if(device == NULL) {
216 return;
217 }
218 if(device->elements) {
219 lib_free(device->elements);
220 device->elements = NULL;
221 }
222 }
223
joy_hidlib_get_value(joy_hid_device_t * device,joy_hid_element_t * element,int * value,int phys)224 int joy_hidlib_get_value(joy_hid_device_t *device,
225 joy_hid_element_t *element,
226 int *value, int phys)
227 {
228 pRecDevice d = device->internal_device;
229 pRecElement e = element->internal_element;
230 if (HIDIsValidElement(d, e)) {
231 *value = HIDGetElementValue(d, e);
232 return 0;
233 } else {
234 return -1;
235 }
236 }
237
238 #endif /* !HAS_HIDMGR */
239 #endif /* HAS_JOYSTICK */
240 #endif
241
242