Mercurial > sdl-ios-xcode
comparison src/joystick/linux/SDL_sysjoystick.c @ 914:bbf8dcc8aed6
Date: Wed, 23 Jun 2004 17:05:33 -0400
From: Chris Nelson
Subject: [SDL] [Patch] WiseGroup MP-8800 / MP-8866 (PS2 Joystick)
In the current cvs version, SDL doesn't handle these Playstation2
controller => USB adapters correctly, in linux.
It will always assume that the maximum number of joysticks (2 in the
case of the MP-8866, 4 in the case of the 8800) are plugged in. This is
bad not only because it allows SDL to exaggerate the number of logical
joysticks, but primarily because the joystick axes are mapped
incorrectly, all over the place, such that the devices are effectively
unusable unless you have the maximum number of joysticks plugged in.
My changes to src/joystick/linux/SDL_sysjoystick.c build on another's
previous work (which was a special case for this very joystick,
actually), and fix both of these problems, as well as making the current
code a little more general, to allow for others to more easily drop in
code for quirky joysticks such as these.
I've tested this code under 2.6.7 as well as 2.4.24... Both work as
advertised (provided you load the JOYDEV linux code as a module,
otherwise they won't work at all, new code or old, but that's another
issue entirely).
Though this sounds horribly formal, you have my permission to distribute
all of my work on this issue under the LGPL. So there.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 25 Jul 2004 18:31:50 +0000 |
parents | b56dc586a5ef |
children | cb5e1d0cad31 |
comparison
equal
deleted
inserted
replaced
913:a7a8c282d62e | 914:bbf8dcc8aed6 |
---|---|
67 { "Saitek Saitek X45", 6, 1, 0 } | 67 { "Saitek Saitek X45", 6, 1, 0 } |
68 }; | 68 }; |
69 | 69 |
70 #ifndef NO_LOGICAL_JOYSTICKS | 70 #ifndef NO_LOGICAL_JOYSTICKS |
71 | 71 |
72 static struct joystick_logical_values { | 72 /* |
73 Some USB HIDs show up as a single joystick even though they actually | |
74 control 2 or more joysticks. | |
75 */ | |
76 /* | |
77 This code handles the MP-8800 (Quad) and MP-8866 (Dual), which can | |
78 be identified by their transparent blue design. It's quite trivial | |
79 to add other joysticks with similar quirky behavior. | |
80 -id | |
81 */ | |
82 | |
83 struct joystick_logical_mapping { | |
73 int njoy; | 84 int njoy; |
74 int nthing; | 85 int nthing; |
75 } joystick_logical_values[] = { | 86 }; |
76 | 87 |
77 /* +0 */ | 88 /* |
78 /* MP-8800 axes map - map to {logical joystick #, logical axis #} */ | 89 {logical joy, logical axis}, |
79 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},{1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, | 90 {logical joy, logical hat}, |
80 {3,0},{3,1},{3,2},{3,3},{0,4},{1,4},{2,4}, | 91 {logical joy, logical ball}, |
81 | 92 {logical joy, logical button} |
82 /* +19 */ | 93 */ |
83 /* MP-8800 hat map - map to {logical joystick #, logical hat #} */ | 94 |
84 {0,0},{1,0},{2,0},{3,0}, | 95 static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = { |
85 | 96 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5} |
86 /* +23 */ | 97 }; |
87 /* MP-8800 button map - map to {logical joystick #, logical button #} */ | 98 static struct joystick_logical_mapping mp88xx_1_logical_buttonmap[] = { |
99 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11} | |
100 }; | |
101 | |
102 static struct joystick_logical_mapping mp88xx_2_logical_axismap[] = { | |
103 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, | |
104 {1,2},{1,3},{0,4},{0,5},{1,4},{1,5} | |
105 }; | |
106 static struct joystick_logical_mapping mp88xx_2_logical_buttonmap[] = { | |
107 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, | |
108 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11} | |
109 }; | |
110 | |
111 static struct joystick_logical_mapping mp88xx_3_logical_axismap[] = { | |
112 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, | |
113 {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, | |
114 {0,4},{0,5},{1,4},{1,5},{2,4},{2,5} | |
115 }; | |
116 static struct joystick_logical_mapping mp88xx_3_logical_buttonmap[] = { | |
117 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, | |
118 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, | |
119 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11} | |
120 }; | |
121 | |
122 static struct joystick_logical_mapping mp88xx_4_logical_axismap[] = { | |
123 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, | |
124 {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, | |
125 {3,0},{3,1},{3,2},{3,3},{0,4},{0,5}, | |
126 {1,4},{1,5},{2,4},{2,5},{3,4},{3,5} | |
127 }; | |
128 static struct joystick_logical_mapping mp88xx_4_logical_buttonmap[] = { | |
88 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, | 129 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, |
89 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, | 130 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, |
90 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}, | 131 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}, |
91 {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11} | 132 {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11} |
92 }; | 133 }; |
93 | 134 |
94 static struct joystick_logical_layout { | 135 struct joystick_logical_layout { |
95 int naxes; | 136 int naxes; |
96 int nhats; | 137 int nhats; |
97 int nballs; | 138 int nballs; |
98 int nbuttons; | 139 int nbuttons; |
99 } joystick_logical_layout[] = { | 140 }; |
100 /* MP-8800 logical layout */ | 141 |
101 {5, 1, 0, 12}, | 142 static struct joystick_logical_layout mp88xx_1_logical_layout[] = { |
102 {5, 1, 0, 12}, | 143 {6, 0, 0, 12} |
103 {5, 1, 0, 12}, | 144 }; |
104 {4, 1, 0, 12} | 145 static struct joystick_logical_layout mp88xx_2_logical_layout[] = { |
146 {6, 0, 0, 12}, | |
147 {6, 0, 0, 12} | |
148 }; | |
149 static struct joystick_logical_layout mp88xx_3_logical_layout[] = { | |
150 {6, 0, 0, 12}, | |
151 {6, 0, 0, 12}, | |
152 {6, 0, 0, 12} | |
153 }; | |
154 static struct joystick_logical_layout mp88xx_4_logical_layout[] = { | |
155 {6, 0, 0, 12}, | |
156 {6, 0, 0, 12}, | |
157 {6, 0, 0, 12}, | |
158 {6, 0, 0, 12} | |
105 }; | 159 }; |
106 | 160 |
107 /* | 161 /* |
108 Some USB HIDs show up as a single joystick even though they actually | 162 This array sets up a means of mapping a single physical joystick to |
109 control 2 or more joysticks. This array sets up a means of mapping | 163 multiple logical joysticks. (djm) |
110 a single physical joystick to multiple logical joysticks. (djm) | |
111 | 164 |
112 njoys | 165 njoys |
113 the number of logical joysticks | 166 the number of logical joysticks |
114 | 167 |
115 layouts | 168 layouts |
116 an array of layout structures, one to describe each logical joystick | 169 an array of layout structures, one to describe each logical joystick |
117 | 170 |
118 axes, hats, balls, buttons | 171 axes, hats, balls, buttons |
119 arrays that map a physical thingy to a logical thingy | 172 arrays that map a physical thingy to a logical thingy |
120 */ | 173 */ |
121 static struct joystick_logicalmap { | 174 struct joystick_logicalmap { |
122 const char *name; | 175 const char *name; |
176 int nbuttons; | |
123 int njoys; | 177 int njoys; |
124 struct joystick_logical_layout *layouts; | 178 struct joystick_logical_layout *layout; |
125 struct joystick_logical_values *axes; | 179 struct joystick_logical_mapping *axismap; |
126 struct joystick_logical_values *hats; | 180 struct joystick_logical_mapping *hatmap; |
127 struct joystick_logical_values *balls; | 181 struct joystick_logical_mapping *ballmap; |
128 struct joystick_logical_values *buttons; | 182 struct joystick_logical_mapping *buttonmap; |
129 | 183 }; |
130 } joystick_logicalmap[] = { | 184 |
131 {"WiseGroup.,Ltd MP-8800 Quad USB Joypad", 4, joystick_logical_layout, | 185 static struct joystick_logicalmap joystick_logicalmap[] = { |
132 joystick_logical_values, joystick_logical_values+19, NULL, | 186 { |
133 joystick_logical_values+23} | 187 "WiseGroup.,Ltd MP-8866 Dual USB Joypad", |
188 12, | |
189 1, | |
190 mp88xx_1_logical_layout, | |
191 mp88xx_1_logical_axismap, | |
192 NULL, | |
193 NULL, | |
194 mp88xx_1_logical_buttonmap | |
195 }, | |
196 { | |
197 "WiseGroup.,Ltd MP-8866 Dual USB Joypad", | |
198 24, | |
199 2, | |
200 mp88xx_2_logical_layout, | |
201 mp88xx_2_logical_axismap, | |
202 NULL, | |
203 NULL, | |
204 mp88xx_2_logical_buttonmap | |
205 }, | |
206 { | |
207 "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | |
208 12, | |
209 1, | |
210 mp88xx_1_logical_layout, | |
211 mp88xx_1_logical_axismap, | |
212 NULL, | |
213 NULL, | |
214 mp88xx_1_logical_buttonmap | |
215 }, | |
216 { | |
217 "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | |
218 24, | |
219 2, | |
220 mp88xx_2_logical_layout, | |
221 mp88xx_2_logical_axismap, | |
222 NULL, | |
223 NULL, | |
224 mp88xx_2_logical_buttonmap | |
225 }, | |
226 { | |
227 "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | |
228 36, | |
229 3, | |
230 mp88xx_3_logical_layout, | |
231 mp88xx_3_logical_axismap, | |
232 NULL, | |
233 NULL, | |
234 mp88xx_3_logical_buttonmap | |
235 }, | |
236 { | |
237 "WiseGroup.,Ltd MP-8800 Quad USB Joypad", | |
238 48, | |
239 4, | |
240 mp88xx_4_logical_layout, | |
241 mp88xx_4_logical_axismap, | |
242 NULL, | |
243 NULL, | |
244 mp88xx_4_logical_buttonmap | |
245 } | |
134 }; | 246 }; |
135 | 247 |
136 /* find the head of a linked list, given a point in it | 248 /* find the head of a linked list, given a point in it |
137 */ | 249 */ |
138 #define SDL_joylist_head(i, start)\ | 250 #define SDL_joylist_head(i, start)\ |
204 | 316 |
205 static int CountLogicalJoysticks(int max) | 317 static int CountLogicalJoysticks(int max) |
206 { | 318 { |
207 register int i, j, k, ret, prev; | 319 register int i, j, k, ret, prev; |
208 const char* name; | 320 const char* name; |
321 int nbuttons, fd; | |
322 unsigned char n; | |
209 | 323 |
210 ret = 0; | 324 ret = 0; |
211 | 325 |
212 for(i = 0; i < max; i++) { | 326 for(i = 0; i < max; i++) { |
213 name = SDL_SYS_JoystickName(i); | 327 name = SDL_SYS_JoystickName(i); |
328 | |
329 fd = open(SDL_joylist[i].fname, O_RDONLY, 0); | |
330 if ( fd >= 0 ) { | |
331 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) { | |
332 nbuttons = -1; | |
333 } else { | |
334 nbuttons = n; | |
335 } | |
336 close(fd); | |
337 } | |
338 else { | |
339 nbuttons=-1; | |
340 } | |
214 | 341 |
215 if (name) { | 342 if (name) { |
216 for(j = 0; j < SDL_TABLESIZE(joystick_logicalmap); j++) { | 343 for(j = 0; j < SDL_TABLESIZE(joystick_logicalmap); j++) { |
217 if (!strcmp(name, joystick_logicalmap[j].name)) { | 344 if (!strcmp(name, joystick_logicalmap[j].name) && (nbuttons==-1 || nbuttons==joystick_logicalmap[j].nbuttons)) { |
218 | |
219 prev = i; | 345 prev = i; |
220 SDL_joylist[prev].map = joystick_logicalmap+j; | 346 SDL_joylist[prev].map = &(joystick_logicalmap[j]); |
221 | 347 |
222 for(k = 1; k < joystick_logicalmap[j].njoys; k++) { | 348 for(k = 1; k < joystick_logicalmap[j].njoys; k++) { |
223 SDL_joylist[prev].next = max + ret; | 349 SDL_joylist[prev].next = max + ret; |
224 | 350 SDL_joylist[max+ret].prev = prev; |
225 if (prev != i) | 351 |
226 SDL_joylist[max+ret].prev = prev; | |
227 | |
228 prev = max + ret; | 352 prev = max + ret; |
229 SDL_joylist[prev].logicalno = k; | 353 SDL_joylist[prev].logicalno = k; |
230 SDL_joylist[prev].map = joystick_logicalmap+j; | 354 SDL_joylist[prev].map = &(joystick_logicalmap[j]); |
231 ret++; | 355 ret++; |
232 } | 356 } |
233 | 357 |
234 break; | 358 break; |
235 } | 359 } |
245 register int slen; | 369 register int slen; |
246 const static char suffixs[] = | 370 const static char suffixs[] = |
247 "01020304050607080910111213141516171819" | 371 "01020304050607080910111213141516171819" |
248 "20212223242526272829303132"; | 372 "20212223242526272829303132"; |
249 const char* suffix; | 373 const char* suffix; |
250 | |
251 slen = strlen(namebuf); | 374 slen = strlen(namebuf); |
252 | |
253 suffix = NULL; | 375 suffix = NULL; |
254 | 376 |
255 if (logicalno*2<sizeof(suffixs)) | 377 if (logicalno*2<sizeof(suffixs)) |
256 suffix = suffixs + (logicalno*2); | 378 suffix = suffixs + (logicalno*2); |
257 | 379 |
417 } else { | 539 } else { |
418 name = namebuf; | 540 name = namebuf; |
419 } | 541 } |
420 close(fd); | 542 close(fd); |
421 | 543 |
422 #ifndef NO_LOGICAL_JOYSTICKS | 544 |
423 if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next) | 545 #ifndef NO_LOGICAL_JOYSTICKS |
546 if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex) | |
547 { | |
424 LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128); | 548 LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128); |
549 } | |
425 #endif | 550 #endif |
426 } | 551 } |
427 return name; | 552 return name; |
428 } | 553 } |
429 | 554 |
653 #ifndef NO_LOGICAL_JOYSTICKS | 778 #ifndef NO_LOGICAL_JOYSTICKS |
654 static void ConfigLogicalJoystick(SDL_Joystick *joystick) | 779 static void ConfigLogicalJoystick(SDL_Joystick *joystick) |
655 { | 780 { |
656 struct joystick_logical_layout* layout; | 781 struct joystick_logical_layout* layout; |
657 | 782 |
658 layout = SDL_joylist[joystick->index].map->layouts + | 783 layout = SDL_joylist[joystick->index].map->layout + |
659 SDL_joylist[joystick->index].logicalno; | 784 SDL_joylist[joystick->index].logicalno; |
660 | 785 |
661 joystick->nbuttons = layout->nbuttons; | 786 joystick->nbuttons = layout->nbuttons; |
662 joystick->nhats = layout->nhats; | 787 joystick->nhats = layout->nhats; |
663 joystick->naxes = layout->naxes; | 788 joystick->naxes = layout->naxes; |
729 } | 854 } |
730 | 855 |
731 #ifndef NO_LOGICAL_JOYSTICKS | 856 #ifndef NO_LOGICAL_JOYSTICKS |
732 | 857 |
733 static SDL_Joystick* FindLogicalJoystick( | 858 static SDL_Joystick* FindLogicalJoystick( |
734 SDL_Joystick *joystick, struct joystick_logical_values* v) | 859 SDL_Joystick *joystick, struct joystick_logical_mapping* v) |
735 { | 860 { |
736 SDL_Joystick *logicaljoy; | 861 SDL_Joystick *logicaljoy; |
737 register int i; | 862 register int i; |
738 | 863 |
739 i = joystick->index; | 864 i = joystick->index; |
758 return logicaljoy; | 883 return logicaljoy; |
759 } | 884 } |
760 | 885 |
761 static int LogicalJoystickButton( | 886 static int LogicalJoystickButton( |
762 SDL_Joystick *joystick, Uint8 button, Uint8 state){ | 887 SDL_Joystick *joystick, Uint8 button, Uint8 state){ |
763 struct joystick_logical_values* buttons; | 888 struct joystick_logical_mapping* buttons; |
764 SDL_Joystick *logicaljoy = NULL; | 889 SDL_Joystick *logicaljoy = NULL; |
765 | 890 |
766 /* if there's no map then this is just a regular joystick | 891 /* if there's no map then this is just a regular joystick |
767 */ | 892 */ |
768 if (SDL_joylist[joystick->index].map == NULL) | 893 if (SDL_joylist[joystick->index].map == NULL) |
769 return 0; | 894 return 0; |
770 | 895 |
771 /* get the logical joystick that will receive the event | 896 /* get the logical joystick that will receive the event |
772 */ | 897 */ |
773 buttons = SDL_joylist[joystick->index].map->buttons+button; | 898 buttons = SDL_joylist[joystick->index].map->buttonmap+button; |
774 logicaljoy = FindLogicalJoystick(joystick, buttons); | 899 logicaljoy = FindLogicalJoystick(joystick, buttons); |
775 | 900 |
776 if (logicaljoy == NULL) | 901 if (logicaljoy == NULL) |
777 return 1; | 902 return 1; |
778 | 903 |
782 } | 907 } |
783 | 908 |
784 static int LogicalJoystickAxis( | 909 static int LogicalJoystickAxis( |
785 SDL_Joystick *joystick, Uint8 axis, Sint16 value) | 910 SDL_Joystick *joystick, Uint8 axis, Sint16 value) |
786 { | 911 { |
787 struct joystick_logical_values* axes; | 912 struct joystick_logical_mapping* axes; |
788 SDL_Joystick *logicaljoy = NULL; | 913 SDL_Joystick *logicaljoy = NULL; |
789 | 914 |
790 /* if there's no map then this is just a regular joystick | 915 /* if there's no map then this is just a regular joystick |
791 */ | 916 */ |
792 if (SDL_joylist[joystick->index].map == NULL) | 917 if (SDL_joylist[joystick->index].map == NULL) |
793 return 0; | 918 return 0; |
794 | 919 |
795 /* get the logical joystick that will receive the event | 920 /* get the logical joystick that will receive the event |
796 */ | 921 */ |
797 axes = SDL_joylist[joystick->index].map->axes+axis; | 922 axes = SDL_joylist[joystick->index].map->axismap+axis; |
798 logicaljoy = FindLogicalJoystick(joystick, axes); | 923 logicaljoy = FindLogicalJoystick(joystick, axes); |
799 | 924 |
800 if (logicaljoy == NULL) | 925 if (logicaljoy == NULL) |
801 return 1; | 926 return 1; |
802 | 927 |
814 { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP }, | 939 { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP }, |
815 { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT }, | 940 { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT }, |
816 { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } | 941 { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } |
817 }; | 942 }; |
818 SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL); | 943 SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL); |
819 SDL_logical_joydecl(struct joystick_logical_values* hats = NULL); | 944 SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL); |
820 | 945 |
821 the_hat = &stick->hwdata->hats[hat]; | 946 the_hat = &stick->hwdata->hats[hat]; |
822 if ( value < 0 ) { | 947 if ( value < 0 ) { |
823 value = 0; | 948 value = 0; |
824 } else | 949 } else |
836 */ | 961 */ |
837 if (SDL_joylist[stick->index].map != NULL) { | 962 if (SDL_joylist[stick->index].map != NULL) { |
838 | 963 |
839 /* get the fake joystick that will receive the event | 964 /* get the fake joystick that will receive the event |
840 */ | 965 */ |
841 hats = SDL_joylist[stick->index].map->hats+hat; | 966 hats = SDL_joylist[stick->index].map->hatmap+hat; |
842 logicaljoy = FindLogicalJoystick(stick, hats); | 967 logicaljoy = FindLogicalJoystick(stick, hats); |
843 } | 968 } |
844 | 969 |
845 if (logicaljoy) { | 970 if (logicaljoy) { |
846 stick = logicaljoy; | 971 stick = logicaljoy; |