comparison src/joystick/linux/SDL_sysjoystick.c @ 1551:02e19471a694

Fixed bug #4 [Note: I'm applying this patch since it's a cleaner version of what's already implemented, and supports this controller on older kernels. I'll ask to make sure this doesn't break on the new kernels where it's no longer necessary] Date: Mon, 21 Mar 2005 09:41:11 -0500 From: Chris Nelson Subject: SDL Patch Hey, Ryan. I submitted the following patch about a year ago. It's just a simple patch for the linux port, to make multiple joysticks each appear to SDL as their own device, if they are on the same USB port (specifically, these guys <http://www.consoleplus.co.uk/product_info.php?pName=super-joybox-5-quad-joypad-converter>, which allow 4 Playstation2 controllers to be accessed via a single USB port). Without this patch, SDL pretty much drops the ball, and reports that there are 4 joysticks available when less than that number are plugged in. My work built upon the work of another person with the same device. When I submitted the patch to the list, he tested it, but it didn't work for him, so the patch was never accepted. Maybe about 3 times in the past year, I've tried to email the guy, to see if he couldn't run my new version, complete with debug code to diagnose the problem he was having. He never got back to me. So, I'm attaching the patch. I wish I knew why it didn't work for him, but I've been using it for the last year with no problems. Let me know if you need any more information, or have any ideas as to how I could test it. I'd like to see it in the tree, but I want to make sure it works. -Chris
author Sam Lantinga <slouken@libsdl.org>
date Sun, 19 Mar 2006 06:31:34 +0000
parents d910939febfa
children 92947e3a18db
comparison
equal deleted inserted replaced
1550:31c2b8e4885e 1551:02e19471a694
59 { "Saitek Saitek X45", 6, 1, 0 } 59 { "Saitek Saitek X45", 6, 1, 0 }
60 }; 60 };
61 61
62 #ifndef NO_LOGICAL_JOYSTICKS 62 #ifndef NO_LOGICAL_JOYSTICKS
63 63
64 static struct joystick_logical_values { 64 /*
65 Some USB HIDs show up as a single joystick even though they actually
66 control 2 or more joysticks.
67 */
68 /*
69 This code handles the MP-8800 (Quad) and MP-8866 (Dual), which can
70 be identified by their transparent blue design. It's quite trivial
71 to add other joysticks with similar quirky behavior.
72 -id
73 */
74
75 struct joystick_logical_mapping {
65 int njoy; 76 int njoy;
66 int nthing; 77 int nthing;
67 } joystick_logical_values[] = { 78 };
68 79
69 /* +0 */ 80 /*
70 /* MP-8800 axes map - map to {logical joystick #, logical axis #} */ 81 {logical joy, logical axis},
71 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},{1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, 82 {logical joy, logical hat},
72 {3,0},{3,1},{3,2},{3,3},{0,4},{1,4},{2,4}, 83 {logical joy, logical ball},
73 84 {logical joy, logical button}
74 /* +19 */ 85 */
75 /* MP-8800 hat map - map to {logical joystick #, logical hat #} */ 86
76 {0,0},{1,0},{2,0},{3,0}, 87 static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = {
77 88 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5}
78 /* +23 */ 89 };
79 /* MP-8800 button map - map to {logical joystick #, logical button #} */ 90 static struct joystick_logical_mapping mp88xx_1_logical_buttonmap[] = {
91 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}
92 };
93
94 static struct joystick_logical_mapping mp88xx_2_logical_axismap[] = {
95 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
96 {1,2},{1,3},{0,4},{0,5},{1,4},{1,5}
97 };
98 static struct joystick_logical_mapping mp88xx_2_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 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}
101 };
102
103 static struct joystick_logical_mapping mp88xx_3_logical_axismap[] = {
104 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
105 {1,2},{1,3},{2,0},{2,1},{2,2},{2,3},
106 {0,4},{0,5},{1,4},{1,5},{2,4},{2,5}
107 };
108 static struct joystick_logical_mapping mp88xx_3_logical_buttonmap[] = {
109 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
110 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},
111 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}
112 };
113
114 static struct joystick_logical_mapping mp88xx_4_logical_axismap[] = {
115 {0,0},{0,1},{0,2},{1,0},{1,1},{0,3},
116 {1,2},{1,3},{2,0},{2,1},{2,2},{2,3},
117 {3,0},{3,1},{3,2},{3,3},{0,4},{0,5},
118 {1,4},{1,5},{2,4},{2,5},{3,4},{3,5}
119 };
120 static struct joystick_logical_mapping mp88xx_4_logical_buttonmap[] = {
80 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, 121 {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11},
81 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, 122 {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11},
82 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}, 123 {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11},
83 {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11} 124 {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11}
84 }; 125 };
85 126
86 static struct joystick_logical_layout { 127 struct joystick_logical_layout {
87 int naxes; 128 int naxes;
88 int nhats; 129 int nhats;
89 int nballs; 130 int nballs;
90 int nbuttons; 131 int nbuttons;
91 } joystick_logical_layout[] = { 132 };
92 /* MP-8800 logical layout */ 133
93 {5, 1, 0, 12}, 134 static struct joystick_logical_layout mp88xx_1_logical_layout[] = {
94 {5, 1, 0, 12}, 135 {6, 0, 0, 12}
95 {5, 1, 0, 12}, 136 };
96 {4, 1, 0, 12} 137 static struct joystick_logical_layout mp88xx_2_logical_layout[] = {
138 {6, 0, 0, 12},
139 {6, 0, 0, 12}
140 };
141 static struct joystick_logical_layout mp88xx_3_logical_layout[] = {
142 {6, 0, 0, 12},
143 {6, 0, 0, 12},
144 {6, 0, 0, 12}
145 };
146 static struct joystick_logical_layout mp88xx_4_logical_layout[] = {
147 {6, 0, 0, 12},
148 {6, 0, 0, 12},
149 {6, 0, 0, 12},
150 {6, 0, 0, 12}
97 }; 151 };
98 152
99 /* 153 /*
100 Some USB HIDs show up as a single joystick even though they actually 154 This array sets up a means of mapping a single physical joystick to
101 control 2 or more joysticks. This array sets up a means of mapping 155 multiple logical joysticks. (djm)
102 a single physical joystick to multiple logical joysticks. (djm)
103 156
104 njoys 157 njoys
105 the number of logical joysticks 158 the number of logical joysticks
106 159
107 layouts 160 layouts
108 an array of layout structures, one to describe each logical joystick 161 an array of layout structures, one to describe each logical joystick
109 162
110 axes, hats, balls, buttons 163 axes, hats, balls, buttons
111 arrays that map a physical thingy to a logical thingy 164 arrays that map a physical thingy to a logical thingy
112 */ 165 */
113 static struct joystick_logicalmap { 166 struct joystick_logicalmap {
114 const char *name; 167 const char *name;
168 int nbuttons;
115 int njoys; 169 int njoys;
116 struct joystick_logical_layout *layouts; 170 struct joystick_logical_layout *layout;
117 struct joystick_logical_values *axes; 171 struct joystick_logical_mapping *axismap;
118 struct joystick_logical_values *hats; 172 struct joystick_logical_mapping *hatmap;
119 struct joystick_logical_values *balls; 173 struct joystick_logical_mapping *ballmap;
120 struct joystick_logical_values *buttons; 174 struct joystick_logical_mapping *buttonmap;
121 175 };
122 } joystick_logicalmap[] = { 176
123 {"WiseGroup.,Ltd MP-8800 Quad USB Joypad", 4, joystick_logical_layout, 177 static struct joystick_logicalmap joystick_logicalmap[] = {
124 joystick_logical_values, joystick_logical_values+19, NULL, 178 {
125 joystick_logical_values+23} 179 "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
180 12,
181 1,
182 mp88xx_1_logical_layout,
183 mp88xx_1_logical_axismap,
184 NULL,
185 NULL,
186 mp88xx_1_logical_buttonmap
187 },
188 {
189 "WiseGroup.,Ltd MP-8866 Dual USB Joypad",
190 24,
191 2,
192 mp88xx_2_logical_layout,
193 mp88xx_2_logical_axismap,
194 NULL,
195 NULL,
196 mp88xx_2_logical_buttonmap
197 },
198 {
199 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
200 12,
201 1,
202 mp88xx_1_logical_layout,
203 mp88xx_1_logical_axismap,
204 NULL,
205 NULL,
206 mp88xx_1_logical_buttonmap
207 },
208 {
209 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
210 24,
211 2,
212 mp88xx_2_logical_layout,
213 mp88xx_2_logical_axismap,
214 NULL,
215 NULL,
216 mp88xx_2_logical_buttonmap
217 },
218 {
219 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
220 36,
221 3,
222 mp88xx_3_logical_layout,
223 mp88xx_3_logical_axismap,
224 NULL,
225 NULL,
226 mp88xx_3_logical_buttonmap
227 },
228 {
229 "WiseGroup.,Ltd MP-8800 Quad USB Joypad",
230 48,
231 4,
232 mp88xx_4_logical_layout,
233 mp88xx_4_logical_axismap,
234 NULL,
235 NULL,
236 mp88xx_4_logical_buttonmap
237 }
126 }; 238 };
127 239
128 /* find the head of a linked list, given a point in it 240 /* find the head of a linked list, given a point in it
129 */ 241 */
130 #define SDL_joylist_head(i, start)\ 242 #define SDL_joylist_head(i, start)\
185 297
186 static int CountLogicalJoysticks(int max) 298 static int CountLogicalJoysticks(int max)
187 { 299 {
188 register int i, j, k, ret, prev; 300 register int i, j, k, ret, prev;
189 const char* name; 301 const char* name;
302 int nbuttons, fd;
303 unsigned char n;
190 304
191 ret = 0; 305 ret = 0;
192 306
193 for(i = 0; i < max; i++) { 307 for(i = 0; i < max; i++) {
194 name = SDL_SYS_JoystickName(i); 308 name = SDL_SYS_JoystickName(i);
309
310 fd = open(SDL_joylist[i].fname, O_RDONLY, 0);
311 if ( fd >= 0 ) {
312 if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) {
313 nbuttons = -1;
314 } else {
315 nbuttons = n;
316 }
317 close(fd);
318 }
319 else {
320 nbuttons=-1;
321 }
195 322
196 if (name) { 323 if (name) {
197 for(j = 0; j < SDL_arraysize(joystick_logicalmap); j++) { 324 for(j = 0; j < SDL_arraysize(joystick_logicalmap); j++) {
198 if (!SDL_strcmp(name, joystick_logicalmap[j].name)) { 325 if (!SDL_strcmp(name, joystick_logicalmap[j].name) && (nbuttons==-1 || nbuttons==joystick_logicalmap[j].nbuttons)) {
199
200 prev = i; 326 prev = i;
201 SDL_joylist[prev].map = joystick_logicalmap+j; 327 SDL_joylist[prev].map = &(joystick_logicalmap[j]);
202 328
203 for(k = 1; k < joystick_logicalmap[j].njoys; k++) { 329 for(k = 1; k < joystick_logicalmap[j].njoys; k++) {
204 SDL_joylist[prev].next = max + ret; 330 SDL_joylist[prev].next = max + ret;
205 331 SDL_joylist[max+ret].prev = prev;
206 if (prev != i) 332
207 SDL_joylist[max+ret].prev = prev;
208
209 prev = max + ret; 333 prev = max + ret;
210 SDL_joylist[prev].logicalno = k; 334 SDL_joylist[prev].logicalno = k;
211 SDL_joylist[prev].map = joystick_logicalmap+j; 335 SDL_joylist[prev].map = &(joystick_logicalmap[j]);
212 ret++; 336 ret++;
213 } 337 }
214 338
215 break; 339 break;
216 } 340 }
226 register int slen; 350 register int slen;
227 const static char suffixs[] = 351 const static char suffixs[] =
228 "01020304050607080910111213141516171819" 352 "01020304050607080910111213141516171819"
229 "20212223242526272829303132"; 353 "20212223242526272829303132";
230 const char* suffix; 354 const char* suffix;
231
232 slen = SDL_strlen(namebuf); 355 slen = SDL_strlen(namebuf);
233
234 suffix = NULL; 356 suffix = NULL;
235 357
236 if (logicalno*2<sizeof(suffixs)) 358 if (logicalno*2<sizeof(suffixs))
237 suffix = suffixs + (logicalno*2); 359 suffix = suffixs + (logicalno*2);
238 360
397 } else { 519 } else {
398 name = namebuf; 520 name = namebuf;
399 } 521 }
400 close(fd); 522 close(fd);
401 523
402 #ifndef NO_LOGICAL_JOYSTICKS 524
403 if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next) 525 #ifndef NO_LOGICAL_JOYSTICKS
526 if (SDL_joylist[oindex].prev || SDL_joylist[oindex].next || index!=oindex)
527 {
404 LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128); 528 LogicalSuffix(SDL_joylist[oindex].logicalno, namebuf, 128);
529 }
405 #endif 530 #endif
406 } 531 }
407 return name; 532 return name;
408 } 533 }
409 534
633 #ifndef NO_LOGICAL_JOYSTICKS 758 #ifndef NO_LOGICAL_JOYSTICKS
634 static void ConfigLogicalJoystick(SDL_Joystick *joystick) 759 static void ConfigLogicalJoystick(SDL_Joystick *joystick)
635 { 760 {
636 struct joystick_logical_layout* layout; 761 struct joystick_logical_layout* layout;
637 762
638 layout = SDL_joylist[joystick->index].map->layouts + 763 layout = SDL_joylist[joystick->index].map->layout +
639 SDL_joylist[joystick->index].logicalno; 764 SDL_joylist[joystick->index].logicalno;
640 765
641 joystick->nbuttons = layout->nbuttons; 766 joystick->nbuttons = layout->nbuttons;
642 joystick->nhats = layout->nhats; 767 joystick->nhats = layout->nhats;
643 joystick->naxes = layout->naxes; 768 joystick->naxes = layout->naxes;
709 } 834 }
710 835
711 #ifndef NO_LOGICAL_JOYSTICKS 836 #ifndef NO_LOGICAL_JOYSTICKS
712 837
713 static SDL_Joystick* FindLogicalJoystick( 838 static SDL_Joystick* FindLogicalJoystick(
714 SDL_Joystick *joystick, struct joystick_logical_values* v) 839 SDL_Joystick *joystick, struct joystick_logical_mapping* v)
715 { 840 {
716 SDL_Joystick *logicaljoy; 841 SDL_Joystick *logicaljoy;
717 register int i; 842 register int i;
718 843
719 i = joystick->index; 844 i = joystick->index;
738 return logicaljoy; 863 return logicaljoy;
739 } 864 }
740 865
741 static int LogicalJoystickButton( 866 static int LogicalJoystickButton(
742 SDL_Joystick *joystick, Uint8 button, Uint8 state){ 867 SDL_Joystick *joystick, Uint8 button, Uint8 state){
743 struct joystick_logical_values* buttons; 868 struct joystick_logical_mapping* buttons;
744 SDL_Joystick *logicaljoy = NULL; 869 SDL_Joystick *logicaljoy = NULL;
745 870
746 /* if there's no map then this is just a regular joystick 871 /* if there's no map then this is just a regular joystick
747 */ 872 */
748 if (SDL_joylist[joystick->index].map == NULL) 873 if (SDL_joylist[joystick->index].map == NULL)
749 return 0; 874 return 0;
750 875
751 /* get the logical joystick that will receive the event 876 /* get the logical joystick that will receive the event
752 */ 877 */
753 buttons = SDL_joylist[joystick->index].map->buttons+button; 878 buttons = SDL_joylist[joystick->index].map->buttonmap+button;
754 logicaljoy = FindLogicalJoystick(joystick, buttons); 879 logicaljoy = FindLogicalJoystick(joystick, buttons);
755 880
756 if (logicaljoy == NULL) 881 if (logicaljoy == NULL)
757 return 1; 882 return 1;
758 883
762 } 887 }
763 888
764 static int LogicalJoystickAxis( 889 static int LogicalJoystickAxis(
765 SDL_Joystick *joystick, Uint8 axis, Sint16 value) 890 SDL_Joystick *joystick, Uint8 axis, Sint16 value)
766 { 891 {
767 struct joystick_logical_values* axes; 892 struct joystick_logical_mapping* axes;
768 SDL_Joystick *logicaljoy = NULL; 893 SDL_Joystick *logicaljoy = NULL;
769 894
770 /* if there's no map then this is just a regular joystick 895 /* if there's no map then this is just a regular joystick
771 */ 896 */
772 if (SDL_joylist[joystick->index].map == NULL) 897 if (SDL_joylist[joystick->index].map == NULL)
773 return 0; 898 return 0;
774 899
775 /* get the logical joystick that will receive the event 900 /* get the logical joystick that will receive the event
776 */ 901 */
777 axes = SDL_joylist[joystick->index].map->axes+axis; 902 axes = SDL_joylist[joystick->index].map->axismap+axis;
778 logicaljoy = FindLogicalJoystick(joystick, axes); 903 logicaljoy = FindLogicalJoystick(joystick, axes);
779 904
780 if (logicaljoy == NULL) 905 if (logicaljoy == NULL)
781 return 1; 906 return 1;
782 907
794 { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP }, 919 { SDL_HAT_LEFTUP, SDL_HAT_UP, SDL_HAT_RIGHTUP },
795 { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT }, 920 { SDL_HAT_LEFT, SDL_HAT_CENTERED, SDL_HAT_RIGHT },
796 { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN } 921 { SDL_HAT_LEFTDOWN, SDL_HAT_DOWN, SDL_HAT_RIGHTDOWN }
797 }; 922 };
798 SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL); 923 SDL_logical_joydecl(SDL_Joystick *logicaljoy = NULL);
799 SDL_logical_joydecl(struct joystick_logical_values* hats = NULL); 924 SDL_logical_joydecl(struct joystick_logical_mapping* hats = NULL);
800 925
801 the_hat = &stick->hwdata->hats[hat]; 926 the_hat = &stick->hwdata->hats[hat];
802 if ( value < 0 ) { 927 if ( value < 0 ) {
803 value = 0; 928 value = 0;
804 } else 929 } else
816 */ 941 */
817 if (SDL_joylist[stick->index].map != NULL) { 942 if (SDL_joylist[stick->index].map != NULL) {
818 943
819 /* get the fake joystick that will receive the event 944 /* get the fake joystick that will receive the event
820 */ 945 */
821 hats = SDL_joylist[stick->index].map->hats+hat; 946 hats = SDL_joylist[stick->index].map->hatmap+hat;
822 logicaljoy = FindLogicalJoystick(stick, hats); 947 logicaljoy = FindLogicalJoystick(stick, hats);
823 } 948 }
824 949
825 if (logicaljoy) { 950 if (logicaljoy) {
826 stick = logicaljoy; 951 stick = logicaljoy;