Quellcode durchsuchen

Merge pull request #14 from KurtE/Joystick_More_Axis_Rumble

Joystick - USB enhance More Axis, Rumble, LEDS
main
Paul Stoffregen vor 6 Jahren
Ursprung
Commit
84d1df0065
Es ist kein Account mit der E-Mail-Adresse des Committers verbunden
5 geänderte Dateien mit 380 neuen und 36 gelöschten Zeilen
  1. +41
    -7
      USBHost_t36.h
  2. +93
    -6
      examples/Mouse/Mouse.ino
  3. +43
    -10
      hid.cpp
  4. +194
    -13
      joystick.cpp
  5. +9
    -0
      keywords.txt

+ 41
- 7
USBHost_t36.h Datei anzeigen

@@ -603,7 +603,11 @@ class USBHIDParser : public USBDriver {
public:
USBHIDParser(USBHost &host) { init(); }
static void driver_ready_for_hid_collection(USBHIDInput *driver);
bool sendPacket(const uint8_t *buffer);
bool sendPacket(const uint8_t *buffer, int cb=-1);
void setTXBuffers(uint8_t *buffer1, uint8_t *buffer2, uint8_t cb);

bool sendControlPacket(uint32_t bmRequestType, uint32_t bRequest,
uint32_t wValue, uint32_t wIndex, uint32_t wLength, void *buf);
protected:
enum { TOPUSAGE_LIST_LEN = 4 };
enum { USAGE_LIST_LEN = 24 };
@@ -783,9 +787,19 @@ public:
bool available() { return joystickEvent; }
void joystickDataClear();
uint32_t getButtons() { return buttons; }
int getAxis(uint32_t index) { return (index < (sizeof(axis)/sizeof(axis[0]))) ? axis[index] : 0; }
uint32_t axisMask() {return axis_mask_;}
enum { AXIS_COUNT = 10 };
int getAxis(uint32_t index) { return (index < (sizeof(axis)/sizeof(axis[0]))) ? axis[index] : 0; }
uint64_t axisMask() {return axis_mask_;}
uint64_t axisChangedMask() { return axis_changed_mask_;}
uint64_t axisChangeNotifyMask() {return axis_change_notify_mask_;}
void axisChangeNotifyMask(uint64_t notify_mask) {axis_change_notify_mask_ = notify_mask;}

// set functions functionality depends on underlying joystick.
bool setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeout=0xff);
// 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,
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;
joytype_t joystickType = UNKNOWN;
protected:
// From USBDriver
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
@@ -798,16 +812,34 @@ protected:
virtual void hid_input_data(uint32_t usage, int32_t value);
virtual void hid_input_end();
virtual void disconnect_collection(Device_t *dev);
virtual bool hid_process_out_data(const Transfer_t *transfer);
private:

// Class specific
void init();
USBHIDParser *driver_ = nullptr;
joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices);
bool transmitPS4UserFeedbackMsg();
bool transmitPS3UserFeedbackMsg();

