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