Xbox 360 Wireless Controller for Windows library. sample: http://mbed.org/users/okini3939/code/USBHostXpad_HelloWorld/
Dependents: USBHostXpad_HelloWorld USBHostXpad_HelloWorld
Xbox 360 Wireless Controller for Windows
Microsoftの XBOX 360 ワイヤレスコントローラーを、パソコン用のUSB接続型レシーバーで mbed に接続して使えるライブラリです。
USB Host 機能を使いますので mbed LPC1768 専用です。
たまに処理が停止する不具合があります。
Diff: USBHostXpad.cpp
- Revision:
- 1:5bb153989f33
- Parent:
- 0:bd0f6bf72a8b
- Child:
- 2:2749f4e649db
--- a/USBHostXpad.cpp Tue Dec 10 06:50:37 2013 +0000 +++ b/USBHostXpad.cpp Wed Dec 11 04:11:04 2013 +0000 @@ -5,10 +5,8 @@ * * VID=0x045e PID=0x0719 * - * Note: 2012-12-10 - * The library has some problems. - * - X-logo lamp remains flickering. - * - probe() function is irresponsible. + * Reference: + * https://github.com/Grumbel/xboxdrv/blob/master/PROTOCOL */ #include "USBHostXpad.h" @@ -57,7 +55,6 @@ break; if (xpad_device_found) { - xpad_device_found = false; int_in = dev->getEndpoint(xpad_intf, INTERRUPT_ENDPOINT, IN); int_out = dev->getEndpoint(xpad_intf, INTERRUPT_ENDPOINT, OUT); @@ -68,30 +65,17 @@ USB_INFO("endpoint in:%08x out:%08x", int_in, int_out); dev->setName("XPAD", xpad_intf); host->registerDriver(dev, xpad_intf, this, &USBHostXpad::init); + int_in->attach(this, &USBHostXpad::rxHandler); + host->interruptRead(dev, int_in, report, int_in->getSize(), false); - int_in->attach(this, &USBHostXpad::rxHandler); - probe(0x00, 0x00, 0x08, 0x40); - probe(0x01, 0x03, 0x09, 0x01); - probe(0x01, 0x03, 0x08, 0x01); - probe(0x01, 0x03, 0x09, 0x00); - probe(0x01, 0x03, 0x09, 0x01); - probe(0x01, 0x03, 0x08, 0x01); - probe(0x01, 0x03, 0x09, 0x00); - probe(0x01, 0x03, 0x09, 0x01); - probe(0x01, 0x03, 0x08, 0x01); - probe(0x01, 0x03, 0x09, 0x00); - probe(0x01, 0x03, 0x09, 0x01); - probe(0x01, 0x03, 0x08, 0x01); - probe(0x01, 0x03, 0x09, 0x00); - host->interruptRead(dev, int_in, report, int_in->getSize(), false); + Thread::wait(100); + led(XPAD_LED_OFF); dev_connected = true; -// USB_INFO("RETURN TRUE"); return true; } - } //if() - } //for() -// USB_INFO("RETURN FALSE"); + } + } init(); return false; } @@ -100,28 +84,37 @@ int len_listen = int_in->getSize(); int len = int_in->getLengthTransferred(); - USB_INFO("rxHandler len:%d data:%02x %02x", len, report[0], report[1]); +/* for (int i = 0; i < len_listen; i ++) { std::printf(" %02x", report[i]); } std::printf("\r\n"); - +*/ if (report[0] == 0x08 && report[1] == 0x80) { - probe(0x00, 0x00, 0x00, 0x40); + // Connection Status Messages + send(0x00, 0x00, 0x00, 0x40); goto exit; } else if (report[0] == 0x00 && report[1] == 0x0f) { - probe(0x00, 0x00, 0x08, 0x46); - probe(0x00, 0x00, 0x00, 0x40); + // On connection + led(XPAD_LED1_ON); + send(0x00, 0x00, 0x00, 0x40); + goto exit; + } else + if (report[0] == 0x00 && report[1] == 0xf8) { + // Battery Status Msg (maybe) goto exit; } else - if (report[0] == 0x00 && report[1] == 0x00 && report[2] == 0x00 && report[3] == 0x0f) { - // + if (report[0] == 0x00 && report[1] == 0x00 && report[2] == 0x00 && report[3] == 0xf0) { + // Battery Full ? goto exit; } else - if (report[0] != 0x00 || !(report[1] & 1)) { // Check if it's the correct report - the controller also sends different status reports + if (report[0] != 0x00 || report[1] != 0x01 || report[2] != 0x00 || report[3] != 0xf0) { + // Unknown + USB_INFO("rxHandler len:%d data:%02x %02x %02x %02x", len, report[0], report[1], report[2], report[3]); goto exit; } + // Event data buttons = ((uint32_t)report[7] << 8) | report[6]; trigger_l = report[8]; @@ -172,44 +165,55 @@ return false; } -void USBHostXpad::poll () +void USBHostXpad::restart () { - probe(0x08, 0x00, 0x0f, 0xc0); - probe(0x08, 0x00, 0x0f, 0xc0); - probe(0x08, 0x00, 0x0f, 0xc0); - probe(0x08, 0x00, 0x0f, 0xc0); + send(0x08, 0x00, 0x0f, 0xc0); + send(0x08, 0x00, 0x0f, 0xc0); + send(0x08, 0x00, 0x0f, 0xc0); + send(0x08, 0x00, 0x0f, 0xc0); } -bool USBHostXpad::probe(int val1, int val2, int val3, int val4) +bool USBHostXpad::send(int val1, int val2, int val3, int val4) { - unsigned char bdata[32]; - memset(bdata, 0, sizeof(bdata)); - bdata[0] = val1; - bdata[1] = val2; - bdata[2] = val3; - bdata[3] = val4; + unsigned char odata[32]; + memset(odata, 0, sizeof(odata)); + odata[0] = val1; + odata[1] = val2; + odata[2] = val3; + odata[3] = val4; + if (dev) - host->interruptWrite(dev, int_out, bdata, 12, false); + if (host->interruptWrite(dev, int_out, odata, 12) == USB_TYPE_ERROR) { + init(); + return false; + } return true; } -bool USBHostXpad::effect(uint8_t strong, uint8_t weak) +bool USBHostXpad::led(int cmd) { unsigned char odata[32]; + memset(odata, 0, sizeof(odata)); + odata[2] = 0x08; + odata[3] = 0x40 + (cmd % 0x0e); + if (dev) + if (host->interruptWrite(dev, int_out, odata, 12) == USB_TYPE_ERROR) + return false; + return true; +} - odata[0] = 0x00; +bool USBHostXpad::rumble(uint8_t large, uint8_t small) +{ + unsigned char odata[32]; + memset(odata, 0, sizeof(odata)); odata[1] = 0x01; - odata[2] = 0x0F; - odata[3] = 0xC0; - odata[4] = 0x00; - odata[5] = strong; - odata[6] = weak; - odata[7] = 0x00; - odata[8] = 0x00; - odata[9] = 0x00; - odata[10] = 0x00; - odata[11] = 0x00; - host->interruptWrite(dev, int_in, odata, 12, false); + odata[2] = 0x0f; + odata[3] = 0xc0; + odata[5] = large; + odata[6] = small; + if (dev) + if (host->interruptWrite(dev, int_out, odata, 12) == USB_TYPE_ERROR) + return false; return true; }