Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
xbox360gamepad.c
00001 /**************************************************************************** 00002 * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd 00003 * 00004 * This file is part of the Satellite Observers Workbench (SOWB). 00005 * 00006 * SOWB is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * SOWB is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with SOWB. If not, see <http://www.gnu.org/licenses/>. 00018 * 00019 * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $ 00020 * 00021 ***************************************************************************/ 00022 00023 #include "sowb.h" 00024 #include "debug.h" 00025 #include "usbeh_api.h" 00026 #include "usbeh_endpoint.h" 00027 #include "usbeh_device.h" 00028 #include "usbeh_controller.h" 00029 #include "xbox360gamepad.h" 00030 00031 #include "main.h" 00032 00033 /* Define an array of data structures for the buttons. */ 00034 static XBOX360_BUTTON buttons[16]; 00035 static unsigned char button_buffer[16]; 00036 static unsigned char button_buffer_in; 00037 static unsigned char button_buffer_out; 00038 00039 /* Place holders for left and right triggers. */ 00040 static unsigned char trigger_left; 00041 static unsigned char trigger_right; 00042 00043 static XBOX360_STICK stick_left; 00044 static XBOX360_STICK stick_right; 00045 00046 /* A map of wired Xbox 360 controllers. 00047 Data copied from the Linux xboxdrv project, thx :) 00048 http://pingus.seul.org/~grumbel/xboxdrv */ 00049 static XBOX360_DEVICE xbox360_devices[] = { 00050 { 0x045e, 0x028e, "Microsoft Xbox 360 Controller" }, 00051 { 0x0738, 0x4716, "Mad Catz Xbox 360 Controller" }, 00052 { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller" }, 00053 { 0x0738, 0x4740, "Mad Catz Beat Pad" }, 00054 { 0x0738, 0xf738, "Super SFIV FightStick TE S" }, 00055 { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick" }, 00056 { 0x0f0d, 0x000d, "Hori Fighting Stick Ex2" }, 00057 { 0x0f0d, 0x0016, "Hori Real Arcade Pro Ex" }, 00058 { 0x162e, 0xbeef, "Joytech Neo-Se Take2" }, 00059 { 0x046d, 0xc242, "Logitech ChillStream" }, 00060 { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360" }, 00061 { 0x0e6f, 0x0201, "Pelican TSZ360 Pad" }, 00062 { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2" }, // Here's one I found that isn't in the Linux distro. 00063 { 0x0000, 0x0000, "End of list" } 00064 }; 00065 00066 /* Although Microsoft has not published any data or specifications 00067 regarding the Xbox360 gamepad/controller, it's basic makeup is 00068 well known. Define here the pipes for the interfaces we are 00069 interested in. */ 00070 00071 #define XBOX360_GAMEPAD_PIPE_BUFFER_SIZE 32 00072 00073 typedef struct { 00074 USBEH_U08 data_in[XBOX360_GAMEPAD_PIPE_BUFFER_SIZE]; 00075 USBEH_U08 data_out[XBOX360_GAMEPAD_PIPE_BUFFER_SIZE]; 00076 USBEH_U08 ep_number_in; 00077 USBEH_U08 ep_number_out; 00078 } XBOX360_PIPE; 00079 00080 typedef struct { 00081 USBEH_U08 data_in[256]; 00082 USBEH_U08 data_out[256]; 00083 USBEH_U08 ep_number_in; 00084 USBEH_U08 ep_number_out; 00085 } XBOX360_CONTROL_PIPE; 00086 00087 struct _xbox360_gamepad_vendor { 00088 XBOX360_CONTROL_PIPE pipe[1]; 00089 } IF_VENDOR __attribute__((aligned(256))); 00090 00091 struct _xbox360_gamepad_interface0 { 00092 XBOX360_PIPE pipe[1]; 00093 } IF_ZERO __attribute__((aligned(256))); 00094 00095 struct _xbox360_gamepad_interface1 { 00096 XBOX360_PIPE pipe[2]; 00097 } IF_ONE __attribute__((aligned(256))); 00098 00099 struct _xbox360_gamepad_interface2 { 00100 XBOX360_PIPE pipe[1]; 00101 } IF_TWO __attribute__((aligned(256))); 00102 00103 int deviceNumber; 00104 00105 int xbox360gamepad_init(void) { 00106 DEBUG_INIT_START; 00107 for (int i = 0; i < 16; i++) { 00108 buttons[i].state = BUTTON_RELEASED; 00109 buttons[i].count = 0; 00110 button_buffer[i] = 0xFF; 00111 usbeh_sof_counter_init(&buttons[i].pressHold, USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, BUTTON_HOLD_TIME); 00112 buttons[i].pressHold.userData = i; 00113 buttons[i].pressHold.callback = xbox360gamepad_button_hold_callback; 00114 usbeh_sof_counter_register(&buttons[i].pressHold); 00115 } 00116 button_buffer_in = 0; 00117 button_buffer_out = 0; 00118 trigger_left = 0; 00119 trigger_right = 0; 00120 stick_left.x = 0; 00121 stick_left.y = 0; 00122 stick_right.x = 0; 00123 stick_right.y = 0; 00124 DEBUG_INIT_END; 00125 return 0; 00126 } 00127 00128 void xbox360gamepad_process(void) { 00129 // This currently does nothing. 00130 } 00131 00132 void xbox360gamepad_button_press(unsigned char button) { 00133 button_buffer[button_buffer_in] = button; 00134 button_buffer_in++; 00135 button_buffer_in &= 0x0F; 00136 } 00137 00138 char xbox360gamepad_get_button(void) { 00139 if (button_buffer_in == button_buffer_out) { 00140 return 0; 00141 } 00142 00143 char button = button_buffer[button_buffer_out]; 00144 button_buffer_out++; 00145 button_buffer_out &= 0x0F; 00146 return button; 00147 } 00148 00149 char xbox360gamepad_get_button_preview(void) { 00150 if (button_buffer_in == button_buffer_out) { 00151 return 0; 00152 } 00153 00154 char button = button_buffer[button_buffer_out]; 00155 return button; 00156 } 00157 00158 unsigned char xbox360gamepad_get_trigger_left(void) { 00159 return trigger_left; 00160 } 00161 00162 unsigned char xbox360gamepad_get_trigger_right(void) { 00163 return trigger_right; 00164 } 00165 00166 XBOX360_STICK * xbox360gamepad_get_stick_left(void) { 00167 return &stick_left; 00168 } 00169 00170 XBOX360_STICK * xbox360gamepad_get_stick_right(void) { 00171 return &stick_right; 00172 } 00173 00174 void xbox360gamepad_button_hold_callback(USBEH_SOF_COUNTER *q) { 00175 int i = (int)q->userData; 00176 if (buttons[i].state == BUTTON_PRESSED) { 00177 xbox360gamepad_button_press((char)(i + 1 + 32)); 00178 } 00179 } 00180 00181 /** 00182 * xbox360gamepad_interface_0_in 00183 * 00184 * A callback function to handle interface0 pipe0 data. 00185 */ 00186 void xbox360gamepad_interface_0_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { 00187 unsigned button_flags; 00188 00189 /* Is this a button press report? */ 00190 if(IF_ZERO.pipe[(int)userData].data_in[0] == 0 && IF_ZERO.pipe[(int)userData].data_in[1] == 0x14) { 00191 00192 /* Handle the button flags. */ 00193 button_flags = ((IF_ZERO.pipe[(int)userData].data_in[2] & 0xFF) << 8) | (IF_ZERO.pipe[(int)userData].data_in[3] & 0xFF); 00194 for (int i = 0; i < 16; i++) { 00195 if ((button_flags & (1 << i)) != 0) { 00196 if (buttons[i].state == BUTTON_RELEASED) { 00197 buttons[i].state = BUTTON_PRESSED; 00198 buttons[i].count++; 00199 buttons[i].pressHold.flag = 0; 00200 xbox360gamepad_button_press((char)(i + 1)); 00201 } 00202 } 00203 else { 00204 if (buttons[i].state == BUTTON_PRESSED) { 00205 buttons[i].state = BUTTON_RELEASED; 00206 buttons[i].pressHold.flag = 1; 00207 buttons[i].pressHold.counter = BUTTON_HOLD_TIME; 00208 buttons[i].count = 0; 00209 xbox360gamepad_button_press((char)(i + 1 + 16)); 00210 } 00211 } 00212 } 00213 00214 /* Handle the analogue triggers. */ 00215 trigger_left = (unsigned char)IF_ZERO.pipe[(int)userData].data_in[4]; 00216 trigger_right = (unsigned char)IF_ZERO.pipe[(int)userData].data_in[5]; 00217 00218 /* Handle the analogue sticks. */ 00219 { 00220 short x, y; 00221 x = (short)((IF_ZERO.pipe[(int)userData].data_in[6]) | IF_ZERO.pipe[(int)userData].data_in[7] << 8); 00222 y = (short)((IF_ZERO.pipe[(int)userData].data_in[8]) | IF_ZERO.pipe[(int)userData].data_in[9] << 8); 00223 if (x != stick_left.x_previous) { 00224 stick_left.x_previous = stick_left.x; 00225 stick_left.x = x; 00226 } 00227 if (y != stick_left.y_previous) { 00228 stick_left.y_previous = stick_left.y; 00229 stick_left.y = y; 00230 } 00231 x = (short)((IF_ZERO.pipe[(int)userData].data_in[10]) | IF_ZERO.pipe[(int)userData].data_in[11] << 8); 00232 y = (short)((IF_ZERO.pipe[(int)userData].data_in[12]) | IF_ZERO.pipe[(int)userData].data_in[13] << 8); 00233 if (x != stick_right.x_previous) { 00234 stick_right.x_previous = stick_right.x; 00235 stick_right.x = x; 00236 } 00237 if (y != stick_right.y_previous) { 00238 stick_right.y_previous = stick_right.y; 00239 stick_right.y = y; 00240 } 00241 } 00242 } 00243 else if(len == 3) { 00244 /* Chatpad return? */ 00245 #ifdef DEBUG_USB_DRIVER_IF_0 00246 debug_printf("Got %02x %02x %02x \r\n", buf[0], buf[1], buf[2]); 00247 #endif 00248 } 00249 else { 00250 #ifdef DEBUG_USB_DRIVER_IF_0 00251 DEBUG_UNKNOWN_PACKET_IF_0 00252 #endif 00253 } 00254 00255 /* Schedule another transfer to keep the IN flow of data coming. */ 00256 usbeh_api_interrupt_transfer(device, endpoint, IF_ZERO.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_0_in, userData); 00257 } 00258 00259 void xbox360gamepad_interface_1_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { 00260 /* We don't currently do anything with Interface:1 */ 00261 #ifdef DEBUG_USB_DRIVER_IF_1 00262 DEBUG_UNKNOWN_PACKET_IF_1 00263 #endif 00264 00265 /* Schedule another transfer to keep the IN flow of data coming. */ 00266 usbeh_api_interrupt_transfer(device, endpoint, IF_ONE.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_1_in, userData); 00267 } 00268 00269 void xbox360gamepad_interface_2_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { 00270 /* We don't currently do anything with Interface:2 */ 00271 #ifdef DEBUG_USB_DRIVER_IF_2 00272 DEBUG_UNKNOWN_PACKET_IF_2 00273 #endif 00274 00275 /* Schedule another transfer to keep the IN flow of data coming. */ 00276 usbeh_api_interrupt_transfer(device, endpoint, IF_TWO.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_2_in, userData); 00277 } 00278 00279 int xbox360gamepad_add_interface(int device, USBEH_interfaceDescriptor *iface, USBEH_endpointDescriptor *ed) { 00280 00281 /* Handle interrupt IN transfers. */ 00282 if ((ed->bmAttributes & 3) != USBEH_ENDPOINT_INTERRUPT) { 00283 return 0; 00284 } 00285 00286 if (iface->bInterfaceNumber == 0) { 00287 int pipe = 0; 00288 if (ed->bEndpointAddress & 0x80) { 00289 #ifdef DEBUG_USB_DRIVER 00290 DEBUG_USB_MSG_ALLOCATION 00291 #endif 00292 IF_ZERO.pipe[pipe].ep_number_in = ed->bEndpointAddress; 00293 usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_ZERO.pipe[0].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_0_in, (void *)pipe); 00294 } 00295 else { 00296 #ifdef DEBUG_USB_DRIVER 00297 DEBUG_USB_MSG_ALLOCATION 00298 #endif 00299 IF_ZERO.pipe[pipe].ep_number_out = ed->bEndpointAddress; 00300 } 00301 } 00302 00303 if (iface->bInterfaceNumber == 1) { 00304 int pipe = (IF_ONE.pipe[0].ep_number_in == 0) ? 0 : 1; 00305 if (ed->bEndpointAddress & 0x80) { 00306 IF_ONE.pipe[pipe].ep_number_in = ed->bEndpointAddress; 00307 #ifdef DEBUG_USB_DRIVER 00308 DEBUG_USB_MSG_ALLOCATION 00309 #endif 00310 usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_ONE.pipe[pipe].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_1_in, (void *)pipe); 00311 } 00312 else { 00313 #ifdef DEBUG_USB_DRIVER 00314 DEBUG_USB_MSG_ALLOCATION 00315 #endif 00316 IF_ONE.pipe[pipe].ep_number_out = ed->bEndpointAddress; 00317 } 00318 } 00319 00320 00321 if (iface->bInterfaceNumber == 2) { 00322 int pipe = (IF_TWO.pipe[0].ep_number_in == 0) ? 0 : 1; 00323 if (ed->bEndpointAddress & 0x80) { 00324 IF_TWO.pipe[pipe].ep_number_in = ed->bEndpointAddress; 00325 #ifdef DEBUG_USB_DRIVER 00326 DEBUG_USB_MSG_ALLOCATION 00327 #endif 00328 usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_TWO.pipe[pipe].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_2_in, (void *)pipe); 00329 } 00330 else { 00331 #ifdef DEBUG_USB_DRIVER 00332 DEBUG_USB_MSG_ALLOCATION 00333 #endif 00334 IF_TWO.pipe[pipe].ep_number_out = ed->bEndpointAddress; 00335 } 00336 } 00337 00338 return 1; 00339 } 00340 00341 static XBOX360_DEVICE * xbox360gamepad_vendor_product_check(uint16_t vendorId, uint16_t productId) { 00342 for (int i = 0; xbox360_devices[i].idVendor != 0; i++) { 00343 if (xbox360_devices[i].idVendor == vendorId && xbox360_devices[i].idProduct == productId) { 00344 return &xbox360_devices[i]; 00345 } 00346 } 00347 return (XBOX360_DEVICE *)NULL; 00348 } 00349 00350 void xbox360gamepad_led(int code) { 00351 IF_ZERO.pipe[0].data_out[0] = 0x01; 00352 IF_ZERO.pipe[0].data_out[1] = 0x03; 00353 IF_ZERO.pipe[0].data_out[2] = code; 00354 usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, IF_ZERO.pipe[0].data_out, 3, NULL, NULL); 00355 } 00356 00357 USBEH_U08 noise[] = "\x0\x8\x0\x0\x0\x0\x0\x0"; 00358 00359 void xbox360_noise(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { 00360 usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, noise, 8, xbox360_noise, NULL); 00361 } 00362 00363 int xbox360gamepad_onload_callback(int device, USBEH_deviceDescriptor *deviceDesc, USBEH_interfaceDescriptor **interfaceDesc) { 00364 USBEH_interfaceDescriptor *iface; 00365 int length, endpoint_count, interfaceCounter = 0; 00366 USBEH_U08 *start, *end; 00367 00368 /* Is this a Microsoft Xbox360 wired Gamepad? */ 00369 XBOX360_DEVICE *xd = xbox360gamepad_vendor_product_check(deviceDesc->idVendor, deviceDesc->idProduct); 00370 if (!xd) { 00371 /* If not, don't claim it. */ 00372 return 0; 00373 } 00374 00375 #ifdef DEBUG_USB_DRIVER 00376 debug_printf("Found device '%s'\r\n", xd->name); 00377 #endif 00378 00379 /* Save our device number in a global. */ 00380 deviceNumber = device; 00381 00382 memset((char *)&IF_VENDOR, 0, sizeof(IF_VENDOR)); 00383 memset((char *)&IF_ZERO, 0, sizeof(IF_ZERO)); 00384 memset((char *)&IF_ONE, 0, sizeof(IF_ONE)); 00385 memset((char *)&IF_TWO, 0, sizeof(IF_TWO)); 00386 00387 #ifdef DEBUG_USB_DRIVER 00388 debug_printf("%s() ACTIVATED for device id = %d\r\n", __FUNCTION__, device); 00389 debug_printf(" OnLoad VendorId = 0x%04x ProductId = 0x%04x \r\n", deviceDesc->idVendor, deviceDesc->idProduct); 00390 #endif 00391 00392 /* Parse the interface configuration and setup the endpoint handlers. */ 00393 while ((iface = interfaceDesc[interfaceCounter]) != (USBEH_interfaceDescriptor *)NULL) { 00394 #ifdef DEBUG_USB_DRIVER 00395 debug_printf(" interface%d:- \r\n", interfaceCounter); 00396 debug_printf(" InterfaceClass = %02x \r\n", iface->bInterfaceClass); 00397 debug_printf(" InterfaceSubClass = %02x \r\n", iface->bInterfaceSubClass); 00398 debug_printf(" InterfaceProtocol = %02x \r\n", iface->bInterfaceProtocol); 00399 #endif 00400 start = (USBEH_U08 *)iface; 00401 length = start[0]; 00402 end = start + length; 00403 #ifdef DEBUG_USB_DRIVER 00404 debug_printf(" Scanning at start:%08x length:%d end:%08x \r\n", start, length, end); 00405 #endif 00406 while (start < end) { 00407 if (start[1] == USBEH_DESCRIPTOR_TYPE_INTERFACE) { 00408 USBEH_interfaceDescriptor *id = (USBEH_interfaceDescriptor *)start; 00409 //int interfaceNumber = (int)id->bInterfaceNumber; 00410 endpoint_count = (int)id->bNumEndpoints; 00411 #ifdef DEBUG_USB_DRIVER 00412 debug_printf(" found definition for if:%d with %d endpoints.\r\n", interfaceNumber, endpoint_count); 00413 #endif 00414 start += start[0]; 00415 while (endpoint_count > 0) { 00416 if (start[1] == USBEH_DESCRIPTOR_TYPE_ENDPOINT) { 00417 USBEH_endpointDescriptor *ed = (USBEH_endpointDescriptor *)start; 00418 #ifdef DEBUG_USB_DRIVER 00419 debug_printf(" found endpoint 0x%02X\r\n", ed->bEndpointAddress); 00420 #endif 00421 xbox360gamepad_add_interface(device, id, ed); 00422 endpoint_count--; 00423 } 00424 else { 00425 #ifdef DEBUG_USB_DRIVER 00426 debug_printf(" no endpoint for interface, descriptor class: %02X\r\n", start[1]); 00427 #endif 00428 } 00429 start += start[0]; 00430 } 00431 } 00432 else { 00433 #ifdef DEBUG_USB_DRIVER 00434 debug_printf(" no IF descr found at %08x\r\n", start); 00435 #endif 00436 start += start[0]; 00437 } 00438 } 00439 00440 interfaceCounter++; 00441 } 00442 00443 #ifdef DEBUG_USB_DRIVER 00444 debug_printf("Device claimed by %s().\r\n\n", __FUNCTION__); 00445 #endif 00446 00447 /* When the gamepad boots up, the LED ring flashes after it's 00448 configuration is set. Let's flash the led and go steady. */ 00449 xbox360gamepad_led(LED_1_FLASH_THEN_ON); 00450 00451 /* Lets just send "noise" to the headset and see what happens. */ 00452 //usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, noise, 8, xbox360_noise, NULL); 00453 00454 /* I give up, wtf is it with this chatpad that MS needs to keep so secret? */ 00455 //xbox360_chatpad_init(); 00456 00457 /* Tell the USB embedded host that we have claimed this device. */ 00458 return 1; 00459 } 00460 00461 #ifdef NEVERCOMPILETHISCODE 00462 /* 00463 00464 UPDATE: Everything below is ABANDONED when I basically figured out from one replay to the next 00465 that MS use the security channel to "handshake" init the chatpad. Many people believe 00466 the security device in the gamepad is to "tell the xbox I am a real auth MS gamepad". However, 00467 as I have discovered, it's "two-way". There also exists the "tell the gamepad that an auth 00468 Xbox360 is the host" and without that the chatpad will not function. I have no interest in 00469 trying to crack anyones security chips so no further work will be done on this. 00470 00471 Everything below here is related to the chatpad attachment for the Xbox360 gamepad controller. 00472 Unlike the sticks, triggers and buttons, the chatpad appears to require some sort of initialization 00473 in order to start running. Since MS have not published any sort of USB protocol specifications 00474 for their gamepad, what we do here is basically a "replay attack" based on packets sent and received 00475 between an Xbox and a gamepad with a USB protocol analyser in the middle. A classic man-in-the-middle 00476 type of attack. 00477 00478 Here's the basic sequence we attempt to follow:- 00479 00480 1. -> Vendor request IN EP0 (0x01) 00481 -> SETUP C0 01 00 00 00 00 04 00 00482 <- IN 80 03 0D 47 00483 2. -> Vendor request OUT EP0 (0xA9) 00484 -> 40 A9 0C A3 23 44 00 00485 <- Expect STALLED no data 00486 3. -> Vendor request OUT EP0 (0xA9) 00487 -> 40 A9 44 23 03 7F 00 00 00488 <- Expect STALLED no data 00489 4. -> Vendor request OUT EP0 (0xA9) 00490 -> 40 A9 39 58 32 68 00 00 00491 <- Expect STALLED no data 00492 5. <- IN IF:0 EP2 3 bytes 01 03 0E 00493 6. -> Vendor request IN EP0 (0xA1) 00494 -> SETUP C0 A1 00 00 16 E4 02 00 00495 <- IN 01 00 00496 7. -> OUT IF:0 EP1 3 bytes 01 03 01 00497 8. -> Vendor request OUT EP0 (0xA1) 00498 -> SETUP 40 A1 00 00 16 E4 02 00 00499 -> OUT 09 00 00500 9. -> Vendor request IN EP0 (0xA1) 00501 -> SETUP C0 A1 00 00 16 E4 02 00 00502 -> IN 09 00 (echo previous OUT?) 00503 10. <- IN IF:0 EP 1 3 bytes 02 03 00 00504 11. <- IN IF:0 EP 1 3 bytes 03 03 03 00505 12. <- IN IF:0 EP 1 3 bytes 08 03 00 00506 13. <- IN IF:0 EP 1 3 bytes 01 03 01 00507 14. -> Vendor request OUT EP0 (0x00) 00508 -> SETUP 41 00 1F 00 02 00 00 00 00509 -> IN No data 00510 15. -> Vendor request OUT EP0 (0x00) 00511 -> SETUP 41 00 1E 00 02 00 00 00 00512 -> IN No data 00513 00514 Note that 14. and 15. are 1second apart and repeat continuely 00515 toggling between 1F and 1E each second. 00516 00517 16. <- IN IF:2 EP4 (IF:2 PIPE1) 5 bytes F0 03 00 01 01 00518 17. -> Vendor request OUT EP0 (0x00) 00519 -> SETUP 41 00 1B 00 02 00 00 00 00520 -> IN No data 00521 18. <- IN IF:2 EP4 (IF:2 PIPE1) 5 bytes F0 03 00 01 01 00522 19. -> Vendor request OUT EP0 (0x00) 00523 -> SETUP 41 00 1B 00 02 00 00 00 00524 -> IN No data 00525 00526 00527 After this we start receiving data from IF:2 PIPE1 00528 00529 */ 00530 USBEH_U08 chatpad_trash_buffer[256]; 00531 USBEH_U08 chatpad_toggle; 00532 USBEH_U08 chatpad_send_toggle; 00533 USBEH_U08 chatpad_toggle_1Bsent; 00534 USBEH_SOF_COUNTER chatpad_toggle_timer; 00535 00536 void xbox360_chatpad_toggle(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { 00537 int result = usbeh_api_control_transfer(deviceNumber, 00538 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 00539 0x00, 00540 (int)userData, 00541 0x0002, 00542 chatpad_trash_buffer, 00543 0, 00544 xbox360_chatpad_toggle, 00545 (userData == (void *)0x1E) ? (void *)0x001F : (void *)0x001E); 00546 //debug.printf("TOGGLE = 0x%x\r\n", -result & 0xf); 00547 } 00548 00549 void xbox360_chatpad_timed_toggle(USBEH_SOF_COUNTER *q) { 00550 int result; 00551 00552 debug_printf("%s() called.\r\n", __FUNCTION__); 00553 00554 result = usbeh_api_control_transfer(deviceNumber, 00555 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 00556 0x00, 00557 (int)q->userData == 0x1F ? 0x001F : 0x001E, 00558 0x0002, 00559 chatpad_trash_buffer, 00560 0, 00561 0, 0); 00562 00563 debug_printf("repeat! 1F/E = 0x%x\r\n", -result & 0xf); 00564 00565 if (1 && !chatpad_toggle_1Bsent) { 00566 chatpad_toggle_1Bsent = 1; 00567 00568 result = usbeh_api_control_transfer(deviceNumber, 00569 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 00570 0x00, 00571 0x001B, 00572 0x0002, 00573 chatpad_trash_buffer, 00574 0, 00575 0, 0); 00576 } 00577 00578 debug_printf("repeat! 1B = 0x%x\r\n", -result & 0xf); 00579 00580 //usbeh_sof_counter_unregister(&chatpad_toggle_timer); 00581 //usbeh_sof_counter_init(&chatpad_toggle_timer, USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, 1700); 00582 //chatpad_toggle_timer.userData = (int)q->userData == 0x1F ? 0x001F : 0x001E; 00583 //chatpad_toggle_timer.callback = xbox360_chatpad_timed; 00584 //chatpad_toggle_timer.flag = 0; 00585 //usbeh_sof_counter_register(&chatpad_toggle_timer); 00586 00587 00588 } 00589 00590 void xbox360_chatpad_init(void) { 00591 int result; 00592 USBEH_U08 buffer[256]; 00593 USBEH_U08 data[256]; 00594 00595 // int usbeh_api_control_transfer(int device, 00596 // int request_type, 00597 // int request, 00598 // int value, 00599 // int index, 00600 // USBEH_U08 *data, 00601 // int length, 00602 // USBEH_callback callback, void *userData) { 00603 // int r = usbeh_api_control_transfer(device, USBEH_DEVICE_TO_HOST | USBEH_REQUEST_TYPE_CLASS | USBEH_RECIPIENT_DEVICE, USBEH_GET_DESCRIPTOR, (USBEH_DESCRIPTOR_TYPE_HUB << 8), 0, buffer, sizeof(buffer), 0, 0); 00604 00605 result = usbeh_api_control_transfer(deviceNumber, 00606 USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 00607 0x01, 00608 0x0000, 00609 0x0000, 00610 buffer, 00611 4, 00612 0, 0); 00613 debug_printf("Step 1 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00614 00615 result = usbeh_api_control_transfer(deviceNumber, 00616 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 00617 0xA9, 00618 0xA30C, 00619 0x4423, 00620 buffer, 00621 0, 00622 0, 0); 00623 debug_printf("Step 2 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00624 00625 result = usbeh_api_control_transfer(deviceNumber, 00626 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 00627 0xA9, 00628 0x2344, 00629 0x7F03, 00630 buffer, 00631 0, 00632 0, 0); 00633 debug_printf("Step 3 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00634 00635 result = usbeh_api_control_transfer(deviceNumber, 00636 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 00637 0xA9, 00638 0x5839, 00639 0x6832, 00640 buffer, 00641 0, 00642 0, 0); 00643 debug_printf("Step 4 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00644 00645 result = usbeh_api_control_transfer(deviceNumber, 00646 USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 00647 0xA1, 00648 0x0000, 00649 0xE416, 00650 buffer, 00651 2, 00652 0, 0); 00653 debug_printf("Step 5 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00654 00655 data[0] = 9; data[1] = 0; 00656 result = usbeh_api_control_transfer(deviceNumber, 00657 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 00658 0xA1, 00659 0x5839, 00660 0xE416, 00661 data, 00662 2, 00663 0, 0); 00664 debug_printf("Step 6 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00665 00666 result = usbeh_api_control_transfer(deviceNumber, 00667 USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, 00668 0xA1, 00669 0x0000, 00670 0xE416, 00671 buffer, 00672 2, 00673 0, 0); 00674 debug_printf("Step 7 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00675 00676 // Now begin toggling 1F / 1E 00677 chatpad_toggle = 0x1E; 00678 result = usbeh_api_control_transfer(deviceNumber, 00679 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 00680 0x00, 00681 0x001F, 00682 0x0002, 00683 chatpad_trash_buffer, 00684 0, 00685 xbox360_chatpad_toggle, 00686 (void *)0x1E); 00687 debug_printf("Step 8 TOGGLE = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00688 00689 result = usbeh_api_control_transfer(deviceNumber, 00690 USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, 00691 0x00, 00692 0x0003, 00693 0x0002, 00694 chatpad_trash_buffer, 00695 0, 00696 0, 00697 0); 00698 debug_printf("Step 9 OUT 0x03 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); 00699 00700 //usbeh_sof_counter_init(&chatpad_toggle_timer, USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, 1700); 00701 //chatpad_toggle_timer.userData = (int)chatpad_toggle; 00702 //chatpad_toggle_timer.callback = xbox360_chatpad_timed; 00703 //usbeh_sof_counter_register(&chatpad_toggle_timer); 00704 00705 } 00706 00707 #endif
Generated on Tue Jul 12 2022 18:05:35 by 1.7.2