bool anychange = false;
volatile bool joystickEvent = false;
uint32_t buttons = 0;
int axis[AXIS_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t axis_mask_ = 0; // which axis have valid data
int axis[TOTAL_AXIS_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint64_t axis_mask_ = 0; // which axis have valid data
uint64_t axis_changed_mask_ = 0;
uint64_t axis_change_notify_mask_ = 0x3ff; // assume the low 10 values only.

uint16_t additional_axis_usage_page_ = 0;
uint16_t additional_axis_usage_start_ = 0;
uint16_t additional_axis_usage_count_ = 0;

// State values to output to Joystick.
uint8_t rumble_lValue_ = 0;
uint8_t rumble_rValue_ = 0;
uint8_t rumble_timeout_ = 0;
uint8_t leds_[3] = {0,0,0};


// Used by HID code
uint8_t collections_claimed = 0;
@@ -827,11 +859,13 @@ private:
Pipe_t *rxpipe_;
Pipe_t *txpipe_;
uint8_t rxbuf_[64]; // receive circular buffer
uint8_t txbuf_[64]; // buffer to use to send commands to joystick
// Mapping table to say which devices we handle
typedef struct {
uint16_t idVendor;
uint16_t idProduct;
joytype_t joyType;
bool hidDevice;
} product_vendor_mapping_t;
static product_vendor_mapping_t pid_vid_mapping[];


+ 93
- 6
examples/Mouse/Mouse.ino Datei anzeigen

@@ -9,7 +9,6 @@ USBHub hub1(myusb);
USBHub hub2(myusb);
KeyboardController keyboard1(myusb);
KeyboardController keyboard2(myusb);
//KeyboardHIDExtrasController hidextras(myusb);
USBHIDParser hid1(myusb);
USBHIDParser hid2(myusb);
USBHIDParser hid3(myusb);
@@ -17,6 +16,8 @@ USBHIDParser hid4(myusb);
USBHIDParser hid5(myusb);
MouseController mouse1(myusb);
JoystickController joystick1(myusb);
int user_axis[64];
uint32_t buttons_prev = 0;
RawHIDController rawhid1(myusb);
RawHIDController rawhid2(myusb, 0xffc90004);

@@ -30,7 +31,11 @@ USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2};
#define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0]))
const char * hid_driver_names[CNT_DEVICES] = {"Mouse1","Joystick1", "RawHid1", "RawHid2"};
bool hid_driver_active[CNT_DEVICES] = {false, false};
bool show_changed_only = false;

uint8_t joystick_left_trigger_value = 0;
uint8_t joystick_right_trigger_value = 0;
uint64_t joystick_full_notify_mask = (uint64_t)-1;

void setup()
{
@@ -54,6 +59,27 @@ void loop()
{
myusb.Task();

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");
joystick1.axisChangeNotifyMask(0x3ff);
} else if ((ch == 'f') || (ch == 'F')) {
Serial.println("Only notify on Full Axis changes");
joystick1.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 (uint8_t i = 0; i < CNT_DEVICES; i++) {
if (*drivers[i] != driver_active[i]) {
if (driver_active[i]) {
@@ -109,14 +135,75 @@ void loop()
mouse1.mouseDataClear();
}
if (joystick1.available()) {
uint32_t axis_mask = joystick1.axisMask();
uint64_t axis_mask = joystick1.axisMask();
uint64_t axis_changed_mask = joystick1.axisChangedMask();
Serial.print("Joystick: buttons = ");
Serial.print(joystick1.getButtons(), HEX);
for (uint8_t i = 0; axis_mask != 0; i++, axis_mask >>= 1) {
if (axis_mask & 1) {
Serial.printf(" %d:%d", i, joystick1.getAxis(i));
uint32_t buttons = joystick1.getButtons();
Serial.print(buttons, HEX);
//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, joystick1.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, joystick1.getAxis(i));
}
}

} else {
for (uint8_t i = 0; axis_mask != 0; i++, axis_mask >>= 1) {
if (axis_mask & 1) {
Serial.printf(" %d:%d", i, joystick1.getAxis(i));
}
}
}
uint8_t ltv;
uint8_t rtv;
switch (joystick1.joystickType) {
default:
break;
case JoystickController::PS4:
ltv = joystick1.getAxis(3);
rtv = joystick1.getAxis(4);
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv;
joystick1.setRumble(ltv, rtv);
}
break;

case JoystickController::PS3:
ltv = joystick1.getAxis(18);
rtv = joystick1.getAxis(19);
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv;
joystick1.setRumble(ltv, rtv, 50);
}
break;

case JoystickController::XBOXONE:
ltv = joystick1.getAxis(4);
rtv = joystick1.getAxis(5);
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) {
joystick_left_trigger_value = ltv;
joystick_right_trigger_value = rtv;
joystick1.setRumble(ltv, rtv);
Serial.printf(" Set Rumble %d %d", ltv, rtv);
}
break;
}
if (buttons != buttons_prev) {
if (joystick1.joystickType == JoystickController::PS3) {
joystick1.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;
joystick1.setLEDs(lr, lg, lb);
}
buttons_prev = buttons;
}

Serial.println();
joystick1.joystickDataClear();
}

+ 43
- 10
hid.cpp Datei anzeigen

@@ -205,13 +205,12 @@ void USBHIDParser::disconnect()
// Called when the HID device sends a report
void USBHIDParser::in_data(const Transfer_t *transfer)
{
/*Serial.print("HID: ");
/*Serial.printf("HID: ");
uint8_t *pb = (uint8_t*)transfer->buffer;
for (uint8_t i = 0; i < transfer->length; i++) {
Serial.print(pb[i], HEX);
Serial.print(" ");
Serial.printf("%x ",pb[i]);
}
Serial.println(); */
Serial.printf("\n"); */

print("HID: ");
print(use_report_id);
@@ -249,7 +248,7 @@ void USBHIDParser::out_data(const Transfer_t *transfer)
}
}

