Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
usbeh/xbox360gamepad.c@0:0a841b89d614, 2010-10-11 (annotated)
- Committer:
- AjK
- Date:
- Mon Oct 11 10:34:55 2010 +0000
- Revision:
- 0:0a841b89d614
Totally Alpha quality as this project isn\t completed. Just publishing it as it answers many questions asked in the forums
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AjK | 0:0a841b89d614 | 1 | /**************************************************************************** |
AjK | 0:0a841b89d614 | 2 | * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd |
AjK | 0:0a841b89d614 | 3 | * |
AjK | 0:0a841b89d614 | 4 | * This file is part of the Satellite Observers Workbench (SOWB). |
AjK | 0:0a841b89d614 | 5 | * |
AjK | 0:0a841b89d614 | 6 | * SOWB is free software: you can redistribute it and/or modify |
AjK | 0:0a841b89d614 | 7 | * it under the terms of the GNU General Public License as published by |
AjK | 0:0a841b89d614 | 8 | * the Free Software Foundation, either version 3 of the License, or |
AjK | 0:0a841b89d614 | 9 | * (at your option) any later version. |
AjK | 0:0a841b89d614 | 10 | * |
AjK | 0:0a841b89d614 | 11 | * SOWB is distributed in the hope that it will be useful, |
AjK | 0:0a841b89d614 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
AjK | 0:0a841b89d614 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
AjK | 0:0a841b89d614 | 14 | * GNU General Public License for more details. |
AjK | 0:0a841b89d614 | 15 | * |
AjK | 0:0a841b89d614 | 16 | * You should have received a copy of the GNU General Public License |
AjK | 0:0a841b89d614 | 17 | * along with SOWB. If not, see <http://www.gnu.org/licenses/>. |
AjK | 0:0a841b89d614 | 18 | * |
AjK | 0:0a841b89d614 | 19 | * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $ |
AjK | 0:0a841b89d614 | 20 | * |
AjK | 0:0a841b89d614 | 21 | ***************************************************************************/ |
AjK | 0:0a841b89d614 | 22 | |
AjK | 0:0a841b89d614 | 23 | #include "sowb.h" |
AjK | 0:0a841b89d614 | 24 | #include "debug.h" |
AjK | 0:0a841b89d614 | 25 | #include "usbeh_api.h" |
AjK | 0:0a841b89d614 | 26 | #include "usbeh_endpoint.h" |
AjK | 0:0a841b89d614 | 27 | #include "usbeh_device.h" |
AjK | 0:0a841b89d614 | 28 | #include "usbeh_controller.h" |
AjK | 0:0a841b89d614 | 29 | #include "xbox360gamepad.h" |
AjK | 0:0a841b89d614 | 30 | |
AjK | 0:0a841b89d614 | 31 | #include "main.h" |
AjK | 0:0a841b89d614 | 32 | |
AjK | 0:0a841b89d614 | 33 | /* Define an array of data structures for the buttons. */ |
AjK | 0:0a841b89d614 | 34 | static XBOX360_BUTTON buttons[16]; |
AjK | 0:0a841b89d614 | 35 | static unsigned char button_buffer[16]; |
AjK | 0:0a841b89d614 | 36 | static unsigned char button_buffer_in; |
AjK | 0:0a841b89d614 | 37 | static unsigned char button_buffer_out; |
AjK | 0:0a841b89d614 | 38 | |
AjK | 0:0a841b89d614 | 39 | /* Place holders for left and right triggers. */ |
AjK | 0:0a841b89d614 | 40 | static unsigned char trigger_left; |
AjK | 0:0a841b89d614 | 41 | static unsigned char trigger_right; |
AjK | 0:0a841b89d614 | 42 | |
AjK | 0:0a841b89d614 | 43 | static XBOX360_STICK stick_left; |
AjK | 0:0a841b89d614 | 44 | static XBOX360_STICK stick_right; |
AjK | 0:0a841b89d614 | 45 | |
AjK | 0:0a841b89d614 | 46 | /* A map of wired Xbox 360 controllers. |
AjK | 0:0a841b89d614 | 47 | Data copied from the Linux xboxdrv project, thx :) |
AjK | 0:0a841b89d614 | 48 | http://pingus.seul.org/~grumbel/xboxdrv */ |
AjK | 0:0a841b89d614 | 49 | static XBOX360_DEVICE xbox360_devices[] = { |
AjK | 0:0a841b89d614 | 50 | { 0x045e, 0x028e, "Microsoft Xbox 360 Controller" }, |
AjK | 0:0a841b89d614 | 51 | { 0x0738, 0x4716, "Mad Catz Xbox 360 Controller" }, |
AjK | 0:0a841b89d614 | 52 | { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller" }, |
AjK | 0:0a841b89d614 | 53 | { 0x0738, 0x4740, "Mad Catz Beat Pad" }, |
AjK | 0:0a841b89d614 | 54 | { 0x0738, 0xf738, "Super SFIV FightStick TE S" }, |
AjK | 0:0a841b89d614 | 55 | { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick" }, |
AjK | 0:0a841b89d614 | 56 | { 0x0f0d, 0x000d, "Hori Fighting Stick Ex2" }, |
AjK | 0:0a841b89d614 | 57 | { 0x0f0d, 0x0016, "Hori Real Arcade Pro Ex" }, |
AjK | 0:0a841b89d614 | 58 | { 0x162e, 0xbeef, "Joytech Neo-Se Take2" }, |
AjK | 0:0a841b89d614 | 59 | { 0x046d, 0xc242, "Logitech ChillStream" }, |
AjK | 0:0a841b89d614 | 60 | { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360" }, |
AjK | 0:0a841b89d614 | 61 | { 0x0e6f, 0x0201, "Pelican TSZ360 Pad" }, |
AjK | 0:0a841b89d614 | 62 | { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2" }, // Here's one I found that isn't in the Linux distro. |
AjK | 0:0a841b89d614 | 63 | { 0x0000, 0x0000, "End of list" } |
AjK | 0:0a841b89d614 | 64 | }; |
AjK | 0:0a841b89d614 | 65 | |
AjK | 0:0a841b89d614 | 66 | /* Although Microsoft has not published any data or specifications |
AjK | 0:0a841b89d614 | 67 | regarding the Xbox360 gamepad/controller, it's basic makeup is |
AjK | 0:0a841b89d614 | 68 | well known. Define here the pipes for the interfaces we are |
AjK | 0:0a841b89d614 | 69 | interested in. */ |
AjK | 0:0a841b89d614 | 70 | |
AjK | 0:0a841b89d614 | 71 | #define XBOX360_GAMEPAD_PIPE_BUFFER_SIZE 32 |
AjK | 0:0a841b89d614 | 72 | |
AjK | 0:0a841b89d614 | 73 | typedef struct { |
AjK | 0:0a841b89d614 | 74 | USBEH_U08 data_in[XBOX360_GAMEPAD_PIPE_BUFFER_SIZE]; |
AjK | 0:0a841b89d614 | 75 | USBEH_U08 data_out[XBOX360_GAMEPAD_PIPE_BUFFER_SIZE]; |
AjK | 0:0a841b89d614 | 76 | USBEH_U08 ep_number_in; |
AjK | 0:0a841b89d614 | 77 | USBEH_U08 ep_number_out; |
AjK | 0:0a841b89d614 | 78 | } XBOX360_PIPE; |
AjK | 0:0a841b89d614 | 79 | |
AjK | 0:0a841b89d614 | 80 | typedef struct { |
AjK | 0:0a841b89d614 | 81 | USBEH_U08 data_in[256]; |
AjK | 0:0a841b89d614 | 82 | USBEH_U08 data_out[256]; |
AjK | 0:0a841b89d614 | 83 | USBEH_U08 ep_number_in; |
AjK | 0:0a841b89d614 | 84 | USBEH_U08 ep_number_out; |
AjK | 0:0a841b89d614 | 85 | } XBOX360_CONTROL_PIPE; |
AjK | 0:0a841b89d614 | 86 | |
AjK | 0:0a841b89d614 | 87 | struct _xbox360_gamepad_vendor { |
AjK | 0:0a841b89d614 | 88 | XBOX360_CONTROL_PIPE pipe[1]; |
AjK | 0:0a841b89d614 | 89 | } IF_VENDOR __attribute__((aligned(256))); |
AjK | 0:0a841b89d614 | 90 | |
AjK | 0:0a841b89d614 | 91 | struct _xbox360_gamepad_interface0 { |
AjK | 0:0a841b89d614 | 92 | XBOX360_PIPE pipe[1]; |
AjK | 0:0a841b89d614 | 93 | } IF_ZERO __attribute__((aligned(256))); |
AjK | 0:0a841b89d614 | 94 | |
AjK | 0:0a841b89d614 | 95 | struct _xbox360_gamepad_interface1 { |
AjK | 0:0a841b89d614 | 96 | XBOX360_PIPE pipe[2]; |
AjK | 0:0a841b89d614 | 97 | } IF_ONE __attribute__((aligned(256))); |
AjK | 0:0a841b89d614 | 98 | |
AjK | 0:0a841b89d614 | 99 | struct _xbox360_gamepad_interface2 { |
AjK | 0:0a841b89d614 | 100 | XBOX360_PIPE pipe[1]; |
AjK | 0:0a841b89d614 | 101 | } IF_TWO __attribute__((aligned(256))); |
AjK | 0:0a841b89d614 | 102 | |
AjK | 0:0a841b89d614 | 103 | int deviceNumber; |
AjK | 0:0a841b89d614 | 104 | |
AjK | 0:0a841b89d614 | 105 | int xbox360gamepad_init(void) { |
AjK | 0:0a841b89d614 | 106 | DEBUG_INIT_START; |
AjK | 0:0a841b89d614 | 107 | for (int i = 0; i < 16; i++) { |
AjK | 0:0a841b89d614 | 108 | buttons[i].state = BUTTON_RELEASED; |
AjK | 0:0a841b89d614 | 109 | buttons[i].count = 0; |
AjK | 0:0a841b89d614 | 110 | button_buffer[i] = 0xFF; |
AjK | 0:0a841b89d614 | 111 | usbeh_sof_counter_init(&buttons[i].pressHold, USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, BUTTON_HOLD_TIME); |
AjK | 0:0a841b89d614 | 112 | buttons[i].pressHold.userData = i; |
AjK | 0:0a841b89d614 | 113 | buttons[i].pressHold.callback = xbox360gamepad_button_hold_callback; |
AjK | 0:0a841b89d614 | 114 | usbeh_sof_counter_register(&buttons[i].pressHold); |
AjK | 0:0a841b89d614 | 115 | } |
AjK | 0:0a841b89d614 | 116 | button_buffer_in = 0; |
AjK | 0:0a841b89d614 | 117 | button_buffer_out = 0; |
AjK | 0:0a841b89d614 | 118 | trigger_left = 0; |
AjK | 0:0a841b89d614 | 119 | trigger_right = 0; |
AjK | 0:0a841b89d614 | 120 | stick_left.x = 0; |
AjK | 0:0a841b89d614 | 121 | stick_left.y = 0; |
AjK | 0:0a841b89d614 | 122 | stick_right.x = 0; |
AjK | 0:0a841b89d614 | 123 | stick_right.y = 0; |
AjK | 0:0a841b89d614 | 124 | DEBUG_INIT_END; |
AjK | 0:0a841b89d614 | 125 | return 0; |
AjK | 0:0a841b89d614 | 126 | } |
AjK | 0:0a841b89d614 | 127 | |
AjK | 0:0a841b89d614 | 128 | void xbox360gamepad_process(void) { |
AjK | 0:0a841b89d614 | 129 | // This currently does nothing. |
AjK | 0:0a841b89d614 | 130 | } |
AjK | 0:0a841b89d614 | 131 | |
AjK | 0:0a841b89d614 | 132 | void xbox360gamepad_button_press(unsigned char button) { |
AjK | 0:0a841b89d614 | 133 | button_buffer[button_buffer_in] = button; |
AjK | 0:0a841b89d614 | 134 | button_buffer_in++; |
AjK | 0:0a841b89d614 | 135 | button_buffer_in &= 0x0F; |
AjK | 0:0a841b89d614 | 136 | } |
AjK | 0:0a841b89d614 | 137 | |
AjK | 0:0a841b89d614 | 138 | char xbox360gamepad_get_button(void) { |
AjK | 0:0a841b89d614 | 139 | if (button_buffer_in == button_buffer_out) { |
AjK | 0:0a841b89d614 | 140 | return 0; |
AjK | 0:0a841b89d614 | 141 | } |
AjK | 0:0a841b89d614 | 142 | |
AjK | 0:0a841b89d614 | 143 | char button = button_buffer[button_buffer_out]; |
AjK | 0:0a841b89d614 | 144 | button_buffer_out++; |
AjK | 0:0a841b89d614 | 145 | button_buffer_out &= 0x0F; |
AjK | 0:0a841b89d614 | 146 | return button; |
AjK | 0:0a841b89d614 | 147 | } |
AjK | 0:0a841b89d614 | 148 | |
AjK | 0:0a841b89d614 | 149 | char xbox360gamepad_get_button_preview(void) { |
AjK | 0:0a841b89d614 | 150 | if (button_buffer_in == button_buffer_out) { |
AjK | 0:0a841b89d614 | 151 | return 0; |
AjK | 0:0a841b89d614 | 152 | } |
AjK | 0:0a841b89d614 | 153 | |
AjK | 0:0a841b89d614 | 154 | char button = button_buffer[button_buffer_out]; |
AjK | 0:0a841b89d614 | 155 | return button; |
AjK | 0:0a841b89d614 | 156 | } |
AjK | 0:0a841b89d614 | 157 | |
AjK | 0:0a841b89d614 | 158 | unsigned char xbox360gamepad_get_trigger_left(void) { |
AjK | 0:0a841b89d614 | 159 | return trigger_left; |
AjK | 0:0a841b89d614 | 160 | } |
AjK | 0:0a841b89d614 | 161 | |
AjK | 0:0a841b89d614 | 162 | unsigned char xbox360gamepad_get_trigger_right(void) { |
AjK | 0:0a841b89d614 | 163 | return trigger_right; |
AjK | 0:0a841b89d614 | 164 | } |
AjK | 0:0a841b89d614 | 165 | |
AjK | 0:0a841b89d614 | 166 | XBOX360_STICK * xbox360gamepad_get_stick_left(void) { |
AjK | 0:0a841b89d614 | 167 | return &stick_left; |
AjK | 0:0a841b89d614 | 168 | } |
AjK | 0:0a841b89d614 | 169 | |
AjK | 0:0a841b89d614 | 170 | XBOX360_STICK * xbox360gamepad_get_stick_right(void) { |
AjK | 0:0a841b89d614 | 171 | return &stick_right; |
AjK | 0:0a841b89d614 | 172 | } |
AjK | 0:0a841b89d614 | 173 | |
AjK | 0:0a841b89d614 | 174 | void xbox360gamepad_button_hold_callback(USBEH_SOF_COUNTER *q) { |
AjK | 0:0a841b89d614 | 175 | int i = (int)q->userData; |
AjK | 0:0a841b89d614 | 176 | if (buttons[i].state == BUTTON_PRESSED) { |
AjK | 0:0a841b89d614 | 177 | xbox360gamepad_button_press((char)(i + 1 + 32)); |
AjK | 0:0a841b89d614 | 178 | } |
AjK | 0:0a841b89d614 | 179 | } |
AjK | 0:0a841b89d614 | 180 | |
AjK | 0:0a841b89d614 | 181 | /** |
AjK | 0:0a841b89d614 | 182 | * xbox360gamepad_interface_0_in |
AjK | 0:0a841b89d614 | 183 | * |
AjK | 0:0a841b89d614 | 184 | * A callback function to handle interface0 pipe0 data. |
AjK | 0:0a841b89d614 | 185 | */ |
AjK | 0:0a841b89d614 | 186 | void xbox360gamepad_interface_0_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { |
AjK | 0:0a841b89d614 | 187 | unsigned button_flags; |
AjK | 0:0a841b89d614 | 188 | |
AjK | 0:0a841b89d614 | 189 | /* Is this a button press report? */ |
AjK | 0:0a841b89d614 | 190 | if(IF_ZERO.pipe[(int)userData].data_in[0] == 0 && IF_ZERO.pipe[(int)userData].data_in[1] == 0x14) { |
AjK | 0:0a841b89d614 | 191 | |
AjK | 0:0a841b89d614 | 192 | /* Handle the button flags. */ |
AjK | 0:0a841b89d614 | 193 | button_flags = ((IF_ZERO.pipe[(int)userData].data_in[2] & 0xFF) << 8) | (IF_ZERO.pipe[(int)userData].data_in[3] & 0xFF); |
AjK | 0:0a841b89d614 | 194 | for (int i = 0; i < 16; i++) { |
AjK | 0:0a841b89d614 | 195 | if ((button_flags & (1 << i)) != 0) { |
AjK | 0:0a841b89d614 | 196 | if (buttons[i].state == BUTTON_RELEASED) { |
AjK | 0:0a841b89d614 | 197 | buttons[i].state = BUTTON_PRESSED; |
AjK | 0:0a841b89d614 | 198 | buttons[i].count++; |
AjK | 0:0a841b89d614 | 199 | buttons[i].pressHold.flag = 0; |
AjK | 0:0a841b89d614 | 200 | xbox360gamepad_button_press((char)(i + 1)); |
AjK | 0:0a841b89d614 | 201 | } |
AjK | 0:0a841b89d614 | 202 | } |
AjK | 0:0a841b89d614 | 203 | else { |
AjK | 0:0a841b89d614 | 204 | if (buttons[i].state == BUTTON_PRESSED) { |
AjK | 0:0a841b89d614 | 205 | buttons[i].state = BUTTON_RELEASED; |
AjK | 0:0a841b89d614 | 206 | buttons[i].pressHold.flag = 1; |
AjK | 0:0a841b89d614 | 207 | buttons[i].pressHold.counter = BUTTON_HOLD_TIME; |
AjK | 0:0a841b89d614 | 208 | buttons[i].count = 0; |
AjK | 0:0a841b89d614 | 209 | xbox360gamepad_button_press((char)(i + 1 + 16)); |
AjK | 0:0a841b89d614 | 210 | } |
AjK | 0:0a841b89d614 | 211 | } |
AjK | 0:0a841b89d614 | 212 | } |
AjK | 0:0a841b89d614 | 213 | |
AjK | 0:0a841b89d614 | 214 | /* Handle the analogue triggers. */ |
AjK | 0:0a841b89d614 | 215 | trigger_left = (unsigned char)IF_ZERO.pipe[(int)userData].data_in[4]; |
AjK | 0:0a841b89d614 | 216 | trigger_right = (unsigned char)IF_ZERO.pipe[(int)userData].data_in[5]; |
AjK | 0:0a841b89d614 | 217 | |
AjK | 0:0a841b89d614 | 218 | /* Handle the analogue sticks. */ |
AjK | 0:0a841b89d614 | 219 | { |
AjK | 0:0a841b89d614 | 220 | short x, y; |
AjK | 0:0a841b89d614 | 221 | x = (short)((IF_ZERO.pipe[(int)userData].data_in[6]) | IF_ZERO.pipe[(int)userData].data_in[7] << 8); |
AjK | 0:0a841b89d614 | 222 | y = (short)((IF_ZERO.pipe[(int)userData].data_in[8]) | IF_ZERO.pipe[(int)userData].data_in[9] << 8); |
AjK | 0:0a841b89d614 | 223 | if (x != stick_left.x_previous) { |
AjK | 0:0a841b89d614 | 224 | stick_left.x_previous = stick_left.x; |
AjK | 0:0a841b89d614 | 225 | stick_left.x = x; |
AjK | 0:0a841b89d614 | 226 | } |
AjK | 0:0a841b89d614 | 227 | if (y != stick_left.y_previous) { |
AjK | 0:0a841b89d614 | 228 | stick_left.y_previous = stick_left.y; |
AjK | 0:0a841b89d614 | 229 | stick_left.y = y; |
AjK | 0:0a841b89d614 | 230 | } |
AjK | 0:0a841b89d614 | 231 | x = (short)((IF_ZERO.pipe[(int)userData].data_in[10]) | IF_ZERO.pipe[(int)userData].data_in[11] << 8); |
AjK | 0:0a841b89d614 | 232 | y = (short)((IF_ZERO.pipe[(int)userData].data_in[12]) | IF_ZERO.pipe[(int)userData].data_in[13] << 8); |
AjK | 0:0a841b89d614 | 233 | if (x != stick_right.x_previous) { |
AjK | 0:0a841b89d614 | 234 | stick_right.x_previous = stick_right.x; |
AjK | 0:0a841b89d614 | 235 | stick_right.x = x; |
AjK | 0:0a841b89d614 | 236 | } |
AjK | 0:0a841b89d614 | 237 | if (y != stick_right.y_previous) { |
AjK | 0:0a841b89d614 | 238 | stick_right.y_previous = stick_right.y; |
AjK | 0:0a841b89d614 | 239 | stick_right.y = y; |
AjK | 0:0a841b89d614 | 240 | } |
AjK | 0:0a841b89d614 | 241 | } |
AjK | 0:0a841b89d614 | 242 | } |
AjK | 0:0a841b89d614 | 243 | else if(len == 3) { |
AjK | 0:0a841b89d614 | 244 | /* Chatpad return? */ |
AjK | 0:0a841b89d614 | 245 | #ifdef DEBUG_USB_DRIVER_IF_0 |
AjK | 0:0a841b89d614 | 246 | debug_printf("Got %02x %02x %02x \r\n", buf[0], buf[1], buf[2]); |
AjK | 0:0a841b89d614 | 247 | #endif |
AjK | 0:0a841b89d614 | 248 | } |
AjK | 0:0a841b89d614 | 249 | else { |
AjK | 0:0a841b89d614 | 250 | #ifdef DEBUG_USB_DRIVER_IF_0 |
AjK | 0:0a841b89d614 | 251 | DEBUG_UNKNOWN_PACKET_IF_0 |
AjK | 0:0a841b89d614 | 252 | #endif |
AjK | 0:0a841b89d614 | 253 | } |
AjK | 0:0a841b89d614 | 254 | |
AjK | 0:0a841b89d614 | 255 | /* Schedule another transfer to keep the IN flow of data coming. */ |
AjK | 0:0a841b89d614 | 256 | usbeh_api_interrupt_transfer(device, endpoint, IF_ZERO.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_0_in, userData); |
AjK | 0:0a841b89d614 | 257 | } |
AjK | 0:0a841b89d614 | 258 | |
AjK | 0:0a841b89d614 | 259 | void xbox360gamepad_interface_1_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { |
AjK | 0:0a841b89d614 | 260 | /* We don't currently do anything with Interface:1 */ |
AjK | 0:0a841b89d614 | 261 | #ifdef DEBUG_USB_DRIVER_IF_1 |
AjK | 0:0a841b89d614 | 262 | DEBUG_UNKNOWN_PACKET_IF_1 |
AjK | 0:0a841b89d614 | 263 | #endif |
AjK | 0:0a841b89d614 | 264 | |
AjK | 0:0a841b89d614 | 265 | /* Schedule another transfer to keep the IN flow of data coming. */ |
AjK | 0:0a841b89d614 | 266 | usbeh_api_interrupt_transfer(device, endpoint, IF_ONE.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_1_in, userData); |
AjK | 0:0a841b89d614 | 267 | } |
AjK | 0:0a841b89d614 | 268 | |
AjK | 0:0a841b89d614 | 269 | void xbox360gamepad_interface_2_in(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { |
AjK | 0:0a841b89d614 | 270 | /* We don't currently do anything with Interface:2 */ |
AjK | 0:0a841b89d614 | 271 | #ifdef DEBUG_USB_DRIVER_IF_2 |
AjK | 0:0a841b89d614 | 272 | DEBUG_UNKNOWN_PACKET_IF_2 |
AjK | 0:0a841b89d614 | 273 | #endif |
AjK | 0:0a841b89d614 | 274 | |
AjK | 0:0a841b89d614 | 275 | /* Schedule another transfer to keep the IN flow of data coming. */ |
AjK | 0:0a841b89d614 | 276 | usbeh_api_interrupt_transfer(device, endpoint, IF_TWO.pipe[(int)userData].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_2_in, userData); |
AjK | 0:0a841b89d614 | 277 | } |
AjK | 0:0a841b89d614 | 278 | |
AjK | 0:0a841b89d614 | 279 | int xbox360gamepad_add_interface(int device, USBEH_interfaceDescriptor *iface, USBEH_endpointDescriptor *ed) { |
AjK | 0:0a841b89d614 | 280 | |
AjK | 0:0a841b89d614 | 281 | /* Handle interrupt IN transfers. */ |
AjK | 0:0a841b89d614 | 282 | if ((ed->bmAttributes & 3) != USBEH_ENDPOINT_INTERRUPT) { |
AjK | 0:0a841b89d614 | 283 | return 0; |
AjK | 0:0a841b89d614 | 284 | } |
AjK | 0:0a841b89d614 | 285 | |
AjK | 0:0a841b89d614 | 286 | if (iface->bInterfaceNumber == 0) { |
AjK | 0:0a841b89d614 | 287 | int pipe = 0; |
AjK | 0:0a841b89d614 | 288 | if (ed->bEndpointAddress & 0x80) { |
AjK | 0:0a841b89d614 | 289 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 290 | DEBUG_USB_MSG_ALLOCATION |
AjK | 0:0a841b89d614 | 291 | #endif |
AjK | 0:0a841b89d614 | 292 | IF_ZERO.pipe[pipe].ep_number_in = ed->bEndpointAddress; |
AjK | 0:0a841b89d614 | 293 | usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_ZERO.pipe[0].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_0_in, (void *)pipe); |
AjK | 0:0a841b89d614 | 294 | } |
AjK | 0:0a841b89d614 | 295 | else { |
AjK | 0:0a841b89d614 | 296 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 297 | DEBUG_USB_MSG_ALLOCATION |
AjK | 0:0a841b89d614 | 298 | #endif |
AjK | 0:0a841b89d614 | 299 | IF_ZERO.pipe[pipe].ep_number_out = ed->bEndpointAddress; |
AjK | 0:0a841b89d614 | 300 | } |
AjK | 0:0a841b89d614 | 301 | } |
AjK | 0:0a841b89d614 | 302 | |
AjK | 0:0a841b89d614 | 303 | if (iface->bInterfaceNumber == 1) { |
AjK | 0:0a841b89d614 | 304 | int pipe = (IF_ONE.pipe[0].ep_number_in == 0) ? 0 : 1; |
AjK | 0:0a841b89d614 | 305 | if (ed->bEndpointAddress & 0x80) { |
AjK | 0:0a841b89d614 | 306 | IF_ONE.pipe[pipe].ep_number_in = ed->bEndpointAddress; |
AjK | 0:0a841b89d614 | 307 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 308 | DEBUG_USB_MSG_ALLOCATION |
AjK | 0:0a841b89d614 | 309 | #endif |
AjK | 0:0a841b89d614 | 310 | usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_ONE.pipe[pipe].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_1_in, (void *)pipe); |
AjK | 0:0a841b89d614 | 311 | } |
AjK | 0:0a841b89d614 | 312 | else { |
AjK | 0:0a841b89d614 | 313 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 314 | DEBUG_USB_MSG_ALLOCATION |
AjK | 0:0a841b89d614 | 315 | #endif |
AjK | 0:0a841b89d614 | 316 | IF_ONE.pipe[pipe].ep_number_out = ed->bEndpointAddress; |
AjK | 0:0a841b89d614 | 317 | } |
AjK | 0:0a841b89d614 | 318 | } |
AjK | 0:0a841b89d614 | 319 | |
AjK | 0:0a841b89d614 | 320 | |
AjK | 0:0a841b89d614 | 321 | if (iface->bInterfaceNumber == 2) { |
AjK | 0:0a841b89d614 | 322 | int pipe = (IF_TWO.pipe[0].ep_number_in == 0) ? 0 : 1; |
AjK | 0:0a841b89d614 | 323 | if (ed->bEndpointAddress & 0x80) { |
AjK | 0:0a841b89d614 | 324 | IF_TWO.pipe[pipe].ep_number_in = ed->bEndpointAddress; |
AjK | 0:0a841b89d614 | 325 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 326 | DEBUG_USB_MSG_ALLOCATION |
AjK | 0:0a841b89d614 | 327 | #endif |
AjK | 0:0a841b89d614 | 328 | usbeh_api_interrupt_transfer(device, ed->bEndpointAddress, IF_TWO.pipe[pipe].data_in, XBOX360_GAMEPAD_PIPE_BUFFER_SIZE, xbox360gamepad_interface_2_in, (void *)pipe); |
AjK | 0:0a841b89d614 | 329 | } |
AjK | 0:0a841b89d614 | 330 | else { |
AjK | 0:0a841b89d614 | 331 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 332 | DEBUG_USB_MSG_ALLOCATION |
AjK | 0:0a841b89d614 | 333 | #endif |
AjK | 0:0a841b89d614 | 334 | IF_TWO.pipe[pipe].ep_number_out = ed->bEndpointAddress; |
AjK | 0:0a841b89d614 | 335 | } |
AjK | 0:0a841b89d614 | 336 | } |
AjK | 0:0a841b89d614 | 337 | |
AjK | 0:0a841b89d614 | 338 | return 1; |
AjK | 0:0a841b89d614 | 339 | } |
AjK | 0:0a841b89d614 | 340 | |
AjK | 0:0a841b89d614 | 341 | static XBOX360_DEVICE * xbox360gamepad_vendor_product_check(uint16_t vendorId, uint16_t productId) { |
AjK | 0:0a841b89d614 | 342 | for (int i = 0; xbox360_devices[i].idVendor != 0; i++) { |
AjK | 0:0a841b89d614 | 343 | if (xbox360_devices[i].idVendor == vendorId && xbox360_devices[i].idProduct == productId) { |
AjK | 0:0a841b89d614 | 344 | return &xbox360_devices[i]; |
AjK | 0:0a841b89d614 | 345 | } |
AjK | 0:0a841b89d614 | 346 | } |
AjK | 0:0a841b89d614 | 347 | return (XBOX360_DEVICE *)NULL; |
AjK | 0:0a841b89d614 | 348 | } |
AjK | 0:0a841b89d614 | 349 | |
AjK | 0:0a841b89d614 | 350 | void xbox360gamepad_led(int code) { |
AjK | 0:0a841b89d614 | 351 | IF_ZERO.pipe[0].data_out[0] = 0x01; |
AjK | 0:0a841b89d614 | 352 | IF_ZERO.pipe[0].data_out[1] = 0x03; |
AjK | 0:0a841b89d614 | 353 | IF_ZERO.pipe[0].data_out[2] = code; |
AjK | 0:0a841b89d614 | 354 | usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, IF_ZERO.pipe[0].data_out, 3, NULL, NULL); |
AjK | 0:0a841b89d614 | 355 | } |
AjK | 0:0a841b89d614 | 356 | |
AjK | 0:0a841b89d614 | 357 | USBEH_U08 noise[] = "\x0\x8\x0\x0\x0\x0\x0\x0"; |
AjK | 0:0a841b89d614 | 358 | |
AjK | 0:0a841b89d614 | 359 | void xbox360_noise(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { |
AjK | 0:0a841b89d614 | 360 | usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, noise, 8, xbox360_noise, NULL); |
AjK | 0:0a841b89d614 | 361 | } |
AjK | 0:0a841b89d614 | 362 | |
AjK | 0:0a841b89d614 | 363 | int xbox360gamepad_onload_callback(int device, USBEH_deviceDescriptor *deviceDesc, USBEH_interfaceDescriptor **interfaceDesc) { |
AjK | 0:0a841b89d614 | 364 | USBEH_interfaceDescriptor *iface; |
AjK | 0:0a841b89d614 | 365 | int length, endpoint_count, interfaceCounter = 0; |
AjK | 0:0a841b89d614 | 366 | USBEH_U08 *start, *end; |
AjK | 0:0a841b89d614 | 367 | |
AjK | 0:0a841b89d614 | 368 | /* Is this a Microsoft Xbox360 wired Gamepad? */ |
AjK | 0:0a841b89d614 | 369 | XBOX360_DEVICE *xd = xbox360gamepad_vendor_product_check(deviceDesc->idVendor, deviceDesc->idProduct); |
AjK | 0:0a841b89d614 | 370 | if (!xd) { |
AjK | 0:0a841b89d614 | 371 | /* If not, don't claim it. */ |
AjK | 0:0a841b89d614 | 372 | return 0; |
AjK | 0:0a841b89d614 | 373 | } |
AjK | 0:0a841b89d614 | 374 | |
AjK | 0:0a841b89d614 | 375 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 376 | debug_printf("Found device '%s'\r\n", xd->name); |
AjK | 0:0a841b89d614 | 377 | #endif |
AjK | 0:0a841b89d614 | 378 | |
AjK | 0:0a841b89d614 | 379 | /* Save our device number in a global. */ |
AjK | 0:0a841b89d614 | 380 | deviceNumber = device; |
AjK | 0:0a841b89d614 | 381 | |
AjK | 0:0a841b89d614 | 382 | memset((char *)&IF_VENDOR, 0, sizeof(IF_VENDOR)); |
AjK | 0:0a841b89d614 | 383 | memset((char *)&IF_ZERO, 0, sizeof(IF_ZERO)); |
AjK | 0:0a841b89d614 | 384 | memset((char *)&IF_ONE, 0, sizeof(IF_ONE)); |
AjK | 0:0a841b89d614 | 385 | memset((char *)&IF_TWO, 0, sizeof(IF_TWO)); |
AjK | 0:0a841b89d614 | 386 | |
AjK | 0:0a841b89d614 | 387 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 388 | debug_printf("%s() ACTIVATED for device id = %d\r\n", __FUNCTION__, device); |
AjK | 0:0a841b89d614 | 389 | debug_printf(" OnLoad VendorId = 0x%04x ProductId = 0x%04x \r\n", deviceDesc->idVendor, deviceDesc->idProduct); |
AjK | 0:0a841b89d614 | 390 | #endif |
AjK | 0:0a841b89d614 | 391 | |
AjK | 0:0a841b89d614 | 392 | /* Parse the interface configuration and setup the endpoint handlers. */ |
AjK | 0:0a841b89d614 | 393 | while ((iface = interfaceDesc[interfaceCounter]) != (USBEH_interfaceDescriptor *)NULL) { |
AjK | 0:0a841b89d614 | 394 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 395 | debug_printf(" interface%d:- \r\n", interfaceCounter); |
AjK | 0:0a841b89d614 | 396 | debug_printf(" InterfaceClass = %02x \r\n", iface->bInterfaceClass); |
AjK | 0:0a841b89d614 | 397 | debug_printf(" InterfaceSubClass = %02x \r\n", iface->bInterfaceSubClass); |
AjK | 0:0a841b89d614 | 398 | debug_printf(" InterfaceProtocol = %02x \r\n", iface->bInterfaceProtocol); |
AjK | 0:0a841b89d614 | 399 | #endif |
AjK | 0:0a841b89d614 | 400 | start = (USBEH_U08 *)iface; |
AjK | 0:0a841b89d614 | 401 | length = start[0]; |
AjK | 0:0a841b89d614 | 402 | end = start + length; |
AjK | 0:0a841b89d614 | 403 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 404 | debug_printf(" Scanning at start:%08x length:%d end:%08x \r\n", start, length, end); |
AjK | 0:0a841b89d614 | 405 | #endif |
AjK | 0:0a841b89d614 | 406 | while (start < end) { |
AjK | 0:0a841b89d614 | 407 | if (start[1] == USBEH_DESCRIPTOR_TYPE_INTERFACE) { |
AjK | 0:0a841b89d614 | 408 | USBEH_interfaceDescriptor *id = (USBEH_interfaceDescriptor *)start; |
AjK | 0:0a841b89d614 | 409 | //int interfaceNumber = (int)id->bInterfaceNumber; |
AjK | 0:0a841b89d614 | 410 | endpoint_count = (int)id->bNumEndpoints; |
AjK | 0:0a841b89d614 | 411 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 412 | debug_printf(" found definition for if:%d with %d endpoints.\r\n", interfaceNumber, endpoint_count); |
AjK | 0:0a841b89d614 | 413 | #endif |
AjK | 0:0a841b89d614 | 414 | start += start[0]; |
AjK | 0:0a841b89d614 | 415 | while (endpoint_count > 0) { |
AjK | 0:0a841b89d614 | 416 | if (start[1] == USBEH_DESCRIPTOR_TYPE_ENDPOINT) { |
AjK | 0:0a841b89d614 | 417 | USBEH_endpointDescriptor *ed = (USBEH_endpointDescriptor *)start; |
AjK | 0:0a841b89d614 | 418 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 419 | debug_printf(" found endpoint 0x%02X\r\n", ed->bEndpointAddress); |
AjK | 0:0a841b89d614 | 420 | #endif |
AjK | 0:0a841b89d614 | 421 | xbox360gamepad_add_interface(device, id, ed); |
AjK | 0:0a841b89d614 | 422 | endpoint_count--; |
AjK | 0:0a841b89d614 | 423 | } |
AjK | 0:0a841b89d614 | 424 | else { |
AjK | 0:0a841b89d614 | 425 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 426 | debug_printf(" no endpoint for interface, descriptor class: %02X\r\n", start[1]); |
AjK | 0:0a841b89d614 | 427 | #endif |
AjK | 0:0a841b89d614 | 428 | } |
AjK | 0:0a841b89d614 | 429 | start += start[0]; |
AjK | 0:0a841b89d614 | 430 | } |
AjK | 0:0a841b89d614 | 431 | } |
AjK | 0:0a841b89d614 | 432 | else { |
AjK | 0:0a841b89d614 | 433 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 434 | debug_printf(" no IF descr found at %08x\r\n", start); |
AjK | 0:0a841b89d614 | 435 | #endif |
AjK | 0:0a841b89d614 | 436 | start += start[0]; |
AjK | 0:0a841b89d614 | 437 | } |
AjK | 0:0a841b89d614 | 438 | } |
AjK | 0:0a841b89d614 | 439 | |
AjK | 0:0a841b89d614 | 440 | interfaceCounter++; |
AjK | 0:0a841b89d614 | 441 | } |
AjK | 0:0a841b89d614 | 442 | |
AjK | 0:0a841b89d614 | 443 | #ifdef DEBUG_USB_DRIVER |
AjK | 0:0a841b89d614 | 444 | debug_printf("Device claimed by %s().\r\n\n", __FUNCTION__); |
AjK | 0:0a841b89d614 | 445 | #endif |
AjK | 0:0a841b89d614 | 446 | |
AjK | 0:0a841b89d614 | 447 | /* When the gamepad boots up, the LED ring flashes after it's |
AjK | 0:0a841b89d614 | 448 | configuration is set. Let's flash the led and go steady. */ |
AjK | 0:0a841b89d614 | 449 | xbox360gamepad_led(LED_1_FLASH_THEN_ON); |
AjK | 0:0a841b89d614 | 450 | |
AjK | 0:0a841b89d614 | 451 | /* Lets just send "noise" to the headset and see what happens. */ |
AjK | 0:0a841b89d614 | 452 | //usbeh_api_interrupt_transfer(deviceNumber, IF_ZERO.pipe[0].ep_number_out, noise, 8, xbox360_noise, NULL); |
AjK | 0:0a841b89d614 | 453 | |
AjK | 0:0a841b89d614 | 454 | /* I give up, wtf is it with this chatpad that MS needs to keep so secret? */ |
AjK | 0:0a841b89d614 | 455 | //xbox360_chatpad_init(); |
AjK | 0:0a841b89d614 | 456 | |
AjK | 0:0a841b89d614 | 457 | /* Tell the USB embedded host that we have claimed this device. */ |
AjK | 0:0a841b89d614 | 458 | return 1; |
AjK | 0:0a841b89d614 | 459 | } |
AjK | 0:0a841b89d614 | 460 | |
AjK | 0:0a841b89d614 | 461 | #ifdef NEVERCOMPILETHISCODE |
AjK | 0:0a841b89d614 | 462 | /* |
AjK | 0:0a841b89d614 | 463 | |
AjK | 0:0a841b89d614 | 464 | UPDATE: Everything below is ABANDONED when I basically figured out from one replay to the next |
AjK | 0:0a841b89d614 | 465 | that MS use the security channel to "handshake" init the chatpad. Many people believe |
AjK | 0:0a841b89d614 | 466 | the security device in the gamepad is to "tell the xbox I am a real auth MS gamepad". However, |
AjK | 0:0a841b89d614 | 467 | as I have discovered, it's "two-way". There also exists the "tell the gamepad that an auth |
AjK | 0:0a841b89d614 | 468 | Xbox360 is the host" and without that the chatpad will not function. I have no interest in |
AjK | 0:0a841b89d614 | 469 | trying to crack anyones security chips so no further work will be done on this. |
AjK | 0:0a841b89d614 | 470 | |
AjK | 0:0a841b89d614 | 471 | Everything below here is related to the chatpad attachment for the Xbox360 gamepad controller. |
AjK | 0:0a841b89d614 | 472 | Unlike the sticks, triggers and buttons, the chatpad appears to require some sort of initialization |
AjK | 0:0a841b89d614 | 473 | in order to start running. Since MS have not published any sort of USB protocol specifications |
AjK | 0:0a841b89d614 | 474 | for their gamepad, what we do here is basically a "replay attack" based on packets sent and received |
AjK | 0:0a841b89d614 | 475 | between an Xbox and a gamepad with a USB protocol analyser in the middle. A classic man-in-the-middle |
AjK | 0:0a841b89d614 | 476 | type of attack. |
AjK | 0:0a841b89d614 | 477 | |
AjK | 0:0a841b89d614 | 478 | Here's the basic sequence we attempt to follow:- |
AjK | 0:0a841b89d614 | 479 | |
AjK | 0:0a841b89d614 | 480 | 1. -> Vendor request IN EP0 (0x01) |
AjK | 0:0a841b89d614 | 481 | -> SETUP C0 01 00 00 00 00 04 00 |
AjK | 0:0a841b89d614 | 482 | <- IN 80 03 0D 47 |
AjK | 0:0a841b89d614 | 483 | 2. -> Vendor request OUT EP0 (0xA9) |
AjK | 0:0a841b89d614 | 484 | -> 40 A9 0C A3 23 44 00 |
AjK | 0:0a841b89d614 | 485 | <- Expect STALLED no data |
AjK | 0:0a841b89d614 | 486 | 3. -> Vendor request OUT EP0 (0xA9) |
AjK | 0:0a841b89d614 | 487 | -> 40 A9 44 23 03 7F 00 00 |
AjK | 0:0a841b89d614 | 488 | <- Expect STALLED no data |
AjK | 0:0a841b89d614 | 489 | 4. -> Vendor request OUT EP0 (0xA9) |
AjK | 0:0a841b89d614 | 490 | -> 40 A9 39 58 32 68 00 00 |
AjK | 0:0a841b89d614 | 491 | <- Expect STALLED no data |
AjK | 0:0a841b89d614 | 492 | 5. <- IN IF:0 EP2 3 bytes 01 03 0E |
AjK | 0:0a841b89d614 | 493 | 6. -> Vendor request IN EP0 (0xA1) |
AjK | 0:0a841b89d614 | 494 | -> SETUP C0 A1 00 00 16 E4 02 00 |
AjK | 0:0a841b89d614 | 495 | <- IN 01 00 |
AjK | 0:0a841b89d614 | 496 | 7. -> OUT IF:0 EP1 3 bytes 01 03 01 |
AjK | 0:0a841b89d614 | 497 | 8. -> Vendor request OUT EP0 (0xA1) |
AjK | 0:0a841b89d614 | 498 | -> SETUP 40 A1 00 00 16 E4 02 00 |
AjK | 0:0a841b89d614 | 499 | -> OUT 09 00 |
AjK | 0:0a841b89d614 | 500 | 9. -> Vendor request IN EP0 (0xA1) |
AjK | 0:0a841b89d614 | 501 | -> SETUP C0 A1 00 00 16 E4 02 00 |
AjK | 0:0a841b89d614 | 502 | -> IN 09 00 (echo previous OUT?) |
AjK | 0:0a841b89d614 | 503 | 10. <- IN IF:0 EP 1 3 bytes 02 03 00 |
AjK | 0:0a841b89d614 | 504 | 11. <- IN IF:0 EP 1 3 bytes 03 03 03 |
AjK | 0:0a841b89d614 | 505 | 12. <- IN IF:0 EP 1 3 bytes 08 03 00 |
AjK | 0:0a841b89d614 | 506 | 13. <- IN IF:0 EP 1 3 bytes 01 03 01 |
AjK | 0:0a841b89d614 | 507 | 14. -> Vendor request OUT EP0 (0x00) |
AjK | 0:0a841b89d614 | 508 | -> SETUP 41 00 1F 00 02 00 00 00 |
AjK | 0:0a841b89d614 | 509 | -> IN No data |
AjK | 0:0a841b89d614 | 510 | 15. -> Vendor request OUT EP0 (0x00) |
AjK | 0:0a841b89d614 | 511 | -> SETUP 41 00 1E 00 02 00 00 00 |
AjK | 0:0a841b89d614 | 512 | -> IN No data |
AjK | 0:0a841b89d614 | 513 | |
AjK | 0:0a841b89d614 | 514 | Note that 14. and 15. are 1second apart and repeat continuely |
AjK | 0:0a841b89d614 | 515 | toggling between 1F and 1E each second. |
AjK | 0:0a841b89d614 | 516 | |
AjK | 0:0a841b89d614 | 517 | 16. <- IN IF:2 EP4 (IF:2 PIPE1) 5 bytes F0 03 00 01 01 |
AjK | 0:0a841b89d614 | 518 | 17. -> Vendor request OUT EP0 (0x00) |
AjK | 0:0a841b89d614 | 519 | -> SETUP 41 00 1B 00 02 00 00 00 |
AjK | 0:0a841b89d614 | 520 | -> IN No data |
AjK | 0:0a841b89d614 | 521 | 18. <- IN IF:2 EP4 (IF:2 PIPE1) 5 bytes F0 03 00 01 01 |
AjK | 0:0a841b89d614 | 522 | 19. -> Vendor request OUT EP0 (0x00) |
AjK | 0:0a841b89d614 | 523 | -> SETUP 41 00 1B 00 02 00 00 00 |
AjK | 0:0a841b89d614 | 524 | -> IN No data |
AjK | 0:0a841b89d614 | 525 | |
AjK | 0:0a841b89d614 | 526 | |
AjK | 0:0a841b89d614 | 527 | After this we start receiving data from IF:2 PIPE1 |
AjK | 0:0a841b89d614 | 528 | |
AjK | 0:0a841b89d614 | 529 | */ |
AjK | 0:0a841b89d614 | 530 | USBEH_U08 chatpad_trash_buffer[256]; |
AjK | 0:0a841b89d614 | 531 | USBEH_U08 chatpad_toggle; |
AjK | 0:0a841b89d614 | 532 | USBEH_U08 chatpad_send_toggle; |
AjK | 0:0a841b89d614 | 533 | USBEH_U08 chatpad_toggle_1Bsent; |
AjK | 0:0a841b89d614 | 534 | USBEH_SOF_COUNTER chatpad_toggle_timer; |
AjK | 0:0a841b89d614 | 535 | |
AjK | 0:0a841b89d614 | 536 | void xbox360_chatpad_toggle(int device, int endpoint, int status, USBEH_U08 *data, int len, void *userData) { |
AjK | 0:0a841b89d614 | 537 | int result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 538 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, |
AjK | 0:0a841b89d614 | 539 | 0x00, |
AjK | 0:0a841b89d614 | 540 | (int)userData, |
AjK | 0:0a841b89d614 | 541 | 0x0002, |
AjK | 0:0a841b89d614 | 542 | chatpad_trash_buffer, |
AjK | 0:0a841b89d614 | 543 | 0, |
AjK | 0:0a841b89d614 | 544 | xbox360_chatpad_toggle, |
AjK | 0:0a841b89d614 | 545 | (userData == (void *)0x1E) ? (void *)0x001F : (void *)0x001E); |
AjK | 0:0a841b89d614 | 546 | //debug.printf("TOGGLE = 0x%x\r\n", -result & 0xf); |
AjK | 0:0a841b89d614 | 547 | } |
AjK | 0:0a841b89d614 | 548 | |
AjK | 0:0a841b89d614 | 549 | void xbox360_chatpad_timed_toggle(USBEH_SOF_COUNTER *q) { |
AjK | 0:0a841b89d614 | 550 | int result; |
AjK | 0:0a841b89d614 | 551 | |
AjK | 0:0a841b89d614 | 552 | debug_printf("%s() called.\r\n", __FUNCTION__); |
AjK | 0:0a841b89d614 | 553 | |
AjK | 0:0a841b89d614 | 554 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 555 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, |
AjK | 0:0a841b89d614 | 556 | 0x00, |
AjK | 0:0a841b89d614 | 557 | (int)q->userData == 0x1F ? 0x001F : 0x001E, |
AjK | 0:0a841b89d614 | 558 | 0x0002, |
AjK | 0:0a841b89d614 | 559 | chatpad_trash_buffer, |
AjK | 0:0a841b89d614 | 560 | 0, |
AjK | 0:0a841b89d614 | 561 | 0, 0); |
AjK | 0:0a841b89d614 | 562 | |
AjK | 0:0a841b89d614 | 563 | debug_printf("repeat! 1F/E = 0x%x\r\n", -result & 0xf); |
AjK | 0:0a841b89d614 | 564 | |
AjK | 0:0a841b89d614 | 565 | if (1 && !chatpad_toggle_1Bsent) { |
AjK | 0:0a841b89d614 | 566 | chatpad_toggle_1Bsent = 1; |
AjK | 0:0a841b89d614 | 567 | |
AjK | 0:0a841b89d614 | 568 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 569 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, |
AjK | 0:0a841b89d614 | 570 | 0x00, |
AjK | 0:0a841b89d614 | 571 | 0x001B, |
AjK | 0:0a841b89d614 | 572 | 0x0002, |
AjK | 0:0a841b89d614 | 573 | chatpad_trash_buffer, |
AjK | 0:0a841b89d614 | 574 | 0, |
AjK | 0:0a841b89d614 | 575 | 0, 0); |
AjK | 0:0a841b89d614 | 576 | } |
AjK | 0:0a841b89d614 | 577 | |
AjK | 0:0a841b89d614 | 578 | debug_printf("repeat! 1B = 0x%x\r\n", -result & 0xf); |
AjK | 0:0a841b89d614 | 579 | |
AjK | 0:0a841b89d614 | 580 | //usbeh_sof_counter_unregister(&chatpad_toggle_timer); |
AjK | 0:0a841b89d614 | 581 | //usbeh_sof_counter_init(&chatpad_toggle_timer, USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, 1700); |
AjK | 0:0a841b89d614 | 582 | //chatpad_toggle_timer.userData = (int)q->userData == 0x1F ? 0x001F : 0x001E; |
AjK | 0:0a841b89d614 | 583 | //chatpad_toggle_timer.callback = xbox360_chatpad_timed; |
AjK | 0:0a841b89d614 | 584 | //chatpad_toggle_timer.flag = 0; |
AjK | 0:0a841b89d614 | 585 | //usbeh_sof_counter_register(&chatpad_toggle_timer); |
AjK | 0:0a841b89d614 | 586 | |
AjK | 0:0a841b89d614 | 587 | |
AjK | 0:0a841b89d614 | 588 | } |
AjK | 0:0a841b89d614 | 589 | |
AjK | 0:0a841b89d614 | 590 | void xbox360_chatpad_init(void) { |
AjK | 0:0a841b89d614 | 591 | int result; |
AjK | 0:0a841b89d614 | 592 | USBEH_U08 buffer[256]; |
AjK | 0:0a841b89d614 | 593 | USBEH_U08 data[256]; |
AjK | 0:0a841b89d614 | 594 | |
AjK | 0:0a841b89d614 | 595 | // int usbeh_api_control_transfer(int device, |
AjK | 0:0a841b89d614 | 596 | // int request_type, |
AjK | 0:0a841b89d614 | 597 | // int request, |
AjK | 0:0a841b89d614 | 598 | // int value, |
AjK | 0:0a841b89d614 | 599 | // int index, |
AjK | 0:0a841b89d614 | 600 | // USBEH_U08 *data, |
AjK | 0:0a841b89d614 | 601 | // int length, |
AjK | 0:0a841b89d614 | 602 | // USBEH_callback callback, void *userData) { |
AjK | 0:0a841b89d614 | 603 | // 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); |
AjK | 0:0a841b89d614 | 604 | |
AjK | 0:0a841b89d614 | 605 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 606 | USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, |
AjK | 0:0a841b89d614 | 607 | 0x01, |
AjK | 0:0a841b89d614 | 608 | 0x0000, |
AjK | 0:0a841b89d614 | 609 | 0x0000, |
AjK | 0:0a841b89d614 | 610 | buffer, |
AjK | 0:0a841b89d614 | 611 | 4, |
AjK | 0:0a841b89d614 | 612 | 0, 0); |
AjK | 0:0a841b89d614 | 613 | debug_printf("Step 1 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 614 | |
AjK | 0:0a841b89d614 | 615 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 616 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, |
AjK | 0:0a841b89d614 | 617 | 0xA9, |
AjK | 0:0a841b89d614 | 618 | 0xA30C, |
AjK | 0:0a841b89d614 | 619 | 0x4423, |
AjK | 0:0a841b89d614 | 620 | buffer, |
AjK | 0:0a841b89d614 | 621 | 0, |
AjK | 0:0a841b89d614 | 622 | 0, 0); |
AjK | 0:0a841b89d614 | 623 | debug_printf("Step 2 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 624 | |
AjK | 0:0a841b89d614 | 625 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 626 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, |
AjK | 0:0a841b89d614 | 627 | 0xA9, |
AjK | 0:0a841b89d614 | 628 | 0x2344, |
AjK | 0:0a841b89d614 | 629 | 0x7F03, |
AjK | 0:0a841b89d614 | 630 | buffer, |
AjK | 0:0a841b89d614 | 631 | 0, |
AjK | 0:0a841b89d614 | 632 | 0, 0); |
AjK | 0:0a841b89d614 | 633 | debug_printf("Step 3 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 634 | |
AjK | 0:0a841b89d614 | 635 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 636 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, |
AjK | 0:0a841b89d614 | 637 | 0xA9, |
AjK | 0:0a841b89d614 | 638 | 0x5839, |
AjK | 0:0a841b89d614 | 639 | 0x6832, |
AjK | 0:0a841b89d614 | 640 | buffer, |
AjK | 0:0a841b89d614 | 641 | 0, |
AjK | 0:0a841b89d614 | 642 | 0, 0); |
AjK | 0:0a841b89d614 | 643 | debug_printf("Step 4 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 644 | |
AjK | 0:0a841b89d614 | 645 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 646 | USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, |
AjK | 0:0a841b89d614 | 647 | 0xA1, |
AjK | 0:0a841b89d614 | 648 | 0x0000, |
AjK | 0:0a841b89d614 | 649 | 0xE416, |
AjK | 0:0a841b89d614 | 650 | buffer, |
AjK | 0:0a841b89d614 | 651 | 2, |
AjK | 0:0a841b89d614 | 652 | 0, 0); |
AjK | 0:0a841b89d614 | 653 | debug_printf("Step 5 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 654 | |
AjK | 0:0a841b89d614 | 655 | data[0] = 9; data[1] = 0; |
AjK | 0:0a841b89d614 | 656 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 657 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, |
AjK | 0:0a841b89d614 | 658 | 0xA1, |
AjK | 0:0a841b89d614 | 659 | 0x5839, |
AjK | 0:0a841b89d614 | 660 | 0xE416, |
AjK | 0:0a841b89d614 | 661 | data, |
AjK | 0:0a841b89d614 | 662 | 2, |
AjK | 0:0a841b89d614 | 663 | 0, 0); |
AjK | 0:0a841b89d614 | 664 | debug_printf("Step 6 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 665 | |
AjK | 0:0a841b89d614 | 666 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 667 | USBEH_DEVICE_TO_HOST | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_DEVICE, |
AjK | 0:0a841b89d614 | 668 | 0xA1, |
AjK | 0:0a841b89d614 | 669 | 0x0000, |
AjK | 0:0a841b89d614 | 670 | 0xE416, |
AjK | 0:0a841b89d614 | 671 | buffer, |
AjK | 0:0a841b89d614 | 672 | 2, |
AjK | 0:0a841b89d614 | 673 | 0, 0); |
AjK | 0:0a841b89d614 | 674 | debug_printf("Step 7 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 675 | |
AjK | 0:0a841b89d614 | 676 | // Now begin toggling 1F / 1E |
AjK | 0:0a841b89d614 | 677 | chatpad_toggle = 0x1E; |
AjK | 0:0a841b89d614 | 678 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 679 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, |
AjK | 0:0a841b89d614 | 680 | 0x00, |
AjK | 0:0a841b89d614 | 681 | 0x001F, |
AjK | 0:0a841b89d614 | 682 | 0x0002, |
AjK | 0:0a841b89d614 | 683 | chatpad_trash_buffer, |
AjK | 0:0a841b89d614 | 684 | 0, |
AjK | 0:0a841b89d614 | 685 | xbox360_chatpad_toggle, |
AjK | 0:0a841b89d614 | 686 | (void *)0x1E); |
AjK | 0:0a841b89d614 | 687 | debug_printf("Step 8 TOGGLE = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 688 | |
AjK | 0:0a841b89d614 | 689 | result = usbeh_api_control_transfer(deviceNumber, |
AjK | 0:0a841b89d614 | 690 | USBEH_HOST_TO_DEVICE | USBEH_SETUP_TYPE_MASK_VENDOR | USBEH_RECIPIENT_INTERFACE, |
AjK | 0:0a841b89d614 | 691 | 0x00, |
AjK | 0:0a841b89d614 | 692 | 0x0003, |
AjK | 0:0a841b89d614 | 693 | 0x0002, |
AjK | 0:0a841b89d614 | 694 | chatpad_trash_buffer, |
AjK | 0:0a841b89d614 | 695 | 0, |
AjK | 0:0a841b89d614 | 696 | 0, |
AjK | 0:0a841b89d614 | 697 | 0); |
AjK | 0:0a841b89d614 | 698 | debug_printf("Step 9 OUT 0x03 = 0x%x %02x %02x %02x %02x \r\n", result, buffer[0], buffer[1], buffer[2], buffer[3]); |
AjK | 0:0a841b89d614 | 699 | |
AjK | 0:0a841b89d614 | 700 | //usbeh_sof_counter_init(&chatpad_toggle_timer, USBEH_SOF_COUNTER_DEC | USBEH_SOF_COUNTER_RELOAD, 1700); |
AjK | 0:0a841b89d614 | 701 | //chatpad_toggle_timer.userData = (int)chatpad_toggle; |
AjK | 0:0a841b89d614 | 702 | //chatpad_toggle_timer.callback = xbox360_chatpad_timed; |
AjK | 0:0a841b89d614 | 703 | //usbeh_sof_counter_register(&chatpad_toggle_timer); |
AjK | 0:0a841b89d614 | 704 | |
AjK | 0:0a841b89d614 | 705 | } |
AjK | 0:0a841b89d614 | 706 | |
AjK | 0:0a841b89d614 | 707 | #endif |