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 Suga koubou

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;
 }