bool USBHIDParser::sendPacket(const uint8_t *buffer) {
bool USBHIDParser::sendPacket(const uint8_t *buffer, int cb) {
if (!out_size || !out_pipe) return false;
if (!tx1) {
// Was not init before, for now lets put it at end of descriptor
@@ -259,22 +258,40 @@ bool USBHIDParser::sendPacket(const uint8_t *buffer) {
tx2 = tx1 - out_size;
}
if ((txstate & 3) == 3) return false; // both transmit buffers are full
if (cb == -1)
cb = out_size;
uint8_t *p = tx1;
if ((txstate & 1) == 0) {
txstate |= 1;
} else {
if (!tx2)
return false; // only one buffer
txstate |= 2;
p = tx2;
}
// copy the users data into our out going buffer
memcpy(p, buffer, out_size);
memcpy(p, buffer, cb);
println("USBHIDParser Send packet");
print_hexbytes(buffer, out_size);
queue_Data_Transfer(out_pipe, p, out_size, this);
print_hexbytes(buffer, cb);
queue_Data_Transfer(out_pipe, p, cb, this);
println(" Queue_data transfer returned");
return true;
}

void USBHIDParser::setTXBuffers(uint8_t *buffer1, uint8_t *buffer2, uint8_t cb)
{
tx1 = buffer1;
tx2 = buffer2;
}

bool USBHIDParser::sendControlPacket(uint32_t bmRequestType, uint32_t bRequest,
uint32_t wValue, uint32_t wIndex, uint32_t wLength, void *buf)
{
// Use setup structure to build packet
mk_setup(setup, bmRequestType, bRequest, wValue, wIndex, wLength); // ps3 tell to send report 1?
return queue_Control_Transfer(device, &setup, buf, this);
}


// This no-inputs parse is meant to be used when we first get the
// HID report descriptor. It finds all the top level collections
@@ -444,6 +461,7 @@ void USBHIDParser::parse(uint16_t type_and_report_id, const uint8_t *data, uint3
uint16_t report_size = 0;
uint16_t report_count = 0;
uint16_t usage_page = 0;
uint32_t last_usage = 0;
int32_t logical_min = 0;
int32_t logical_max = 0;
uint32_t bitindex = 0;
@@ -551,23 +569,38 @@ void USBHIDParser::parse(uint16_t type_and_report_id, const uint8_t *data, uint3
if ((val & 2)) {
// ordinary variable format
uint32_t uindex = 0;
uint32_t uindex_max = 0xffff; // assume no MAX
bool uminmax = false;
if (usage_count > USAGE_LIST_LEN || usage_count == 0) {
if (usage_count > USAGE_LIST_LEN) {
// usage numbers by min/max, not from list
uindex = usage[0];
uindex_max = usage[1];
uminmax = true;
} else if ((report_count > 1) && (usage_count <= 1)) {
// Special cases: Either only one or no usages specified and there are more than one
// report counts .
if (usage_count == 1) {
uindex = usage[0];
} else {
// BUGBUG:: Not sure good place to start? maybe round up from last usage to next higher group up of 0x100?
uindex = (last_usage & 0xff00) + 0x100;
}
uminmax = true;
}
//Serial.printf("TU:%x US:%x %x %d %d: C:%d, %d, MM:%d, %x %x\n", topusage, usage_page, val, logical_min, logical_max,
// report_count, usage_count, uminmax, usage[0], usage[1]);
for (uint32_t i=0; i < report_count; i++) {
uint32_t u;
if (uminmax) {
u = uindex;
if (uindex < usage[1]) uindex++;
if (uindex < uindex_max) uindex++;
} else {
u = usage[uindex++];
if (uindex >= USAGE_LIST_LEN-1) {
uindex = USAGE_LIST_LEN-1;
}
}
last_usage = u; // remember the last one we used...
u |= (uint32_t)usage_page << 16;
print(" usage = ", u, HEX);


+ 194
- 13
joystick.cpp Datei anzeigen

@@ -27,6 +27,18 @@
#define print USBHost::print_
#define println USBHost::println_

// PID/VID to joystick mapping - Only the XBOXOne is used to claim the USB interface directly,
// The others are used after claim-hid code to know which one we have and to use it for
// doing other features.
JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping[] = {
{ 0x045e, 0x02ea, XBOXONE, false },{ 0x045e, 0x02dd, XBOXONE, false },
{ 0x054C, 0x0268, PS3, true},
{ 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true }
};



//-----------------------------------------------------------------------------
void JoystickController::init()
{
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
@@ -36,6 +48,19 @@ void JoystickController::init()
USBHIDParser::driver_ready_for_hid_collection(this);
}

//-----------------------------------------------------------------------------
JoystickController::joytype_t JoystickController::mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices)
{
for (uint8_t i = 0; i < (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0])); i++) {
if ((idVendor == pid_vid_mapping[i].idVendor) && (idProduct == pid_vid_mapping[i].idProduct)) {
println("Match PID/VID: ", i, DEC);
if (exclude_hid_devices && pid_vid_mapping[i].hidDevice) return UNKNOWN;
return pid_vid_mapping[i].joyType;
}
}
return UNKNOWN; // Not in our list
}

//*****************************************************************************
// Some simple query functions depend on which interface we are using...
//*****************************************************************************
@@ -76,9 +101,109 @@ const uint8_t *JoystickController::serialNumber()
}


bool JoystickController::setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeout)
{
// Need to know which joystick we are on. Start off with XBox support - maybe need to add some enum value for the known
// joystick types.
rumble_lValue_ = lValue;
rumble_rValue_ = rValue;
rumble_timeout_ = timeout;

switch (joystickType) {
default:
break;
case PS3:
return transmitPS3UserFeedbackMsg();
case PS4:
return transmitPS4UserFeedbackMsg();
case XBOXONE:
// Lets try sending a request to the XBox 1.
txbuf_[0] = 0x9;
txbuf_[1] = 0x8;
txbuf_[2] = 0x0;
txbuf_[3] = 0x08; // Substructure (what substructure rest of this packet has)
txbuf_[4] = 0x00; // Mode
txbuf_[5] = 0x0f; // Rumble mask (what motors are activated) (0000 lT rT L R)
txbuf_[6] = 0x0; // lT force
txbuf_[7] = 0x0; // rT force
txbuf_[8] = lValue; // L force
txbuf_[9] = rValue; // R force
txbuf_[10] = 0x80; // Length of pulse
txbuf_[11] = 0x00; // Period between pulses
if (!queue_Data_Transfer(txpipe_, txbuf_, 12, this)) {
println("XBoxOne rumble transfer fail");
}
return true; //
}
return false;
}

bool JoystickController::setLEDs(uint8_t lr, uint8_t lg, uint8_t lb)
{
// Need to know which joystick we are on. Start off with XBox support - maybe need to add some enum value for the known
// joystick types.
if ((leds_[0] != lr) || (leds_[1] != lg) || (leds_[2] != lb)) {
leds_[0] = lr;
leds_[1] = lg;
leds_[2] = lb;

switch (joystickType) {
case PS3:
return transmitPS3UserFeedbackMsg();
case PS4:
return transmitPS4UserFeedbackMsg();
default:
return false;
}
}
return false;
}

bool JoystickController::transmitPS4UserFeedbackMsg() {
if (!driver_) return false;
uint8_t packet[32];
memset(packet, 0, sizeof(packet));

packet[0] = 0x05; // Report ID
packet[1]= 0xFF;

packet[4] = rumble_lValue_; // Small Rumble
packet[5] = rumble_rValue_; // Big rumble
packet[6] = leds_[0]; // RGB value
packet[7] = leds_[1];
packet[8] = leds_[2];
// 9, 10 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255
Serial.printf("Joystick update Rumble/LEDs");
return driver_->sendPacket(packet, 32);
}

static const uint8_t PS3_USER_FEEDBACK_INIT[] = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00 };

bool JoystickController::transmitPS3UserFeedbackMsg() {
if (!driver_) return false;
memcpy(txbuf_, PS3_USER_FEEDBACK_INIT, 48);

txbuf_[1] = rumble_lValue_? rumble_timeout_ : 0;
txbuf_[2] = rumble_lValue_; // Small Rumble
txbuf_[3] = rumble_rValue_? rumble_timeout_ : 0;
txbuf_[4] = rumble_rValue_; // Big rumble
txbuf_[9] = leds_[0] << 1; // RGB value
//Serial.printf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[1], txbuf_[2], txbuf_[3], txbuf_[4], txbuf_[9]);
return driver_->sendControlPacket(0x21, 9, 0x201, 0, 48, txbuf_);
}

//*****************************************************************************
// Support for Joysticks that USe HID data.
// Support for Joysticks that Use HID data.
//*****************************************************************************

hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage)
@@ -90,6 +215,31 @@ hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *
mydevice = dev;
collections_claimed++;
anychange = true; // always report values on first read
driver_ = driver; // remember the driver.
driver_->setTXBuffers(txbuf_, nullptr, sizeof(txbuf_));

