mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-24 01:52:23 -05:00
Merge pull request #19 from KurtE/XBOX-360-Wireless
XBox360 Wireless controller
This commit is contained in:
commit
fd4842d94b
@ -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)) {
|
||||||
|
213
joystick.cpp
213
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;
|
||||||
|
|
||||||
// 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...
|
// 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...
|
||||||
// 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,38 +521,113 @@ 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);
|
||||||
axis_mask_ = 0x3f;
|
|
||||||
axis_changed_mask_ = 0; // assume none for now
|
if (joystickType == XBOXONE) {
|
||||||
xbox1data20_t *xb1d = (xbox1data20_t *)transfer->buffer;
|
// Process XBOX One data
|
||||||
if ((xb1d->type == 0x20) && (transfer->length >= sizeof (xbox1data20_t))) {
|
axis_mask_ = 0x3f;
|
||||||
// We have a data transfer. Lets see what is new...
|
axis_changed_mask_ = 0; // assume none for now
|
||||||
if (xb1d->buttons != buttons) {
|
xbox1data20_t *xb1d = (xbox1data20_t *)transfer->buffer;
|
||||||
buttons = xb1d->buttons;
|
if ((xb1d->type == 0x20) && (transfer->length >= sizeof (xbox1data20_t))) {
|
||||||
anychange = true;
|
// We have a data transfer. Lets see what is new...
|
||||||
}
|
if (xb1d->buttons != buttons) {
|
||||||
for (uint8_t i = 0; i < sizeof (xbox_axis_order_mapping); i++) {
|
buttons = xb1d->buttons;
|
||||||
// The first two values were unsigned.
|
|
||||||
int axis_value = (i < 2)? (int)(uint16_t)xb1d->axis[i] : xb1d->axis[i];
|
|
||||||
if (axis_value != axis[xbox_axis_order_mapping[i]]) {
|
|
||||||
axis[xbox_axis_order_mapping[i]] = axis_value;
|
|
||||||
anychange = true;
|
anychange = true;
|
||||||
}
|
}
|
||||||
|
for (uint8_t i = 0; i < sizeof (xbox_axis_order_mapping); i++) {
|
||||||
|
// The first two values were unsigned.
|
||||||
|
int axis_value = (i < 2)? (int)(uint16_t)xb1d->axis[i] : xb1d->axis[i];
|
||||||
|
if (axis_value != axis[xbox_axis_order_mapping[i]]) {
|
||||||
|
axis[xbox_axis_order_mapping[i]] = axis_value;
|
||||||
|
axis_changed_mask_ |= (1 << xbox_axis_order_mapping[i]);
|
||||||
|
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