Xbox 360 Wireless Controller for Windows library. sample: http://mbed.org/users/okini3939/code/USBHostXpad_HelloWorld/
Dependents: x4180_Tank Totaleprogramma Handmatig Totaleprogramma1
Fork of USBHostXpad by
USBHostXpad.cpp
00001 /* 00002 * Xbox 360 Wireless Controller for Windows library 00003 * for mbed USBHost library 00004 * Copyright (c) 2013 Hiroshi Suga 00005 * 00006 * VID=0x045e PID=0x0719 00007 * 00008 * Reference: 00009 * https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL 00010 * http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller 00011 */ 00012 00013 #include "USBHostXpad.h" 00014 00015 #if 1 or USBHOST_XPAD 00016 00017 #include "dbg.h" 00018 00019 #define DEVICE_TO_HOST 0x80 00020 #define HOST_TO_DEVICE 0x00 00021 00022 USBHostXpad::USBHostXpad() 00023 { 00024 host = USBHost::getHostInst(); 00025 init(); 00026 } 00027 00028 void USBHostXpad::init() { 00029 dev_connected = false; 00030 dev = NULL; 00031 int_in = NULL; 00032 int_out = NULL; 00033 xpad_intf = -1; 00034 xpad_device_found = false; 00035 nb_ep = 0; 00036 dev_type = TYPE_UNKNOWN; 00037 dev_started = false; 00038 } 00039 00040 bool USBHostXpad::connected() 00041 { 00042 return dev_connected; 00043 } 00044 00045 bool USBHostXpad::connect() 00046 { 00047 00048 if (dev_connected) { 00049 return true; 00050 } 00051 00052 for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) { 00053 if ((dev = host->getDevice(i)) != NULL) { 00054 00055 //USB_DBG("Trying to connect MSD device\r\n"); 00056 00057 if(host->enumerate(dev, this)) break; 00058 00059 if (xpad_device_found) { 00060 int_in = dev->getEndpoint(xpad_intf, INTERRUPT_ENDPOINT, IN); 00061 int_out = dev->getEndpoint(xpad_intf, INTERRUPT_ENDPOINT, OUT); 00062 00063 if (!int_in || !int_out) continue; 00064 00065 USB_INFO("New MSD device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, xpad_intf); 00066 dev->setName("XPAD", xpad_intf); 00067 host->registerDriver(dev, xpad_intf, this, &USBHostXpad::init); 00068 int_in->attach(this, &USBHostXpad::rxHandler); 00069 host->interruptRead(dev, int_in, report, int_in->getSize(), false); 00070 00071 Thread::wait(100); 00072 led(LED_OFF); 00073 dev_connected = true; 00074 return true; 00075 } 00076 00077 } 00078 } 00079 init(); 00080 return false; 00081 } 00082 00083 void USBHostXpad::rxHandler() { 00084 int len_listen = int_in->getSize(); 00085 int len = int_in->getLengthTransferred(); 00086 00087 /* 00088 for (int i = 0; i < len_listen; i ++) { 00089 std::printf(" %02x", report[i]); 00090 } 00091 std::printf("\r\n"); 00092 */ 00093 if (dev_type == TYPE_XBOX) { 00094 parseMessage(); 00095 } else 00096 if (report[0] == 0x08) { 00097 if (report[1] == 0x80) { 00098 // Connection Status Messages 00099 start(); 00100 } else 00101 if (report[1] == 0x00) { 00102 // Disconnected Status Messages 00103 dev_started = false; 00104 } 00105 } else 00106 if (report[0] == 0x00) { 00107 if ((report[1] == 0x14) || 00108 (report[1] == 0x01 && report[2] == 0x00 && report[3] == 0xf0)) { 00109 // Event data 00110 parseMessage(); 00111 } else 00112 if (report[1] == 0x0f) { 00113 // On connection 00114 led(LED1_ON); 00115 start(); 00116 dev_started = true; 00117 } else 00118 if (report[1] == 0x00) { 00119 if (report[3] == 0x13) { 00120 // Battery charge level 00121 battery = report[4]; 00122 } else 00123 if (report[3] == 0xf0) { 00124 // Device low power mode (HID updates will stop until controller inputs change) 00125 // restart(); 00126 } 00127 } else 00128 if (report[1] == 0xf8) { 00129 // Status Messages ? 00130 } 00131 } else { 00132 // Unknown 00133 USB_INFO("rxHandler len:%d data:%02x %02x %02x %02x", len, report[0], report[1], report[2], report[3]); 00134 } 00135 00136 if (dev) { 00137 host->interruptRead(dev, int_in, report, len_listen, false); 00138 } 00139 } 00140 00141 /*virtual*/ void USBHostXpad::setVidPid(uint16_t vid, uint16_t pid) 00142 { 00143 // we don't check VID/PID for MSD driver 00144 if (vid == 0x045e && (pid == 0x0202 || pid == 0x0285 || pid == 0x0287 || pid == 0x0289)) { 00145 dev_type = TYPE_XBOX; 00146 } else 00147 if (vid == 0x045e && pid == 0x028e) { 00148 dev_type = TYPE_XBOX360; 00149 } else 00150 if (vid == 0x045e && pid == 0x0719) { 00151 dev_type = TYPE_XBOX360W; 00152 } 00153 USB_INFO("setVidPid vid:%04x pid:%04x xbox:%d", vid, pid, dev_type); 00154 } 00155 00156 /*virtual*/ bool USBHostXpad::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed 00157 { 00158 USB_INFO("parseInterface class:%02x subclass:%02x protocol:%02x [nb: %d - intf: %d]", intf_class, intf_subclass, intf_protocol, intf_nb, xpad_intf); 00159 if ((xpad_intf == -1) && (intf_class == 0x58) && (intf_subclass == 0x42) && (intf_protocol == 0x00)) { 00160 xpad_intf = intf_nb; // XBOX ? 00161 return true; 00162 } 00163 if ((xpad_intf == -1) && (intf_class == 0xff) && (intf_subclass == 0x5d) && (intf_protocol == 0x81)) { 00164 xpad_intf = intf_nb; // XBOX360W 00165 return true; 00166 } 00167 return false; 00168 } 00169 00170 /*virtual*/ bool USBHostXpad::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used 00171 { 00172 USB_INFO("useEndpoint nb:%d type:%d dir:%d", intf_nb, type, dir); 00173 if (intf_nb == xpad_intf) { 00174 if (type == INTERRUPT_ENDPOINT) { 00175 nb_ep ++; 00176 if (nb_ep == 2) { 00177 xpad_device_found = true; 00178 } 00179 return true; 00180 } 00181 } 00182 return false; 00183 } 00184 00185 00186 void USBHostXpad::parseMessage() 00187 { 00188 uint8_t *data = report; 00189 00190 switch (dev_type) { 00191 case TYPE_XBOX: 00192 buttons = ((uint32_t)report[3] << 8) | report[2]; 00193 if (report[4]) buttons |= XPAD_PAD_A; 00194 if (report[5]) buttons |= XPAD_PAD_B; 00195 if (report[6]) buttons |= XPAD_PAD_X; 00196 if (report[7]) buttons |= XPAD_PAD_Y; 00197 trigger_l = data[10]; 00198 trigger_r = data[11]; 00199 00200 stick_lx = ((int16_t)report[13] << 8) | report[12]; 00201 stick_ly = ((int16_t)report[15] << 8) | report[14]; 00202 stick_rx = ((int16_t)report[17] << 8) | report[16]; 00203 stick_ry = ((int16_t)report[19] << 8) | report[18]; 00204 break; 00205 case TYPE_XBOX360W: 00206 data += 4; 00207 case TYPE_XBOX360: 00208 buttons = ((uint32_t)data[3] << 8) | data[2]; 00209 trigger_l = data[4]; 00210 trigger_r = data[5]; 00211 00212 stick_lx = ((int16_t)data[7] << 8) | data[6]; 00213 stick_ly = ((int16_t)data[9] << 8) | data[8]; 00214 stick_rx = ((int16_t)data[11] << 8) | data[10]; 00215 stick_ry = ((int16_t)data[13] << 8) | data[12]; 00216 break; 00217 default: 00218 return; 00219 } 00220 00221 if (onUpdate) { 00222 (*onUpdate)(buttons, stick_lx, stick_ly, stick_rx, stick_ry, trigger_l, trigger_r); 00223 } 00224 } 00225 00226 bool USBHostXpad::restart () 00227 { 00228 unsigned char odata[32]; 00229 memset(odata, 0, sizeof(odata)); 00230 odata[0] = 0x08; 00231 odata[2] = 0x0f; 00232 odata[3] = 0xc0; 00233 if (dev) { 00234 for (int i = 0; i < 4; i ++) { 00235 host->interruptWrite(dev, int_out, odata, 12); 00236 } 00237 } 00238 return true; 00239 } 00240 00241 int USBHostXpad::read (PAD pad) 00242 { 00243 switch (pad) { 00244 case XPAD_BUTTONS: 00245 return buttons; 00246 case XPAD_STICK_LX: 00247 return stick_lx; 00248 case XPAD_STICK_LY: 00249 return stick_ly; 00250 case XPAD_STICK_RX: 00251 return stick_rx; 00252 case XPAD_STICK_RY: 00253 return stick_ry; 00254 case XPAD_TRIGGER_L: 00255 return trigger_l; 00256 case XPAD_TRIGGER_R: 00257 return trigger_r; 00258 case XPAD_BATTERY: 00259 return battery; 00260 default: 00261 return (buttons & pad) ? 1 : 0; 00262 } 00263 } 00264 00265 bool USBHostXpad::start() 00266 { 00267 unsigned char odata[32]; 00268 memset(odata, 0, sizeof(odata)); 00269 odata[3] = 0x40; 00270 if (dev) { 00271 if (host->interruptWrite(dev, int_out, odata, 12) != USB_TYPE_OK) { 00272 return false; 00273 } 00274 } 00275 return true; 00276 } 00277 00278 bool USBHostXpad::stop() 00279 { 00280 unsigned char odata[32]; 00281 memset(odata, 0, sizeof(odata)); 00282 odata[2] = 0x08; 00283 odata[3] = 0xc0; 00284 if (dev) { 00285 if (host->interruptWrite(dev, int_out, odata, 12) != USB_TYPE_OK) { 00286 return false; 00287 } 00288 } 00289 return true; 00290 } 00291 00292 bool USBHostXpad::led(LED cmd) 00293 { 00294 unsigned char odata[32]; 00295 memset(odata, 0, sizeof(odata)); 00296 switch (dev_type) { 00297 case TYPE_XBOX: 00298 return true; 00299 case TYPE_XBOX360: 00300 odata[0] = 0x01; 00301 odata[1] = 0x03; 00302 odata[2] = cmd; 00303 break; 00304 case TYPE_XBOX360W: 00305 odata[2] = 0x08; 00306 odata[3] = 0x40 + (cmd % 0x0e); 00307 break; 00308 default: 00309 return false; 00310 } 00311 if (dev) { 00312 if (host->interruptWrite(dev, int_out, odata, 12) != USB_TYPE_OK) { 00313 return false; 00314 } 00315 } 00316 return true; 00317 } 00318 00319 bool USBHostXpad::rumble(uint8_t large, uint8_t small) 00320 { 00321 unsigned char odata[32]; 00322 memset(odata, 0, sizeof(odata)); 00323 switch (dev_type) { 00324 case TYPE_XBOX: 00325 odata[1] = 0x06; 00326 odata[3] = small; 00327 odata[5] = large; 00328 break; 00329 case TYPE_XBOX360: 00330 odata[1] = 0x08; 00331 odata[3] = large; 00332 odata[4] = small; 00333 break; 00334 case TYPE_XBOX360W: 00335 odata[1] = 0x01; 00336 odata[2] = 0x0f; 00337 odata[3] = 0xc0; 00338 odata[5] = large; 00339 odata[6] = small; 00340 break; 00341 default: 00342 return false; 00343 } 00344 if (dev) { 00345 if (host->interruptWrite(dev, int_out, odata, 12) != USB_TYPE_OK) { 00346 return false; 00347 } 00348 } 00349 return true; 00350 } 00351 00352 #endif 00353
Generated on Wed Jul 20 2022 11:16:45 by 1.7.2