// 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);
switch (joystickType) {
case PS3:
additional_axis_usage_page_ = 0x1;
additional_axis_usage_start_ = 0x100;
additional_axis_usage_count_ = 39;
axis_change_notify_mask_ = (uint64_t)-1; // Start off assume all bits
break;
case PS4:
additional_axis_usage_page_ = 0xFF00;
additional_axis_usage_start_ = 0x21;
additional_axis_usage_count_ = 54;
axis_change_notify_mask_ = (uint64_t)0xfffffffffffff3ffl; // Start off assume all bits - 10 and 11
break;
default:
additional_axis_usage_page_ = 0;
additional_axis_usage_start_ = 0;
additional_axis_usage_count_ = 0;
axis_change_notify_mask_ = 0x3ff; // Start off assume only the 10 bits...
}
Serial.printf("Claim Additional axis: %x %x %d\n", additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_);
return CLAIM_REPORT;
}

@@ -97,7 +247,9 @@ void JoystickController::disconnect_collection(Device_t *dev)
{
if (--collections_claimed == 0) {
mydevice = NULL;
driver_ = nullptr;
axis_mask_ = 0;
axis_changed_mask_ = 0;
}
}

@@ -131,8 +283,32 @@ void JoystickController::hid_input_data(uint32_t usage, int32_t value)
axis_mask_ |= (1 << i); // Keep record of which axis we have data on.
if (axis[i] != value) {
axis[i] = value;
anychange = true;
axis_changed_mask_ |= (1 << i);
if (axis_changed_mask_ & axis_change_notify_mask_)
anychange = true;
}
} else if (usage_page == additional_axis_usage_page_) {
// see if the usage is witin range.
//Serial.printf("UP: usage_page=%x usage=%x User: %x %d\n", usage_page, usage, user_buttons_usage_start, user_buttons_count_);
if ((usage >= additional_axis_usage_start_) && (usage < (additional_axis_usage_start_ + additional_axis_usage_count_))) {
// We are in the user range.
uint16_t usage_index = usage - additional_axis_usage_start_ + STANDARD_AXIS_COUNT;
if (usage_index < (sizeof(axis)/sizeof(axis[0]))) {
if (axis[usage_index] != value) {
axis[usage_index] = value;
if (usage_index > 63) usage_index = 63; // don't overflow our mask
axis_changed_mask_ |= ((uint64_t)1 << usage_index); // Keep track of which ones changed.
if (axis_changed_mask_ & axis_change_notify_mask_)
anychange = true; // We have changes...
}
axis_mask_ |= ((uint64_t)1 << usage_index); // Keep record of which axis we have data on.
}
//Serial.printf("UB: index=%x value=%x\n", usage_index, value);
}

} else {
Serial.printf("UP: usage_page=%x usage=%x add: %x %x %d\n", usage_page, usage, additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_);

}
// TODO: hat switch?
}
@@ -144,18 +320,23 @@ void JoystickController::hid_input_end()
}
}

