mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-24 18:12:16 -05:00
XBox360 Wireless controller
Support for using the Microsoft XBox 360 wireless receiver for windows to be able to communicate with XBox 360 wireless controllers. In theory this should support up to 4 controllers. So far I have only tested with one as I only have one. Added a joystick only test that should support up to 4 joystick objects.
This commit is contained in:
parent
5e4707a242
commit
eaad0684f2
@ -782,7 +782,7 @@ public:
|
|||||||
const uint8_t *manufacturer();
|
const uint8_t *manufacturer();
|
||||||
const uint8_t *product();
|
const uint8_t *product();
|
||||||
const uint8_t *serialNumber();
|
const uint8_t *serialNumber();
|
||||||
operator bool() { return ((device != nullptr) || (mydevice != nullptr)); } // override as in both USBDriver and in USBHIDInput
|
operator bool() { return (((device != nullptr) || (mydevice != nullptr)) && connected_); } // override as in both USBDriver and in USBHIDInput
|
||||||
|
|
||||||
bool available() { return joystickEvent; }
|
bool available() { return joystickEvent; }
|
||||||
void joystickDataClear();
|
void joystickDataClear();
|
||||||
@ -798,7 +798,7 @@ public:
|
|||||||
// setLEDs on PS4(RGB), PS3 simple LED setting (only uses lr)
|
// setLEDs on PS4(RGB), PS3 simple LED setting (only uses lr)
|
||||||
bool setLEDs(uint8_t lr, uint8_t lg=0, uint8_t lb=0); // sets Leds,
|
bool setLEDs(uint8_t lr, uint8_t lg=0, uint8_t lb=0); // sets Leds,
|
||||||
enum { STANDARD_AXIS_COUNT = 10, ADDITIONAL_AXIS_COUNT = 54, TOTAL_AXIS_COUNT = (STANDARD_AXIS_COUNT+ADDITIONAL_AXIS_COUNT) };
|
enum { STANDARD_AXIS_COUNT = 10, ADDITIONAL_AXIS_COUNT = 54, TOTAL_AXIS_COUNT = (STANDARD_AXIS_COUNT+ADDITIONAL_AXIS_COUNT) };
|
||||||
typedef enum { UNKNOWN=0, PS3, PS4, XBOXONE} joytype_t;
|
typedef enum { UNKNOWN=0, PS3, PS4, XBOXONE, XBOX360} joytype_t;
|
||||||
joytype_t joystickType = UNKNOWN;
|
joytype_t joystickType = UNKNOWN;
|
||||||
protected:
|
protected:
|
||||||
// From USBDriver
|
// From USBDriver
|
||||||
@ -839,6 +839,7 @@ private:
|
|||||||
uint8_t rumble_rValue_ = 0;
|
uint8_t rumble_rValue_ = 0;
|
||||||
uint8_t rumble_timeout_ = 0;
|
uint8_t rumble_timeout_ = 0;
|
||||||
uint8_t leds_[3] = {0,0,0};
|
uint8_t leds_[3] = {0,0,0};
|
||||||
|
uint8_t connected_ = 0; // what type of device if any is connected xbox 360...
|
||||||
|
|
||||||
|
|
||||||
// Used by HID code
|
// Used by HID code
|
||||||
@ -854,6 +855,7 @@ private:
|
|||||||
Transfer_t mytransfers[7] __attribute__ ((aligned(32)));
|
Transfer_t mytransfers[7] __attribute__ ((aligned(32)));
|
||||||
strbuf_t mystring_bufs[1];
|
strbuf_t mystring_bufs[1];
|
||||||
|
|
||||||
|
uint8_t rx_ep_ = 0; // remember which end point this object is...
|
||||||
uint16_t rx_size_ = 0;
|
uint16_t rx_size_ = 0;
|
||||||
uint16_t tx_size_ = 0;
|
uint16_t tx_size_ = 0;
|
||||||
Pipe_t *rxpipe_;
|
Pipe_t *rxpipe_;
|
||||||
|
@ -44,7 +44,7 @@ static USBDriver *available_drivers = NULL;
|
|||||||
// Static buffers used during enumeration. One a single USB device
|
// Static buffers used during enumeration. One a single USB device
|
||||||
// may enumerate at once, because USB address zero is used, and
|
// may enumerate at once, because USB address zero is used, and
|
||||||
// because this static buffer & state info can't be shared.
|
// because this static buffer & state info can't be shared.
|
||||||
static uint8_t enumbuf[256] __attribute__ ((aligned(16)));
|
static uint8_t enumbuf[512] __attribute__ ((aligned(16)));
|
||||||
static setup_t enumsetup __attribute__ ((aligned(16)));
|
static setup_t enumsetup __attribute__ ((aligned(16)));
|
||||||
static uint16_t enumlen;
|
static uint16_t enumlen;
|
||||||
|
|
||||||
|
195
examples/Joystick/Joystick.ino
Normal file
195
examples/Joystick/Joystick.ino
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
// Simple test of USB Host Joystick
|
||||||
|
//
|
||||||
|
// This example is in the public domain
|
||||||
|
|
||||||
|
#include "USBHost_t36.h"
|
||||||
|
|
||||||
|
USBHost myusb;
|
||||||
|
USBHub hub1(myusb);
|
||||||
|
USBHIDParser hid1(myusb);
|
||||||
|
USBHIDParser hid2(myusb);
|
||||||
|
USBHIDParser hid3(myusb);
|
||||||
|
USBHIDParser hid4(myusb);
|
||||||
|
#define COUNT_JOYSTICKS 4
|
||||||
|
JoystickController joysticks[COUNT_JOYSTICKS](myusb);
|
||||||
|
int user_axis[64];
|
||||||
|
uint32_t buttons_prev = 0;
|
||||||
|
|
||||||
|
USBDriver *drivers[] = {&hub1, &joysticks[0], &joysticks[1], &joysticks[2], &joysticks[3], &hid1, &hid2, &hid3, &hid4};
|
||||||
|
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0]))
|
||||||
|
const char * driver_names[CNT_DEVICES] = {"Hub1", "joystick[0D]", "joystick[1D]", "joystick[2D]", "joystick[3D]", "HID1", "HID2", "HID3", "HID4"};
|
||||||
|
bool driver_active[CNT_DEVICES] = {false, false, false, false};
|
||||||
|
|
||||||
|
// Lets also look at HID Input devices
|
||||||
|
USBHIDInput *hiddrivers[] = {&joysticks[0], &joysticks[1], &joysticks[2], &joysticks[3]};
|
||||||
|
#define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0]))
|
||||||
|
const char * hid_driver_names[CNT_DEVICES] = {"joystick[0H]", "joystick[1H]", "joystick[2H]", "joystick[3H]"};
|
||||||
|
bool hid_driver_active[CNT_DEVICES] = {false};
|
||||||
|
bool show_changed_only = false;
|
||||||
|
|
||||||
|
uint8_t joystick_left_trigger_value[COUNT_JOYSTICKS] = {0};
|
||||||
|
uint8_t joystick_right_trigger_value[COUNT_JOYSTICKS] = {0};
|
||||||
|
uint64_t joystick_full_notify_mask = (uint64_t) - 1;
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Setup
|
||||||
|
//=============================================================================
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
while (!Serial) ; // wait for Arduino Serial Monitor
|
||||||
|
Serial.println("\n\nUSB Host Joystick Testing");
|
||||||
|
myusb.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// loop
|
||||||
|
//=============================================================================
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
myusb.Task();
|
||||||
|
PrintDeviceListChanges();
|
||||||
|
|
||||||
|
if (Serial.available()) {
|
||||||
|
int ch = Serial.read(); // get the first char.
|
||||||
|
while (Serial.read() != -1) ;
|
||||||
|
if ((ch == 'b') || (ch == 'B')) {
|
||||||
|
Serial.println("Only notify on Basic Axis changes");
|
||||||
|
for (int joystick_index = 0; joystick_index < COUNT_JOYSTICKS; joystick_index++)
|
||||||
|
joysticks[joystick_index].axisChangeNotifyMask(0x3ff);
|
||||||
|
} else if ((ch == 'f') || (ch == 'F')) {
|
||||||
|
Serial.println("Only notify on Full Axis changes");
|
||||||
|
for (int joystick_index = 0; joystick_index < COUNT_JOYSTICKS; joystick_index++)
|
||||||
|
joysticks[joystick_index].axisChangeNotifyMask(joystick_full_notify_mask);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (show_changed_only) {
|
||||||
|
show_changed_only = false;
|
||||||
|
Serial.println("\n*** Show All fields mode ***");
|
||||||
|
} else {
|
||||||
|
show_changed_only = true;
|
||||||
|
Serial.println("\n*** Show only changed fields mode ***");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int joystick_index = 0; joystick_index < COUNT_JOYSTICKS; joystick_index++) {
|
||||||
|
if (joysticks[joystick_index].available()) {
|
||||||
|
uint64_t axis_mask = joysticks[joystick_index].axisMask();
|
||||||
|
uint64_t axis_changed_mask = joysticks[joystick_index].axisChangedMask();
|
||||||
|
uint32_t buttons = joysticks[joystick_index].getButtons();
|
||||||
|
Serial.printf("Joystick(%d): buttons = %x", joystick_index, buttons);
|
||||||
|
//Serial.printf(" AMasks: %x %x:%x", axis_mask, (uint32_t)(user_axis_mask >> 32), (uint32_t)(user_axis_mask & 0xffffffff));
|
||||||
|
//Serial.printf(" M: %lx %lx", axis_mask, joysticks[joystick_index].axisChangedMask());
|
||||||
|
if (show_changed_only) {
|
||||||
|
for (uint8_t i = 0; axis_changed_mask != 0; i++, axis_changed_mask >>= 1) {
|
||||||
|
if (axis_changed_mask & 1) {
|
||||||
|
Serial.printf(" %d:%d", i, joysticks[joystick_index].getAxis(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; axis_mask != 0; i++, axis_mask >>= 1) {
|
||||||
|
if (axis_mask & 1) {
|
||||||
|
Serial.printf(" %d:%d", i, joysticks[joystick_index].getAxis(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t ltv;
|
||||||
|
uint8_t rtv;
|
||||||
|
switch (joysticks[joystick_index].joystickType) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case JoystickController::PS4:
|
||||||
|
ltv = joysticks[joystick_index].getAxis(3);
|
||||||
|
rtv = joysticks[joystick_index].getAxis(4);
|
||||||
|
if ((ltv != joystick_left_trigger_value[joystick_index]) || (rtv != joystick_right_trigger_value[joystick_index])) {
|
||||||
|
joystick_left_trigger_value[joystick_index] = ltv;
|
||||||
|
joystick_right_trigger_value[joystick_index] = rtv;
|
||||||
|
joysticks[joystick_index].setRumble(ltv, rtv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JoystickController::PS3:
|
||||||
|
ltv = joysticks[joystick_index].getAxis(18);
|
||||||
|
rtv = joysticks[joystick_index].getAxis(19);
|
||||||
|
if ((ltv != joystick_left_trigger_value[joystick_index]) || (rtv != joystick_right_trigger_value[joystick_index])) {
|
||||||
|
joystick_left_trigger_value[joystick_index] = ltv;
|
||||||
|
joystick_right_trigger_value[joystick_index] = rtv;
|
||||||
|
joysticks[joystick_index].setRumble(ltv, rtv, 50);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case JoystickController::XBOXONE:
|
||||||
|
case JoystickController::XBOX360:
|
||||||
|
ltv = joysticks[joystick_index].getAxis(4);
|
||||||
|
rtv = joysticks[joystick_index].getAxis(5);
|
||||||
|
if ((ltv != joystick_left_trigger_value[joystick_index]) || (rtv != joystick_right_trigger_value[joystick_index])) {
|
||||||
|
joystick_left_trigger_value[joystick_index] = ltv;
|
||||||
|
joystick_right_trigger_value[joystick_index] = rtv;
|
||||||
|
joysticks[joystick_index].setRumble(ltv, rtv);
|
||||||
|
Serial.printf(" Set Rumble %d %d", ltv, rtv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (buttons != buttons_prev) {
|
||||||
|
if (joysticks[joystick_index].joystickType == JoystickController::PS3) {
|
||||||
|
joysticks[joystick_index].setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare
|
||||||
|
} else {
|
||||||
|
uint8_t lr = (buttons & 1) ? 0xff : 0;
|
||||||
|
uint8_t lg = (buttons & 2) ? 0xff : 0;
|
||||||
|
uint8_t lb = (buttons & 4) ? 0xff : 0;
|
||||||
|
joysticks[joystick_index].setLEDs(lr, lg, lb);
|
||||||
|
}
|
||||||
|
buttons_prev = buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
joysticks[joystick_index].joystickDataClear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
// Show when devices are added or removed
|
||||||
|
//=============================================================================
|
||||||
|
void PrintDeviceListChanges() {
|
||||||
|
for (uint8_t i = 0; i < CNT_DEVICES; i++) {
|
||||||
|
if (*drivers[i] != driver_active[i]) {
|
||||||
|
if (driver_active[i]) {
|
||||||
|
Serial.printf("*** Device %s - disconnected ***\n", driver_names[i]);
|
||||||
|
driver_active[i] = false;
|
||||||
|
} else {
|
||||||
|
Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct());
|
||||||
|
driver_active[i] = true;
|
||||||
|
|
||||||
|
const uint8_t *psz = drivers[i]->manufacturer();
|
||||||
|
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
|
||||||
|
psz = drivers[i]->product();
|
||||||
|
if (psz && *psz) Serial.printf(" product: %s\n", psz);
|
||||||
|
psz = drivers[i]->serialNumber();
|
||||||
|
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < CNT_HIDDEVICES; i++) {
|
||||||
|
if (*hiddrivers[i] != hid_driver_active[i]) {
|
||||||
|
if (hid_driver_active[i]) {
|
||||||
|
Serial.printf("*** HID Device %s - disconnected ***\n", hid_driver_names[i]);
|
||||||
|
hid_driver_active[i] = false;
|
||||||
|
} else {
|
||||||
|
Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct());
|
||||||
|
hid_driver_active[i] = true;
|
||||||
|
|
||||||
|
const uint8_t *psz = hiddrivers[i]->manufacturer();
|
||||||
|
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz);
|
||||||
|
psz = hiddrivers[i]->product();
|
||||||
|
if (psz && *psz) Serial.printf(" product: %s\n", psz);
|
||||||
|
psz = hiddrivers[i]->serialNumber();
|
||||||
|
if (psz && *psz) Serial.printf(" Serial: %s\n", psz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -182,6 +182,7 @@ void loop()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JoystickController::XBOXONE:
|
case JoystickController::XBOXONE:
|
||||||
|
case JoystickController::XBOX360:
|
||||||
ltv = joystick1.getAxis(4);
|
ltv = joystick1.getAxis(4);
|
||||||
rtv = joystick1.getAxis(5);
|
rtv = joystick1.getAxis(5);
|
||||||
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
|
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
|
||||||
|
179
joystick.cpp
179
joystick.cpp
@ -32,6 +32,7 @@
|
|||||||
// doing other features.
|
// doing other features.
|
||||||
JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping[] = {
|
JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping[] = {
|
||||||
{ 0x045e, 0x02ea, XBOXONE, false },{ 0x045e, 0x02dd, XBOXONE, false },
|
{ 0x045e, 0x02ea, XBOXONE, false },{ 0x045e, 0x02dd, XBOXONE, false },
|
||||||
|
{ 0x045e, 0x0719, XBOX360, false},
|
||||||
{ 0x054C, 0x0268, PS3, true},
|
{ 0x054C, 0x0268, PS3, true},
|
||||||
{ 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true }
|
{ 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true }
|
||||||
};
|
};
|
||||||
@ -135,6 +136,23 @@ bool JoystickController::setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeo
|
|||||||
println("XBoxOne rumble transfer fail");
|
println("XBoxOne rumble transfer fail");
|
||||||
}
|
}
|
||||||
return true; //
|
return true; //
|
||||||
|
case XBOX360:
|
||||||
|
txbuf_[0] = 0x00;
|
||||||
|
txbuf_[1] = 0x01;
|
||||||
|
txbuf_[2] = 0x0F;
|
||||||
|
txbuf_[3] = 0xC0;
|
||||||
|
txbuf_[4] = 0x00;
|
||||||
|
txbuf_[5] = lValue;
|
||||||
|
txbuf_[6] = rValue;
|
||||||
|
txbuf_[7] = 0x00;
|
||||||
|
txbuf_[8] = 0x00;
|
||||||
|
txbuf_[9] = 0x00;
|
||||||
|
txbuf_[10] = 0x00;
|
||||||
|
txbuf_[11] = 0x00;
|
||||||
|
if (!queue_Data_Transfer(txpipe_, txbuf_, 12, this)) {
|
||||||
|
println("XBox360 rumble transfer fail");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -153,6 +171,27 @@ bool JoystickController::setLEDs(uint8_t lr, uint8_t lg, uint8_t lb)
|
|||||||
return transmitPS3UserFeedbackMsg();
|
return transmitPS3UserFeedbackMsg();
|
||||||
case PS4:
|
case PS4:
|
||||||
return transmitPS4UserFeedbackMsg();
|
return transmitPS4UserFeedbackMsg();
|
||||||
|
case XBOX360:
|
||||||
|
// 0: off, 1: all blink then return to before
|
||||||
|
// 2-5(TL, TR, BL, BR) - blink on then stay on
|
||||||
|
// 6-9() - On
|
||||||
|
// ...
|
||||||
|
txbuf_[1] = 0x00;
|
||||||
|
txbuf_[2] = 0x08;
|
||||||
|
txbuf_[3] = 0x40 + lr;
|
||||||
|
txbuf_[4] = 0x00;
|
||||||
|
txbuf_[5] = 0x00;
|
||||||
|
txbuf_[6] = 0x00;
|
||||||
|
txbuf_[7] = 0x00;
|
||||||
|
txbuf_[8] = 0x00;
|
||||||
|
txbuf_[9] = 0x00;
|
||||||
|
txbuf_[10] = 0x00;
|
||||||
|
txbuf_[11] = 0x00;
|
||||||
|
if (!queue_Data_Transfer(txpipe_, txbuf_, 12, this)) {
|
||||||
|
println("XBox360 set leds fail");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case XBOXONE:
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -213,11 +252,16 @@ hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *
|
|||||||
if (topusage != 0x10004 && topusage != 0x10005) return CLAIM_NO;
|
if (topusage != 0x10004 && topusage != 0x10005) return CLAIM_NO;
|
||||||
// only claim from one physical device
|
// only claim from one physical device
|
||||||
if (mydevice != NULL && dev != mydevice) return CLAIM_NO;
|
if (mydevice != NULL && dev != mydevice) return CLAIM_NO;
|
||||||
|
|
||||||
|
// Also don't allow us to claim if it is used as a standard usb object (XBox...)
|
||||||
|
if (device != nullptr) return CLAIM_NO;
|
||||||
|
|
||||||
mydevice = dev;
|
mydevice = dev;
|
||||||
collections_claimed++;
|
collections_claimed++;
|
||||||
anychange = true; // always report values on first read
|
anychange = true; // always report values on first read
|
||||||
driver_ = driver; // remember the driver.
|
driver_ = driver; // remember the driver.
|
||||||
driver_->setTXBuffers(txbuf_, nullptr, sizeof(txbuf_));
|
driver_->setTXBuffers(txbuf_, nullptr, sizeof(txbuf_));
|
||||||
|
connected_ = true; // remember that hardware is actually connected...
|
||||||
|
|
||||||
// Lets see if we know what type of joystick this is. That is, is it a PS3 or PS4 or ...
|
// Lets see if we know what type of joystick this is. That is, is it a PS3 or PS4 or ...
|
||||||
joystickType = mapVIDPIDtoJoystickType(mydevice->idVendor, mydevice->idProduct, false);
|
joystickType = mapVIDPIDtoJoystickType(mydevice->idVendor, mydevice->idProduct, false);
|
||||||
@ -323,7 +367,7 @@ void JoystickController::hid_input_end()
|
|||||||
|
|
||||||
bool JoystickController::hid_process_out_data(const Transfer_t *transfer)
|
bool JoystickController::hid_process_out_data(const Transfer_t *transfer)
|
||||||
{
|
{
|
||||||
Serial.printf("JoystickController::hid_process_out_data\n");
|
//Serial.printf("JoystickController::hid_process_out_data\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,14 +383,19 @@ void JoystickController::joystickDataClear() {
|
|||||||
// Example: XBox One controller.
|
// Example: XBox One controller.
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
|
||||||
static uint8_t start_input[] = {0x05, 0x20, 0x00, 0x01, 0x00};
|
static uint8_t xboxone_start_input[] = {0x05, 0x20, 0x00, 0x01, 0x00};
|
||||||
|
static uint8_t xbox360w_inquire_present[] = {0x08, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
|
bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descriptors, uint32_t len)
|
||||||
{
|
{
|
||||||
println("JoystickController claim this=", (uint32_t)this, HEX);
|
println("JoystickController claim this=", (uint32_t)this, HEX);
|
||||||
|
|
||||||
// only claim at device level
|
// Don't try to claim if it is used as USB device or HID device
|
||||||
if (type != 0) return false;
|
if (mydevice != NULL) return false;
|
||||||
|
if (device != nullptr) return false;
|
||||||
|
|
||||||
|
// Try claiming at the interface level.
|
||||||
|
if (type != 1) return false;
|
||||||
print_hexbytes(descriptors, len);
|
print_hexbytes(descriptors, len);
|
||||||
|
|
||||||
JoystickController::joytype_t jtype = mapVIDPIDtoJoystickType(dev->idVendor, dev->idProduct, true);
|
JoystickController::joytype_t jtype = mapVIDPIDtoJoystickType(dev->idVendor, dev->idProduct, true);
|
||||||
@ -354,21 +403,38 @@ bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descripto
|
|||||||
if (jtype == UNKNOWN)
|
if (jtype == UNKNOWN)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// XBOX One
|
||||||
// 0 1 2 3 4 5 6 7 8 *9 10 1 2 3 4 5 *6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1...
|
// 0 1 2 3 4 5 6 7 8 *9 10 1 2 3 4 5 *6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1...
|
||||||
// 09 04 00 00 02 FF 47 D0 00 07 05 02 03 40 00 04 07 05 82 03 40 00 04 09 04 01 00 00 FF 47 D0 00
|
// 09 04 00 00 02 FF 47 D0 00 07 05 02 03 40 00 04 07 05 82 03 40 00 04 09 04 01 00 00 FF 47 D0 00
|
||||||
// Lets do some verifications to make sure.
|
// Lets do some verifications to make sure.
|
||||||
|
|
||||||
|
// XBOX 360 wireless... Has 8 interfaces. 4 joysticks (1, 3, 5, 7) and 4 headphones assume 2,4,6, 8...
|
||||||
|
// Shows data for #1 only...
|
||||||
|
// Also they have some unknown data type we need to ignore between interface and end points.
|
||||||
|
// 0 1 2 3 4 5 6 7 8 *9 10 1 2 3 4 5 *6 7 8 9 20 1 2 3 4 5 6 7 8
|
||||||
|
// 09 04 00 00 02 FF 5D 81 00 14 22 00 01 13 81 1D 00 17 01 02 08 13 01 0C 00 0C 01 02 08
|
||||||
|
|
||||||
|
// 29 30 1 2 3 4 5 6 7 8 9 40 41 42
|
||||||
|
// 07 05 81 03 20 00 01 07 05 01 03 20 00 08
|
||||||
|
|
||||||
if (len < 9+7+7) return false;
|
if (len < 9+7+7) return false;
|
||||||
|
|
||||||
|
// Some common stuff for both XBoxs
|
||||||
uint32_t count_end_points = descriptors[4];
|
uint32_t count_end_points = descriptors[4];
|
||||||
if (count_end_points < 2) return false;
|
if (count_end_points < 2) return false;
|
||||||
if (descriptors[5] != 0xff) return false; // bInterfaceClass, 3 = HID
|
if (descriptors[5] != 0xff) return false; // bInterfaceClass, 3 = HID
|
||||||
uint32_t rxep = 0;
|
rx_ep_ = 0;
|
||||||
uint32_t txep = 0;
|
uint32_t txep = 0;
|
||||||
|
uint8_t rx_interval = 0;
|
||||||
|
uint8_t tx_interval = 0;
|
||||||
rx_size_ = 0;
|
rx_size_ = 0;
|
||||||
tx_size_ = 0;
|
tx_size_ = 0;
|
||||||
uint32_t descriptor_index = 9;
|
uint32_t descriptor_index = 9;
|
||||||
while (count_end_points-- && ((rxep == 0) || txep == 0)) {
|
if (descriptors[descriptor_index+1] == 0x22) {
|
||||||
|
if (descriptors[descriptor_index] != 0x14) return false; // only support specific versions...
|
||||||
|
descriptor_index += descriptors[descriptor_index]; // XBox360w ignore this unknown setup...
|
||||||
|
}
|
||||||
|
while (count_end_points-- && ((rx_ep_ == 0) || txep == 0)) {
|
||||||
if (descriptors[descriptor_index] != 7) return false; // length 7
|
if (descriptors[descriptor_index] != 7) return false; // length 7
|
||||||
if (descriptors[descriptor_index+1] != 5) return false; // ep desc
|
if (descriptors[descriptor_index+1] != 5) return false; // ep desc
|
||||||
if ((descriptors[descriptor_index+3] == 3) // Type 3...
|
if ((descriptors[descriptor_index+3] == 3) // Type 3...
|
||||||
@ -376,24 +442,26 @@ bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descripto
|
|||||||
&& (descriptors[descriptor_index+5] == 0)) {
|
&& (descriptors[descriptor_index+5] == 0)) {
|
||||||
// have a bulk EP size
|
// have a bulk EP size
|
||||||
if (descriptors[descriptor_index+2] & 0x80 ) {
|
if (descriptors[descriptor_index+2] & 0x80 ) {
|
||||||
rxep = descriptors[descriptor_index+2];
|
rx_ep_ = descriptors[descriptor_index+2];
|
||||||
rx_size_ = descriptors[descriptor_index+4];
|
rx_size_ = descriptors[descriptor_index+4];
|
||||||
|
rx_interval = descriptors[descriptor_index+6];
|
||||||
} else {
|
} else {
|
||||||
txep = descriptors[descriptor_index+2];
|
txep = descriptors[descriptor_index+2];
|
||||||
tx_size_ = descriptors[descriptor_index+4];
|
tx_size_ = descriptors[descriptor_index+4];
|
||||||
|
tx_interval = descriptors[descriptor_index+6];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptor_index += 7; // setup to look at next one...
|
descriptor_index += 7; // setup to look at next one...
|
||||||
}
|
}
|
||||||
if ((rxep == 0) || (txep == 0)) return false; // did not find two end points.
|
if ((rx_ep_ == 0) || (txep == 0)) return false; // did not find two end points.
|
||||||
print("JoystickController, rxep=", rxep & 15);
|
print("JoystickController, rx_ep_=", rx_ep_ & 15);
|
||||||
print("(", rx_size_);
|
print("(", rx_size_);
|
||||||
print("), txep=", txep);
|
print("), txep=", txep);
|
||||||
print("(", tx_size_);
|
print("(", tx_size_);
|
||||||
println(")");
|
println(")");
|
||||||
rxpipe_ = new_Pipe(dev, 2, rxep & 15, 1, rx_size_);
|
rxpipe_ = new_Pipe(dev, 3, rx_ep_ & 15, 1, rx_size_, rx_interval);
|
||||||
if (!rxpipe_) return false;
|
if (!rxpipe_) return false;
|
||||||
txpipe_ = new_Pipe(dev, 2, txep, 0, tx_size_);
|
txpipe_ = new_Pipe(dev, 3, txep, 0, tx_size_, tx_interval);
|
||||||
if (!txpipe_) {
|
if (!txpipe_) {
|
||||||
//free_Pipe(rxpipe_);
|
//free_Pipe(rxpipe_);
|
||||||
return false;
|
return false;
|
||||||
@ -403,7 +471,13 @@ bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descripto
|
|||||||
|
|
||||||
txpipe_->callback_function = tx_callback;
|
txpipe_->callback_function = tx_callback;
|
||||||
|
|
||||||
queue_Data_Transfer(txpipe_, start_input, sizeof(start_input), this);
|
if (jtype == XBOXONE) {
|
||||||
|
queue_Data_Transfer(txpipe_, xboxone_start_input, sizeof(xboxone_start_input), this);
|
||||||
|
connected_ = true; // remember that hardware is actually connected...
|
||||||
|
} else if (jtype == XBOX360) {
|
||||||
|
queue_Data_Transfer(txpipe_, xbox360w_inquire_present, sizeof(xbox360w_inquire_present), this);
|
||||||
|
connected_ = 0; // remember that hardware is actually connected...
|
||||||
|
}
|
||||||
memset(axis, 0, sizeof(axis)); // clear out any data.
|
memset(axis, 0, sizeof(axis)); // clear out any data.
|
||||||
joystickType = jtype; // remember we are an XBox One.
|
joystickType = jtype; // remember we are an XBox One.
|
||||||
return true;
|
return true;
|
||||||
@ -447,18 +521,39 @@ typedef struct {
|
|||||||
// dpad up, down left, right
|
// dpad up, down left, right
|
||||||
// lb, rb, left stick, right stick
|
// lb, rb, left stick, right stick
|
||||||
// Axis:
|
// Axis:
|
||||||
// lt, rt, lx, xy, rx, ry
|
// lt, rt, lx, ly, rx, ry
|
||||||
//
|
//
|
||||||
uint16_t buttons;
|
uint16_t buttons;
|
||||||
int16_t axis[6];
|
int16_t axis[6];
|
||||||
} xbox1data20_t;
|
} xbox1data20_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t state;
|
||||||
|
uint8_t id_or_type;
|
||||||
|
uint16_t controller_status;
|
||||||
|
uint16_t unknown;
|
||||||
|
// From online references button order:
|
||||||
|
// sync, dummy, start, back, a, b, x, y
|
||||||
|
// dpad up, down left, right
|
||||||
|
// lb, rb, left stick, right stick
|
||||||
|
// Axis:
|
||||||
|
// lt, rt, lx, ly, rx, ry
|
||||||
|
//
|
||||||
|
uint16_t buttons;
|
||||||
|
uint8_t lt;
|
||||||
|
uint8_t rt;
|
||||||
|
int16_t axis[4];
|
||||||
|
} xbox360data_t;
|
||||||
|
|
||||||
static const uint8_t xbox_axis_order_mapping[] = {4, 5, 0, 1, 2, 3};
|
static const uint8_t xbox_axis_order_mapping[] = {4, 5, 0, 1, 2, 3};
|
||||||
|
|
||||||
void JoystickController::rx_data(const Transfer_t *transfer)
|
void JoystickController::rx_data(const Transfer_t *transfer)
|
||||||
{
|
{
|
||||||
// print("JoystickController::rx_data: ");
|
print("JoystickController::rx_data: ");
|
||||||
// print_hexbytes((uint8_t*)transfer->buffer, transfer->length);
|
print_hexbytes((uint8_t*)transfer->buffer, transfer->length);
|
||||||
|
|
||||||
|
if (joystickType == XBOXONE) {
|
||||||
|
// Process XBOX One data
|
||||||
axis_mask_ = 0x3f;
|
axis_mask_ = 0x3f;
|
||||||
axis_changed_mask_ = 0; // assume none for now
|
axis_changed_mask_ = 0; // assume none for now
|
||||||
xbox1data20_t *xb1d = (xbox1data20_t *)transfer->buffer;
|
xbox1data20_t *xb1d = (xbox1data20_t *)transfer->buffer;
|
||||||
@ -473,12 +568,66 @@ void JoystickController::rx_data(const Transfer_t *transfer)
|
|||||||
int axis_value = (i < 2)? (int)(uint16_t)xb1d->axis[i] : xb1d->axis[i];
|
int axis_value = (i < 2)? (int)(uint16_t)xb1d->axis[i] : xb1d->axis[i];
|
||||||
if (axis_value != axis[xbox_axis_order_mapping[i]]) {
|
if (axis_value != axis[xbox_axis_order_mapping[i]]) {
|
||||||
axis[xbox_axis_order_mapping[i]] = axis_value;
|
axis[xbox_axis_order_mapping[i]] = axis_value;
|
||||||
|
axis_changed_mask_ |= (1 << xbox_axis_order_mapping[i]);
|
||||||
anychange = true;
|
anychange = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
joystickEvent = true;
|
joystickEvent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (joystickType == XBOX360) {
|
||||||
|
// First byte appears to status - if the byte is 0x8 it is a connect or disconnect of the controller.
|
||||||
|
xbox360data_t *xb360d = (xbox360data_t *)transfer->buffer;
|
||||||
|
if (xb360d->state == 0x08) {
|
||||||
|
if (xb360d->id_or_type != connected_) {
|
||||||
|
connected_ = xb360d->id_or_type; // remember it...
|
||||||
|
if (connected_) {
|
||||||
|
println("XBox360w - Connected type:", connected_, HEX);
|
||||||
|
// rx_ep_ should be 1, 3, 5, 7 for the wireless convert to 2-5 on led
|
||||||
|
setLEDs(2+rx_ep_/2); // Right now hard coded to first joystick...
|
||||||
|
|
||||||
|
} else {
|
||||||
|
println("XBox360w - disconnected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if((xb360d->id_or_type == 0x00) && (xb360d->controller_status & 0x1300)) {
|
||||||
|
// Controller status report - Maybe we should save away and allow the user access?
|
||||||
|
println("XBox360w - controllerStatus: ", xb360d->controller_status, HEX);
|
||||||
|
} else if(xb360d->id_or_type == 0x01) { // Lets only process report 1.
|
||||||
|
//const uint8_t *pbuffer = (uint8_t*)transfer->buffer;
|
||||||
|
//for (uint8_t i = 0; i < transfer->length; i++) Serial.printf("%02x ", pbuffer[i]);
|
||||||
|
//Serial.printf("\n");
|
||||||
|
|
||||||
|
if (buttons != xb360d->buttons) {
|
||||||
|
buttons = xb360d->buttons;
|
||||||
|
anychange = true;
|
||||||
|
}
|
||||||
|
axis_mask_ = 0x3f;
|
||||||
|
axis_changed_mask_ = 0; // assume none for now
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
|
if (axis[i] != xb360d->axis[i]) {
|
||||||
|
axis[i] = xb360d->axis[i];
|
||||||
|
axis_changed_mask_ |= (1 << i);
|
||||||
|
anychange = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// the two triggers show up as 4 and 5
|
||||||
|
if (axis[4] != xb360d->lt) {
|
||||||
|
axis[4] = xb360d->lt;
|
||||||
|
axis_changed_mask_ |= (1 << 4);
|
||||||
|
anychange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (axis[5] != xb360d->rt) {
|
||||||
|
axis[5] = xb360d->rt;
|
||||||
|
axis_changed_mask_ |= (1 << 5);
|
||||||
|
anychange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anychange) joystickEvent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
queue_Data_Transfer(rxpipe_, rxbuf_, rx_size_, this);
|
queue_Data_Transfer(rxpipe_, rxbuf_, rx_size_, this);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ USBSerial KEYWORD1
|
|||||||
AntPlus KEYWORD1
|
AntPlus KEYWORD1
|
||||||
JoystickController KEYWORD1
|
JoystickController KEYWORD1
|
||||||
RawHIDController KEYWORD1
|
RawHIDController KEYWORD1
|
||||||
|
BluetoothController KEYWORD1
|
||||||
# Common Functions
|
# Common Functions
|
||||||
Task KEYWORD2
|
Task KEYWORD2
|
||||||
idVendor KEYWORD2
|
idVendor KEYWORD2
|
||||||
@ -90,6 +90,7 @@ joystickType KEYWORD2
|
|||||||
PS3 LITERAL1
|
PS3 LITERAL1
|
||||||
PS4 LITERAL1
|
PS4 LITERAL1
|
||||||
XBOXONE LITERAL1
|
XBOXONE LITERAL1
|
||||||
|
XBOX360 LITERAL1
|
||||||
|
|
||||||
# USBSerial
|
# USBSerial
|
||||||
USBHOST_SERIAL_7E1 LITERAL1
|
USBHOST_SERIAL_7E1 LITERAL1
|
||||||
|
Loading…
Reference in New Issue
Block a user