Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers xbox360gamepad.c Source File

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