bool JoystickController::hid_process_out_data(const Transfer_t *transfer)
{
Serial.printf("JoystickController::hid_process_out_data\n");
return true;
}

void JoystickController::joystickDataClear() {
joystickEvent = false;
anychange = false;
axis_changed_mask_ = 0;
axis_mask_ = 0;
}

//*****************************************************************************
// Support for Joysticks that are class specific and do not use HID
// Example: XBox One controller.
//*****************************************************************************
// Note: currently just XBOX one.
JoystickController::product_vendor_mapping_t JoystickController::pid_vid_mapping[] = {
{ 0x045e, 0x02ea },{ 0x045e, 0x02dd } };

static uint8_t start_input[] = {0x05, 0x20, 0x00, 0x01, 0x00};

@@ -167,15 +348,12 @@ bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descripto
if (type != 0) return false;
print_hexbytes(descriptors, len);

uint8_t i = 0;
for (; i < (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0])); i++) {
if ((dev->idVendor == pid_vid_mapping[i].idVendor) && (dev->idProduct == pid_vid_mapping[i].idProduct)) {
break;
}
}
if (i == (sizeof(pid_vid_mapping)/sizeof(pid_vid_mapping[0]))) return false; // Not in our list
JoystickController::joytype_t jtype = mapVIDPIDtoJoystickType(dev->idVendor, dev->idProduct, true);
println("Jtype=", (uint8_t)jtype, DEC);
if (jtype == UNKNOWN)
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...
// 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
// Lets do some verifications to make sure.

