| @@ -1,88 +1,204 @@ | | | @@ -1,88 +1,204 @@ |
1 | $NetBSD: patch-src_joystick_bsd_SDL__sysjoystick.c,v 1.4 2015/02/25 12:48:34 jmcneill Exp $ | | 1 | $NetBSD: patch-src_joystick_bsd_SDL__sysjoystick.c,v 1.5 2015/03/03 19:14:04 jmcneill Exp $ |
2 | | | 2 | |
3 | --- src/joystick/bsd/SDL_sysjoystick.c.orig 2012-01-19 06:30:06.000000000 +0000 | | 3 | --- src/joystick/bsd/SDL_sysjoystick.c.orig 2012-01-19 06:30:06.000000000 +0000 |
4 | +++ src/joystick/bsd/SDL_sysjoystick.c | | 4 | +++ src/joystick/bsd/SDL_sysjoystick.c |
5 | @@ -77,7 +77,7 @@ | | 5 | @@ -77,7 +77,7 @@ |
6 | #include "../SDL_sysjoystick.h" | | 6 | #include "../SDL_sysjoystick.h" |
7 | #include "../SDL_joystick_c.h" | | 7 | #include "../SDL_joystick_c.h" |
8 | | | 8 | |
9 | -#define MAX_UHID_JOYS 4 | | 9 | -#define MAX_UHID_JOYS 4 |
10 | +#define MAX_UHID_JOYS 64 | | 10 | +#define MAX_UHID_JOYS 64 |
11 | #define MAX_JOY_JOYS 2 | | 11 | #define MAX_JOY_JOYS 2 |
12 | #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS) | | 12 | #define MAX_JOYS (MAX_UHID_JOYS + MAX_JOY_JOYS) |
13 | | | 13 | |
14 | @@ -148,9 +148,11 @@ static char *joydevnames[MAX_JOYS]; | | 14 | @@ -148,9 +148,11 @@ static char *joydevnames[MAX_JOYS]; |
15 | static int report_alloc(struct report *, struct report_desc *, int); | | 15 | static int report_alloc(struct report *, struct report_desc *, int); |
16 | static void report_free(struct report *); | | 16 | static void report_free(struct report *); |
17 | | | 17 | |
18 | -#if defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__) | | 18 | -#if defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__) |
19 | +#if defined(__FreeBSD__) && (__FreeBSD_kernel_version >= 900000) | | 19 | +#if defined(__FreeBSD__) && (__FreeBSD_kernel_version >= 900000) |
20 | +#define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) | | 20 | +#define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) |
21 | +#elif defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__) | | 21 | +#elif defined(USBHID_UCR_DATA) || defined(__FreeBSD_kernel__) |
22 | #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data) | | 22 | #define REP_BUF_DATA(rep) ((rep)->buf->ucr_data) |
23 | -#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)) | | 23 | -#elif (defined(__FREEBSD__) && (__FreeBSD_kernel_version > 800063)) |
24 | +#elif (defined(__FreeBSD__) && (__FreeBSD_kernel_version > 800063)) | | 24 | +#elif (defined(__FreeBSD__) && (__FreeBSD_kernel_version > 800063)) |
25 | #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) | | 25 | #define REP_BUF_DATA(rep) ((rep)->buf->ugd_data) |
26 | #else | | 26 | #else |
27 | #define REP_BUF_DATA(rep) ((rep)->buf->data) | | 27 | #define REP_BUF_DATA(rep) ((rep)->buf->data) |
28 | @@ -314,6 +316,38 @@ SDL_SYS_JoystickOpen(SDL_Joystick *joy) | | 28 | @@ -314,6 +316,45 @@ SDL_SYS_JoystickOpen(SDL_Joystick *joy) |
29 | #endif | | 29 | #endif |
30 | rep->rid = -1; /* XXX */ | | 30 | rep->rid = -1; /* XXX */ |
31 | } | | 31 | } |
32 | +#if defined(__NetBSD__) | | 32 | +#if defined(__NetBSD__) |
33 | + usb_device_descriptor_t udd; | | 33 | + usb_device_descriptor_t udd; |
34 | + struct usb_string_desc usd; | | 34 | + struct usb_string_desc usd; |
35 | + if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1) | | 35 | + if (ioctl(fd, USB_GET_DEVICE_DESC, &udd) == -1) { |
| | | 36 | + fprintf(stderr, "USB_GET_DEVICE_DESC failed: %s\n", strerror(errno)); |
36 | + goto desc_failed; | | 37 | + goto desc_failed; |
| | | 38 | + } |
37 | + | | 39 | + |
38 | + /* Get default language */ | | 40 | + /* Get default language */ |
39 | + usd.usd_string_index = USB_LANGUAGE_TABLE; | | 41 | + usd.usd_string_index = USB_LANGUAGE_TABLE; |
40 | + usd.usd_language_id = 0; | | 42 | + usd.usd_language_id = 0; |
41 | + if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) { | | 43 | + if (ioctl(fd, USB_GET_STRING_DESC, &usd) == -1 || usd.usd_desc.bLength < 4) { |
42 | + usd.usd_language_id = 0; | | 44 | + usd.usd_language_id = 0; |
43 | + } else { | | 45 | + } else { |
44 | + usd.usd_language_id = UGETW(usd.usd_desc.bString[0]); | | 46 | + usd.usd_language_id = UGETW(usd.usd_desc.bString[0]); |
45 | + } | | 47 | + } |
46 | + | | 48 | + |
47 | + usd.usd_string_index = udd.iProduct; | | 49 | + usd.usd_string_index = udd.iProduct; |
48 | + if (ioctl(fd, USB_GET_STRING_DESC, &usd) == 0) { | | 50 | + int error = ioctl(fd, USB_GET_STRING_DESC, &usd); |
| | | 51 | + if (error != 0 && usd.usd_language_id != 0) { |
| | | 52 | + usd.usd_language_id = 0; |
| | | 53 | + error = ioctl(fd, USB_GET_STRING_DESC, &usd); |
| | | 54 | + } |
| | | 55 | + if (error == 0) { |
49 | + char str[128]; | | 56 | + char str[128]; |
50 | + char *new_name = NULL; | | 57 | + char *new_name = NULL; |
51 | + int i; | | 58 | + int i; |
52 | + for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i < sizeof(str) - 1; i++) { | | 59 | + for (i = 0; i < (usd.usd_desc.bLength >> 1) - 1 && i < sizeof(str) - 1; i++) { |
53 | + str[i] = UGETW(usd.usd_desc.bString[i]); | | 60 | + str[i] = UGETW(usd.usd_desc.bString[i]); |
54 | + } | | 61 | + } |
55 | + str[i] = '\0'; | | 62 | + str[i] = '\0'; |
56 | + asprintf(&new_name, "%s @ %s", str, path); | | 63 | + asprintf(&new_name, "%s @ %s", str, path); |
57 | + if (new_name != NULL) { | | 64 | + if (new_name != NULL) { |
58 | + free(joydevnames[joy->index]); | | 65 | + free(joydevnames[joy->index]); |
59 | + joydevnames[joy->index] = new_name; | | 66 | + joydevnames[joy->index] = new_name; |
60 | + } | | 67 | + } |
61 | + } | | 68 | + } |
62 | +desc_failed: | | 69 | +desc_failed: |
63 | +#endif | | 70 | +#endif |
64 | if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) { | | 71 | if (report_alloc(rep, hw->repdesc, REPORT_INPUT) < 0) { |
65 | goto usberr; | | 72 | goto usberr; |
66 | } | | 73 | } |
67 | @@ -386,10 +420,21 @@ SDL_SYS_JoystickOpen(SDL_Joystick *joy) | | 74 | @@ -386,10 +427,21 @@ SDL_SYS_JoystickOpen(SDL_Joystick *joy) |
68 | if (hw->axis_map[i] > 0) | | 75 | if (hw->axis_map[i] > 0) |
69 | hw->axis_map[i] = joy->naxes++; | | 76 | hw->axis_map[i] = joy->naxes++; |
70 | | | 77 | |
71 | + if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) { | | 78 | + if (joy->naxes == 0 && joy->nbuttons == 0 && joy->nhats == 0 && joy->nballs == 0) { |
72 | + SDL_SetError("%s: Not a joystick, ignoring", hw->path); | | 79 | + SDL_SetError("%s: Not a joystick, ignoring", hw->path); |
73 | + goto usberr; | | 80 | + goto usberr; |
74 | + } | | 81 | + } |
75 | + | | 82 | + |
76 | usbend: | | 83 | usbend: |
77 | /* The poll blocks the event thread. */ | | 84 | /* The poll blocks the event thread. */ |
78 | fcntl(fd, F_SETFL, O_NONBLOCK); | | 85 | fcntl(fd, F_SETFL, O_NONBLOCK); |
79 | | | 86 | |
80 | +#ifdef __NetBSD__ | | 87 | +#ifdef __NetBSD__ |
81 | + /* Flush any pending events */ | | 88 | + /* Flush any pending events */ |
82 | + while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) | | 89 | + while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) |
83 | + ; | | 90 | + ; |
84 | +#endif | | 91 | +#endif |
85 | + | | 92 | + |
86 | return (0); | | 93 | return (0); |
87 | usberr: | | 94 | usberr: |
88 | close(hw->fd); | | 95 | close(hw->fd); |
| | | 96 | @@ -459,63 +511,62 @@ SDL_SYS_JoystickUpdate(SDL_Joystick *joy |
| | | 97 | |
| | | 98 | rep = &joy->hwdata->inreport; |
| | | 99 | |
| | | 100 | - if (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) != rep->size) { |
| | | 101 | - return; |
| | | 102 | - } |
| | | 103 | + while (read(joy->hwdata->fd, REP_BUF_DATA(rep), rep->size) == rep->size) { |
| | | 104 | #if defined(USBHID_NEW) || (defined(__FREEBSD__) && __FreeBSD_kernel_version >= 500111) || defined(__FreeBSD_kernel__) |
| | | 105 | - hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid); |
| | | 106 | + hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input, rep->rid); |
| | | 107 | #else |
| | | 108 | - hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); |
| | | 109 | + hdata = hid_start_parse(joy->hwdata->repdesc, 1 << hid_input); |
| | | 110 | #endif |
| | | 111 | - if (hdata == NULL) { |
| | | 112 | - fprintf(stderr, "%s: Cannot start HID parser\n", |
| | | 113 | - joy->hwdata->path); |
| | | 114 | - return; |
| | | 115 | - } |
| | | 116 | + if (hdata == NULL) { |
| | | 117 | + fprintf(stderr, "%s: Cannot start HID parser\n", |
| | | 118 | + joy->hwdata->path); |
| | | 119 | + continue; |
| | | 120 | + } |
| | | 121 | |
| | | 122 | - for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { |
| | | 123 | - switch (hitem.kind) { |
| | | 124 | - case hid_input: |
| | | 125 | - switch (HID_PAGE(hitem.usage)) { |
| | | 126 | - case HUP_GENERIC_DESKTOP: { |
| | | 127 | - unsigned usage = HID_USAGE(hitem.usage); |
| | | 128 | - int joyaxe = usage_to_joyaxe(usage); |
| | | 129 | - if (joyaxe >= 0) { |
| | | 130 | - naxe = joy->hwdata->axis_map[joyaxe]; |
| | | 131 | - /* scaleaxe */ |
| | | 132 | - v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
| | | 133 | - &hitem); |
| | | 134 | - v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; |
| | | 135 | - v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); |
| | | 136 | - if (v != joy->axes[naxe]) { |
| | | 137 | - SDL_PrivateJoystickAxis(joy, naxe, v); |
| | | 138 | + for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) { |
| | | 139 | + switch (hitem.kind) { |
| | | 140 | + case hid_input: |
| | | 141 | + switch (HID_PAGE(hitem.usage)) { |
| | | 142 | + case HUP_GENERIC_DESKTOP: { |
| | | 143 | + unsigned usage = HID_USAGE(hitem.usage); |
| | | 144 | + int joyaxe = usage_to_joyaxe(usage); |
| | | 145 | + if (joyaxe >= 0) { |
| | | 146 | + naxe = joy->hwdata->axis_map[joyaxe]; |
| | | 147 | + /* scaleaxe */ |
| | | 148 | + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
| | | 149 | + &hitem); |
| | | 150 | + v -= (hitem.logical_maximum + hitem.logical_minimum + 1)/2; |
| | | 151 | + v *= 32768/((hitem.logical_maximum - hitem.logical_minimum + 1)/2); |
| | | 152 | + if (v != joy->axes[naxe]) { |
| | | 153 | + SDL_PrivateJoystickAxis(joy, naxe, v); |
| | | 154 | + } |
| | | 155 | + } else if (usage == HUG_HAT_SWITCH) { |
| | | 156 | + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
| | | 157 | + &hitem); |
| | | 158 | + SDL_PrivateJoystickHat(joy, 0, |
| | | 159 | + hatval_to_sdl(v)-hitem.logical_minimum); |
| | | 160 | + } |
| | | 161 | + break; |
| | | 162 | } |
| | | 163 | - } else if (usage == HUG_HAT_SWITCH) { |
| | | 164 | - v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
| | | 165 | - &hitem); |
| | | 166 | - SDL_PrivateJoystickHat(joy, 0, |
| | | 167 | - hatval_to_sdl(v)-hitem.logical_minimum); |
| | | 168 | - } |
| | | 169 | - break; |
| | | 170 | - } |
| | | 171 | - case HUP_BUTTON: |
| | | 172 | - v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
| | | 173 | - &hitem); |
| | | 174 | - if (joy->buttons[nbutton] != v) { |
| | | 175 | - SDL_PrivateJoystickButton(joy, |
| | | 176 | - nbutton, v); |
| | | 177 | + case HUP_BUTTON: |
| | | 178 | + v = (Sint32)hid_get_data(REP_BUF_DATA(rep), |
| | | 179 | + &hitem); |
| | | 180 | + if (joy->buttons[nbutton] != v) { |
| | | 181 | + SDL_PrivateJoystickButton(joy, |
| | | 182 | + nbutton, v); |
| | | 183 | + } |
| | | 184 | + nbutton++; |
| | | 185 | + break; |
| | | 186 | + default: |
| | | 187 | + continue; |
| | | 188 | } |
| | | 189 | - nbutton++; |
| | | 190 | break; |
| | | 191 | default: |
| | | 192 | - continue; |
| | | 193 | + break; |
| | | 194 | } |
| | | 195 | - break; |
| | | 196 | - default: |
| | | 197 | - break; |
| | | 198 | } |
| | | 199 | + hid_end_parse(hdata); |
| | | 200 | } |
| | | 201 | - hid_end_parse(hdata); |
| | | 202 | |
| | | 203 | return; |
| | | 204 | } |