@@ -226,6 +404,7 @@ bool JoystickController::claim(Device_t *dev, int type, const uint8_t *descripto

queue_Data_Transfer(txpipe_, start_input, sizeof(start_input), this);
memset(axis, 0, sizeof(axis)); // clear out any data.
joystickType = jtype; // remember we are an XBox One.
return true;
}

@@ -280,6 +459,7 @@ void JoystickController::rx_data(const Transfer_t *transfer)
// print("JoystickController::rx_data: ");
// print_hexbytes((uint8_t*)transfer->buffer, transfer->length);
axis_mask_ = 0x3f;
axis_changed_mask_ = 0; // assume none for now
xbox1data20_t *xb1d = (xbox1data20_t *)transfer->buffer;
if ((xb1d->type == 0x20) && (transfer->length >= sizeof (xbox1data20_t))) {
// We have a data transfer. Lets see what is new...
@@ -309,6 +489,7 @@ void JoystickController::tx_data(const Transfer_t *transfer)
void JoystickController::disconnect()
{
axis_mask_ = 0;
axis_changed_mask_ = 0;
// TODO: free resources
}


+ 9
- 0
keywords.txt Datei anzeigen

@@ -81,6 +81,15 @@ getWheelH KEYWORD2
joystickDataClear KEYWORD2
getAxis KEYWORD2
axisMask KEYWORD2
axisChangedMask KEYWORD2
axisChangeNotifyMask KEYWORD2
userAxisMask KEYWORD2
setRumbleOn KEYWORD2
setLEDs KEYWORD2
joystickType KEYWORD2
PS3 LITERAL1
PS4 LITERAL1
XBOXONE LITERAL1

# USBSerial
USBHOST_SERIAL_7E1 LITERAL1

Laden…
Abbrechen
Speichern