#include <stdint.h> | #include <stdint.h> | ||||
#if !defined(__MK66FX1M0__) && !defined(__IMXRT1052__) && !defined(__IMXRT1062__) | #if !defined(__MK66FX1M0__) && !defined(__IMXRT1052__) && !defined(__IMXRT1062__) | ||||
#error "USBHost_t36 only works with Teensy 3.6. Please select it in Tools > Boards" | |||||
#error "USBHost_t36 only works with Teensy 3.6 or Teensy 4.x. Please select it in Tools > Boards" | |||||
#endif | #endif | ||||
#include "utility/imxrt_usbhs.h" | #include "utility/imxrt_usbhs.h" | ||||
//#define USBHOST_PRINT_DEBUG | //#define USBHOST_PRINT_DEBUG | ||||
//#define USBHDBGSerial Serial1 | |||||
#ifndef USBHDBGSerial | |||||
#define USBHDBGSerial Serial | |||||
#endif | |||||
/************************************************/ | /************************************************/ | ||||
/* Data Types */ | /* Data Types */ | ||||
static void print_config_descriptor(const uint8_t *p, uint32_t maxlen); | static void print_config_descriptor(const uint8_t *p, uint32_t maxlen); | ||||
static void print_string_descriptor(const char *name, const uint8_t *p); | static void print_string_descriptor(const char *name, const uint8_t *p); | ||||
static void print_hexbytes(const void *ptr, uint32_t len); | static void print_hexbytes(const void *ptr, uint32_t len); | ||||
static void print_(const char *s) { Serial.print(s); } | |||||
static void print_(int n) { Serial.print(n); } | |||||
static void print_(unsigned int n) { Serial.print(n); } | |||||
static void print_(long n) { Serial.print(n); } | |||||
static void print_(unsigned long n) { Serial.print(n); } | |||||
static void println_(const char *s) { Serial.println(s); } | |||||
static void println_(int n) { Serial.println(n); } | |||||
static void println_(unsigned int n) { Serial.println(n); } | |||||
static void println_(long n) { Serial.println(n); } | |||||
static void println_(unsigned long n) { Serial.println(n); } | |||||
static void println_() { Serial.println(); } | |||||
static void print_(uint32_t n, uint8_t b) { Serial.print(n, b); } | |||||
static void println_(uint32_t n, uint8_t b) { Serial.println(n, b); } | |||||
static void print_(const char *s) { USBHDBGSerial.print(s); } | |||||
static void print_(int n) { USBHDBGSerial.print(n); } | |||||
static void print_(unsigned int n) { USBHDBGSerial.print(n); } | |||||
static void print_(long n) { USBHDBGSerial.print(n); } | |||||
static void print_(unsigned long n) { USBHDBGSerial.print(n); } | |||||
static void println_(const char *s) { USBHDBGSerial.println(s); } | |||||
static void println_(int n) { USBHDBGSerial.println(n); } | |||||
static void println_(unsigned int n) { USBHDBGSerial.println(n); } | |||||
static void println_(long n) { USBHDBGSerial.println(n); } | |||||
static void println_(unsigned long n) { USBHDBGSerial.println(n); } | |||||
static void println_() { USBHDBGSerial.println(); } | |||||
static void print_(uint32_t n, uint8_t b) { USBHDBGSerial.print(n, b); } | |||||
static void println_(uint32_t n, uint8_t b) { USBHDBGSerial.println(n, b); } | |||||
static void print_(const char *s, int n, uint8_t b = DEC) { | static void print_(const char *s, int n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.print(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
static void print_(const char *s, unsigned int n, uint8_t b = DEC) { | static void print_(const char *s, unsigned int n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.print(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
static void print_(const char *s, long n, uint8_t b = DEC) { | static void print_(const char *s, long n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.print(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
static void print_(const char *s, unsigned long n, uint8_t b = DEC) { | static void print_(const char *s, unsigned long n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.print(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.print(n, b); } | |||||
static void println_(const char *s, int n, uint8_t b = DEC) { | static void println_(const char *s, int n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.println(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
static void println_(const char *s, unsigned int n, uint8_t b = DEC) { | static void println_(const char *s, unsigned int n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.println(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
static void println_(const char *s, long n, uint8_t b = DEC) { | static void println_(const char *s, long n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.println(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
static void println_(const char *s, unsigned long n, uint8_t b = DEC) { | static void println_(const char *s, unsigned long n, uint8_t b = DEC) { | ||||
Serial.print(s); Serial.println(n, b); } | |||||
USBHDBGSerial.print(s); USBHDBGSerial.println(n, b); } | |||||
friend class USBDriverTimer; // for access to print & println | friend class USBDriverTimer; // for access to print & println | ||||
#else | #else | ||||
static void print_(const Transfer_t *transfer) {} | static void print_(const Transfer_t *transfer) {} | ||||
virtual void hid_input_end(); | virtual void hid_input_end(); | ||||
virtual void disconnect_collection(Device_t *dev); | virtual void disconnect_collection(Device_t *dev); | ||||
void add_to_list(); | void add_to_list(); | ||||
USBHIDInput *next; | |||||
USBHIDInput *next = NULL; | |||||
friend class USBHIDParser; | friend class USBHIDParser; | ||||
protected: | protected: | ||||
Device_t *mydevice = NULL; | Device_t *mydevice = NULL; | ||||
}; | }; | ||||
// Device drivers may inherit from this base class, if they wish to receive | |||||
// HID input like data from Bluetooth HID device. | |||||
class BluetoothController; | |||||
class BTHIDInput { | |||||
public: | |||||
operator bool() { return (btdevice != nullptr); } | |||||
uint16_t idVendor() { return (btdevice != nullptr) ? btdevice->idVendor : 0; } | |||||
uint16_t idProduct() { return (btdevice != nullptr) ? btdevice->idProduct : 0; } | |||||
const uint8_t *manufacturer() | |||||
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; } | |||||
const uint8_t *product() | |||||
{ return remote_name_; } | |||||
const uint8_t *serialNumber() | |||||
{ return ((btdevice == nullptr) || (btdevice->strbuf == nullptr)) ? nullptr : &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; } | |||||
private: | |||||
virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class, uint8_t *remoteName) {return false;} | |||||
virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length) {return false;} | |||||
virtual void release_bluetooth() {}; | |||||
virtual bool remoteNameComplete(const uint8_t *remoteName) {return true;} | |||||
virtual void connectionComplete(void) {}; | |||||
void add_to_list(); | |||||
BTHIDInput *next = NULL; | |||||
friend class BluetoothController; | |||||
protected: | |||||
enum {SP_NEED_CONNECT=0x1, SP_DONT_NEED_CONNECT=0x02, SP_PS3_IDS=0x4}; | |||||
enum {REMOTE_NAME_SIZE=32}; | |||||
uint8_t special_process_required = 0; | |||||
Device_t *btdevice = NULL; | |||||
uint8_t remote_name_[REMOTE_NAME_SIZE] = {0}; | |||||
}; | |||||
/************************************************/ | /************************************************/ | ||||
/* USB Device Drivers */ | /* USB Device Drivers */ | ||||
/************************************************/ | /************************************************/ | ||||
uint16_t in_size; | uint16_t in_size; | ||||
uint16_t out_size; | uint16_t out_size; | ||||
setup_t setup; | setup_t setup; | ||||
uint8_t descriptor[512]; | |||||
uint8_t descriptor[800]; | |||||
uint8_t report[64]; | uint8_t report[64]; | ||||
uint16_t descsize; | uint16_t descsize; | ||||
bool use_report_id; | bool use_report_id; | ||||
//-------------------------------------------------------------------------- | //-------------------------------------------------------------------------- | ||||
class KeyboardController : public USBDriver , public USBHIDInput { | |||||
class KeyboardController : public USBDriver , public USBHIDInput, public BTHIDInput { | |||||
public: | public: | ||||
typedef union { | typedef union { | ||||
struct { | struct { | ||||
const uint8_t *product(); | const uint8_t *product(); | ||||
const uint8_t *serialNumber(); | const uint8_t *serialNumber(); | ||||
// Some methods are in both public classes so we need to figure out which one to use | |||||
operator bool() { return (device != nullptr); } | |||||
operator bool() { return ((device != nullptr) || (btdevice != nullptr)); } | |||||
// Main boot keyboard functions. | // Main boot keyboard functions. | ||||
uint16_t getKey() { return keyCode; } | uint16_t getKey() { return keyCode; } | ||||
uint8_t getModifiers() { return modifiers; } | uint8_t getModifiers() { return modifiers; } | ||||
void new_data(const Transfer_t *transfer); | void new_data(const Transfer_t *transfer); | ||||
void init(); | void init(); | ||||
// Bluetooth data | |||||
virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class, uint8_t *remoteName); | |||||
virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length); | |||||
virtual bool remoteNameComplete(const uint8_t *remoteName); | |||||
virtual void release_bluetooth(); | |||||
protected: // HID functions for extra keyboard data. | protected: // HID functions for extra keyboard data. | ||||
virtual hidclaim_t claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage); | virtual hidclaim_t claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage); | ||||
virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); | virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); | ||||
}; | }; | ||||
class MouseController : public USBHIDInput { | |||||
class MouseController : public USBHIDInput, public BTHIDInput { | |||||
public: | public: | ||||
MouseController(USBHost &host) { USBHIDParser::driver_ready_for_hid_collection(this); } | |||||
MouseController(USBHost &host) { init(); } | |||||
bool available() { return mouseEvent; } | bool available() { return mouseEvent; } | ||||
void mouseDataClear(); | void mouseDataClear(); | ||||
uint8_t getButtons() { return buttons; } | uint8_t getButtons() { return buttons; } | ||||
virtual void hid_input_data(uint32_t usage, int32_t value); | virtual void hid_input_data(uint32_t usage, int32_t value); | ||||
virtual void hid_input_end(); | virtual void hid_input_end(); | ||||
virtual void disconnect_collection(Device_t *dev); | virtual void disconnect_collection(Device_t *dev); | ||||
// Bluetooth data | |||||
virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class, uint8_t *remoteName); | |||||
virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length); | |||||
virtual void release_bluetooth(); | |||||
private: | private: | ||||
void init(); | |||||
BluetoothController *btdriver_ = nullptr; | |||||
uint8_t collections_claimed = 0; | uint8_t collections_claimed = 0; | ||||
volatile bool mouseEvent = false; | volatile bool mouseEvent = false; | ||||
volatile bool hid_input_begin_ = false; | volatile bool hid_input_begin_ = false; | ||||
//-------------------------------------------------------------------------- | //-------------------------------------------------------------------------- | ||||
class JoystickController : public USBDriver, public USBHIDInput { | |||||
class DigitizerController : public USBHIDInput, public BTHIDInput { | |||||
public: | |||||
DigitizerController(USBHost &host) { init(); } | |||||
bool available() { return digitizerEvent; } | |||||
void digitizerDataClear(); | |||||
uint8_t getButtons() { return buttons; } | |||||
int getMouseX() { return mouseX; } | |||||
int getMouseY() { return mouseY; } | |||||
int getWheel() { return wheel; } | |||||
int getWheelH() { return wheelH; } | |||||
int getAxis(uint32_t index) { return (index < (sizeof(digiAxes)/sizeof(digiAxes[0]))) ? digiAxes[index] : 0; } | |||||
protected: | |||||
virtual hidclaim_t claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage); | |||||
virtual void hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax); | |||||
virtual void hid_input_data(uint32_t usage, int32_t value); | |||||
virtual void hid_input_end(); | |||||
virtual void disconnect_collection(Device_t *dev); | |||||
private: | |||||
void init(); | |||||
uint8_t collections_claimed = 0; | |||||
volatile bool digitizerEvent = false; | |||||
volatile bool hid_input_begin_ = false; | |||||
uint8_t buttons = 0; | |||||
int mouseX = 0; | |||||
int mouseY = 0; | |||||
int wheel = 0; | |||||
int wheelH = 0; | |||||
int digiAxes[16]; | |||||
}; | |||||
//-------------------------------------------------------------------------- | |||||
class JoystickController : public USBDriver, public USBHIDInput, public BTHIDInput { | |||||
public: | public: | ||||
JoystickController(USBHost &host) { init(); } | JoystickController(USBHost &host) { init(); } | ||||
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)) && connected_); } // override as in both USBDriver and in USBHIDInput | |||||
operator bool() { return (((device != nullptr) || (mydevice != nullptr || (btdevice != nullptr))) && connected_); } // override as in both USBDriver and in USBHIDInput | |||||
bool available() { return joystickEvent; } | bool available() { return joystickEvent; } | ||||
void joystickDataClear(); | void joystickDataClear(); | ||||
// set functions functionality depends on underlying joystick. | // set functions functionality depends on underlying joystick. | ||||
bool setRumble(uint8_t lValue, uint8_t rValue, uint8_t timeout=0xff); | 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, | |||||
// setLEDs on PS4(RGB), PS3 simple LED setting (only uses lb) | |||||
bool setLEDs(uint8_t lr, uint8_t lg, uint8_t lb); // sets Leds, | |||||
bool inline setLEDs(uint32_t leds) {return setLEDs((leds >> 16) & 0xff, (leds >> 8) & 0xff, leds & 0xff);} // sets Leds - passing one arg for all 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, XBOX360} joytype_t; | |||||
joytype_t joystickType = UNKNOWN; | |||||
typedef enum { UNKNOWN=0, PS3, PS4, XBOXONE, XBOX360, PS3_MOTION, SpaceNav} joytype_t; | |||||
joytype_t joystickType() {return joystickType_;} | |||||
// PS3 pair function. hack, requires that it be connect4ed by USB and we have the address of the Bluetooth dongle... | |||||
bool PS3Pair(uint8_t* bdaddr); | |||||
protected: | protected: | ||||
// From USBDriver | // From USBDriver | ||||
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); | virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); | ||||
virtual void hid_input_end(); | virtual void hid_input_end(); | ||||
virtual void disconnect_collection(Device_t *dev); | virtual void disconnect_collection(Device_t *dev); | ||||
virtual bool hid_process_out_data(const Transfer_t *transfer); | virtual bool hid_process_out_data(const Transfer_t *transfer); | ||||
// Bluetooth data | |||||
virtual bool claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class, uint8_t *remoteName); | |||||
virtual bool process_bluetooth_HID_data(const uint8_t *data, uint16_t length); | |||||
virtual void release_bluetooth(); | |||||
virtual bool remoteNameComplete(const uint8_t *remoteName); | |||||
virtual void connectionComplete(void); | |||||
joytype_t joystickType_ = UNKNOWN; | |||||
private: | private: | ||||
// Class specific | // Class specific | ||||
void init(); | void init(); | ||||
USBHIDParser *driver_ = nullptr; | USBHIDParser *driver_ = nullptr; | ||||
BluetoothController *btdriver_ = nullptr; | |||||
joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices); | joytype_t mapVIDPIDtoJoystickType(uint16_t idVendor, uint16_t idProduct, bool exclude_hid_devices); | ||||
bool transmitPS4UserFeedbackMsg(); | bool transmitPS4UserFeedbackMsg(); | ||||
bool transmitPS3UserFeedbackMsg(); | bool transmitPS3UserFeedbackMsg(); | ||||
bool transmitPS3MotionUserFeedbackMsg(); | |||||
bool mapNameToJoystickType(const uint8_t *remoteName); | |||||
bool anychange = false; | bool anychange = false; | ||||
volatile bool joystickEvent = false; | volatile bool joystickEvent = false; | ||||
}; | }; | ||||
//-------------------------------------------------------------------------- | |||||
class BluetoothController: public USBDriver { | |||||
public: | |||||
BluetoothController(USBHost &host, bool pair = false, const char *pin = "0000") : do_pair_device_(pair), pair_pincode_(pin), delayTimer_(this) | |||||
{ init(); } | |||||
enum {MAX_ENDPOINTS=4, NUM_SERVICES=4, }; // Max number of Bluetooth services - if you need more than 4 simply increase this number | |||||
enum {BT_CLASS_DEVICE= 0x0804}; // Toy - Robot | |||||
static void driver_ready_for_bluetooth(BTHIDInput *driver); | |||||
const uint8_t* myBDAddr(void) {return my_bdaddr_;} | |||||
// BUGBUG version to allow some of the controlled objects to call? | |||||
enum {CONTROL_SCID=-1, INTERRUPT_SCID=-2}; | |||||
void sendL2CapCommand(uint8_t* data, uint8_t nbytes, int channel = (int)0x0001); | |||||
protected: | |||||
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); | |||||
virtual void control(const Transfer_t *transfer); | |||||
virtual void disconnect(); | |||||
virtual void timer_event(USBDriverTimer *whichTimer); | |||||
BTHIDInput * find_driver(uint32_t device_type, uint8_t *remoteName=nullptr); | |||||
// Hack to allow PS3 to maybe change values | |||||
uint16_t connection_rxid_ = 0; | |||||
uint16_t control_dcid_ = 0x70; | |||||
uint16_t interrupt_dcid_ = 0x71; | |||||
uint16_t interrupt_scid_; | |||||
uint16_t control_scid_; | |||||
private: | |||||
friend class BTHIDInput; | |||||
static void rx_callback(const Transfer_t *transfer); | |||||
static void rx2_callback(const Transfer_t *transfer); | |||||
static void tx_callback(const Transfer_t *transfer); | |||||
void rx_data(const Transfer_t *transfer); | |||||
void rx2_data(const Transfer_t *transfer); | |||||
void tx_data(const Transfer_t *transfer); | |||||
void init(); | |||||
// HCI support functions... | |||||
void sendHCICommand(uint16_t hciCommand, uint16_t cParams, const uint8_t* data); | |||||
//void sendHCIReadLocalSupportedFeatures(); | |||||
void inline sendHCI_INQUIRY(); | |||||
void inline sendHCIInquiryCancel(); | |||||
void inline sendHCICreateConnection(); | |||||
void inline sendHCIAuthenticationRequested(); | |||||
void inline sendHCIAcceptConnectionRequest(); | |||||
void inline sendHCILinkKeyNegativeReply(); | |||||
void inline sendHCIPinCodeReply(); | |||||
void inline sendResetHCI(); | |||||
void inline sendHDCWriteClassOfDev(); | |||||
void inline sendHCIReadBDAddr(); | |||||
void inline sendHCIReadLocalVersionInfo(); | |||||
void inline sendHCIWriteScanEnable(uint8_t scan_op); | |||||
void inline sendHCIHCIWriteInquiryMode(uint8_t inquiry_mode); | |||||
void inline sendHCISetEventMask(); | |||||
void inline sendHCIRemoteNameRequest(); | |||||
void inline sendHCIRemoteVersionInfoRequest(); | |||||
void handle_hci_command_complete(); | |||||
void handle_hci_command_status(); | |||||
void handle_hci_inquiry_result(bool fRSSI=false); | |||||
void handle_hci_extended_inquiry_result(); | |||||
void handle_hci_inquiry_complete(); | |||||
void handle_hci_incoming_connect(); | |||||
void handle_hci_connection_complete(); | |||||
void handle_hci_disconnect_complete(); | |||||
void handle_hci_authentication_complete(); | |||||
void handle_hci_remote_name_complete(); | |||||
void handle_hci_remote_version_information_complete(); | |||||
void handle_hci_pin_code_request(); | |||||
void handle_hci_link_key_notification(); | |||||
void handle_hci_link_key_request(); | |||||
void queue_next_hci_command(); | |||||
void sendl2cap_ConnectionResponse(uint16_t handle, uint8_t rxid, uint16_t dcid, uint16_t scid, uint8_t result); | |||||
void sendl2cap_ConnectionRequest(uint16_t handle, uint8_t rxid, uint16_t scid, uint16_t psm); | |||||
void sendl2cap_ConfigRequest(uint16_t handle, uint8_t rxid, uint16_t dcid); | |||||
void sendl2cap_ConfigResponse(uint16_t handle, uint8_t rxid, uint16_t scid); | |||||
void sendL2CapCommand(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00); | |||||
void process_l2cap_connection_request(uint8_t *data); | |||||
void process_l2cap_connection_response(uint8_t *data); | |||||
void process_l2cap_config_request(uint8_t *data); | |||||
void process_l2cap_config_response(uint8_t *data); | |||||
void process_l2cap_command_reject(uint8_t *data); | |||||
void process_l2cap_disconnect_request(uint8_t *data); | |||||
void setHIDProtocol(uint8_t protocol); | |||||
void handleHIDTHDRData(uint8_t *buffer); // Pass the whole buffer... | |||||
static BTHIDInput *available_bthid_drivers_list; | |||||
setup_t setup; | |||||
Pipe_t mypipes[4] __attribute__ ((aligned(32))); | |||||
Transfer_t mytransfers[7] __attribute__ ((aligned(32))); | |||||
strbuf_t mystring_bufs[2]; // 2 string buffers - one for our device - one for remote device... | |||||
uint16_t pending_control_ = 0; | |||||
uint16_t pending_control_tx_ = 0; | |||||
uint16_t rx_size_ = 0; | |||||
uint16_t rx2_size_ = 0; | |||||
uint16_t tx_size_ = 0; | |||||
Pipe_t *rxpipe_; | |||||
Pipe_t *rx2pipe_; | |||||
Pipe_t *txpipe_; | |||||
uint8_t rxbuf_[256]; // used to receive data from RX, which may come with several packets... | |||||
uint8_t rx_packet_data_remaining=0; // how much data remaining | |||||
uint8_t rx2buf_[64]; // receive buffer from Bulk end point | |||||
uint8_t txbuf_[256]; // buffer to use to send commands to bluetooth | |||||
uint8_t hciVersion; // what version of HCI do we have? | |||||
bool do_pair_device_; // Should we do a pair for a new device? | |||||
const char *pair_pincode_; // What pin code to use for the pairing | |||||
USBDriverTimer delayTimer_; | |||||
uint8_t my_bdaddr_[6]; // The bluetooth dongles Bluetooth address. | |||||
uint8_t features[8]; // remember our local features. | |||||
BTHIDInput * device_driver_ = nullptr;; | |||||
uint8_t device_bdaddr_[6];// remember devices address | |||||
uint8_t device_ps_repetion_mode_ ; // mode | |||||
uint8_t device_clock_offset_[2]; | |||||
uint32_t device_class_; // class of device. | |||||
uint16_t device_connection_handle_; // handle to connection | |||||
uint8_t remote_ver_; | |||||
uint16_t remote_man_; | |||||
uint8_t remote_subv_; | |||||
uint8_t connection_complete_ = false; // | |||||
typedef struct { | |||||
uint16_t idVendor; | |||||
uint16_t idProduct; | |||||
} product_vendor_mapping_t; | |||||
static product_vendor_mapping_t pid_vid_mapping[]; | |||||
}; | |||||
#endif | #endif |
/* USB EHCI Host for Teensy 3.6 | |||||
* Copyright 2017 Paul Stoffregen (paul@pjrc.com) | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a | |||||
* copy of this software and associated documentation files (the | |||||
* "Software"), to deal in the Software without restriction, including | |||||
* without limitation the rights to use, copy, modify, merge, publish, | |||||
* distribute, sublicense, and/or sell copies of the Software, and to | |||||
* permit persons to whom the Software is furnished to do so, subject to | |||||
* the following conditions: | |||||
* | |||||
* The above copyright notice and this permission notice shall be included | |||||
* in all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
*/ | |||||
#include <Arduino.h> | |||||
#include "USBHost_t36.h" // Read this header first for key info | |||||
void DigitizerController::init() | |||||
{ | |||||
USBHIDParser::driver_ready_for_hid_collection(this); | |||||
} | |||||
hidclaim_t DigitizerController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | |||||
{ | |||||
// only claim Desktop/Mouse | |||||
if (topusage != 0xff0d0001) return CLAIM_NO; | |||||
// only claim from one physical device | |||||
if (mydevice != NULL && dev != mydevice) return CLAIM_NO; | |||||
mydevice = dev; | |||||
collections_claimed++; | |||||
return CLAIM_REPORT; | |||||
} | |||||
void DigitizerController::disconnect_collection(Device_t *dev) | |||||
{ | |||||
if (--collections_claimed == 0) { | |||||
mydevice = NULL; | |||||
} | |||||
} | |||||
void DigitizerController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) | |||||
{ | |||||
// TODO: check if absolute coordinates | |||||
hid_input_begin_ = true; | |||||
} | |||||
void DigitizerController::hid_input_data(uint32_t usage, int32_t value) | |||||
{ | |||||
USBHDBGSerial.printf("Digitizer: usage=%X, value=%d\n", usage, value); | |||||
uint32_t usage_page = usage >> 16; | |||||
usage &= 0xFFFF; | |||||
USBHDBGSerial.printf("Digitizer: &usage=%X, usage_page=%x\n", usage, usage_page); | |||||
// This is Mikes version... | |||||
if (usage_page == 0xff00 && usage >= 100 && usage <= 0x108) { | |||||
switch (usage) { | |||||
case 0x102: | |||||
mouseX = value; | |||||
break; | |||||
case 0x103: | |||||
mouseY = value; | |||||
break; | |||||
case 0x32: // Apple uses this for horizontal scroll | |||||
wheelH = value; | |||||
break; | |||||
case 0x38: | |||||
wheel = value; | |||||
break; | |||||
} | |||||
digiAxes[usage & 0xf] = value; | |||||
} | |||||
if (usage_page == 0xff0D) { | |||||
if (usage >= 0 && usage < 0x138) { //at least to start | |||||
switch (usage) { | |||||
case 0x130: | |||||
mouseX = value; | |||||
break; | |||||
case 0x131: | |||||
mouseY = value; | |||||
break; | |||||
case 0x132: // Apple uses this for horizontal scroll | |||||
wheelH = value; | |||||
break; | |||||
case 0x138: | |||||
wheel = value; | |||||
break; | |||||
case 0x30: digiAxes[0] = value; break; | |||||
case 0x32: digiAxes[1] = value; break; | |||||
case 0x36: digiAxes[2] = value; break; | |||||
case 0x42: digiAxes[3] = value; break; | |||||
case 0x44: digiAxes[4] = value; break; | |||||
case 0x5A: digiAxes[5] = value; break; | |||||
case 0x5B: digiAxes[6] = value; break; | |||||
case 0x5C: digiAxes[7] = value; break; | |||||
case 0x77: digiAxes[8] = value; break; | |||||
} | |||||
//digiAxes[usage & 0xf] = value; | |||||
} else if (usage >= 0x910 && usage <= 0x91f) { | |||||
if (value == 0) { | |||||
buttons &= ~(1 << (usage - 0x910)); | |||||
} else { | |||||
buttons |= (1 << (usage - 0x910)); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
void DigitizerController::hid_input_end() | |||||
{ | |||||
if (hid_input_begin_) { | |||||
digitizerEvent = true; | |||||
hid_input_begin_ = false; | |||||
} | |||||
} | |||||
void DigitizerController::digitizerDataClear() { | |||||
digitizerEvent = false; | |||||
buttons = 0; | |||||
mouseX = 0; | |||||
mouseY = 0; | |||||
wheel = 0; | |||||
wheelH = 0; | |||||
} |
return; | return; | ||||
} | } | ||||
uint32_t remain = USBHS_GPTIMER1CTL & 0xFFFFFF; | uint32_t remain = USBHS_GPTIMER1CTL & 0xFFFFFF; | ||||
//Serial.print("remain = "); | |||||
//Serial.println(remain); | |||||
//USBHDBGSerial.print("remain = "); | |||||
//USBHDBGSerial.println(remain); | |||||
if (microseconds < remain) { | if (microseconds < remain) { | ||||
// this timer event is before any on the schedule | // this timer event is before any on the schedule | ||||
__disable_irq(); | __disable_irq(); | ||||
if (transfer == data) break; | if (transfer == data) break; | ||||
transfer = next; | transfer = next; | ||||
} | } | ||||
return false; | |||||
} | |||||
return false; | |||||
} | |||||
data->qtd.next = (uint32_t)next; | data->qtd.next = (uint32_t)next; | ||||
data = next; | data = next; | ||||
} | } |
// Simple test of USB Host Mouse/Keyboard | |||||
// | |||||
// This example is in the public domain | |||||
#include "USBHost_t36.h" | |||||
//#include "debug_tt.h" | |||||
USBHost myusb; | |||||
USBHub hub1(myusb); | |||||
USBHub hub2(myusb); | |||||
USBHIDParser hid1(myusb); | |||||
USBHIDParser hid2(myusb); | |||||
USBHIDParser hid3(myusb); | |||||
USBHIDParser hid4(myusb); | |||||
USBHIDParser hid5(myusb); | |||||
JoystickController joystick1(myusb); | |||||
//BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
BluetoothController bluet(myusb); // version assumes it already was paired | |||||
int user_axis[64]; | |||||
uint32_t buttons_prev = 0; | |||||
uint32_t buttons; | |||||
RawHIDController rawhid1(myusb); | |||||
RawHIDController rawhid2(myusb, 0xffc90004); | |||||
USBDriver *drivers[] = {&hub1, &hub2, &joystick1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | |||||
const char * driver_names[CNT_DEVICES] = {"Hub1", "Hub2", "JOY1D", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
bool driver_active[CNT_DEVICES] = {false, false, false, false}; | |||||
// Lets also look at HID Input devices | |||||
USBHIDInput *hiddrivers[] = {&joystick1, &rawhid1, &rawhid2}; | |||||
#define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | |||||
const char * hid_driver_names[CNT_DEVICES] = {"Joystick1", "RawHid1", "RawHid2"}; | |||||
bool hid_driver_active[CNT_DEVICES] = {false, false, false}; | |||||
BTHIDInput *bthiddrivers[] = {&joystick1}; | |||||
#define CNT_BTHIDDEVICES (sizeof(bthiddrivers)/sizeof(bthiddrivers[0])) | |||||
const char * bthid_driver_names[CNT_HIDDEVICES] = {"joystick"}; | |||||
bool bthid_driver_active[CNT_HIDDEVICES] = {false}; | |||||
bool show_changed_only = false; | |||||
bool show_raw_data = false; | |||||
bool show_changed_data = false; | |||||
uint8_t joystick_left_trigger_value = 0; | |||||
uint8_t joystick_right_trigger_value = 0; | |||||
uint64_t joystick_full_notify_mask = (uint64_t) - 1; | |||||
int psAxis[64]; | |||||
bool first_joystick_message = true; | |||||
uint8_t last_bdaddr[6] = {0, 0, 0, 0, 0, 0}; | |||||
// ps3 motion on USB does not do much, but see if we can pair it and maybe change | |||||
// color of bulb... | |||||
uint32_t PS3_MOTION_timer = 0; | |||||
uint8_t PS3_MOTION_tried_to_pair_state = 0; | |||||
#define PS3_MOTION_PERIOD 2500 // not sure yet what would be good period for this.. | |||||
//============================================================================= | |||||
// Setup | |||||
//============================================================================= | |||||
void setup() | |||||
{ | |||||
Serial1.begin(2000000); | |||||
while (!Serial) ; // wait for Arduino Serial Monitor | |||||
Serial.println("\n\nUSB Host Testing"); | |||||
Serial.println(sizeof(USBHub), DEC); | |||||
myusb.begin(); | |||||
delay(2000); | |||||
rawhid1.attachReceive(OnReceiveHidData); | |||||
rawhid2.attachReceive(OnReceiveHidData); | |||||
} | |||||
//============================================================================= | |||||
// Loop | |||||
//============================================================================= | |||||
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 ***"); | |||||
} | |||||
} | |||||
} | |||||
// check to see if the device list has changed: | |||||
UpdateActiveDeviceInfo(); | |||||
processPS3MotionTimer(); | |||||
if (joystick1.available()) { | |||||
if (first_joystick_message) { | |||||
Serial.printf("*** First Joystick message %x:%x ***\n", | |||||
joystick1.idVendor(), joystick1.idProduct()); | |||||
first_joystick_message = false; | |||||
const uint8_t *psz = joystick1.manufacturer(); | |||||
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||||
psz = joystick1.product(); | |||||
if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||||
psz = joystick1.serialNumber(); | |||||
if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||||
// lets try to reduce number of fields that update | |||||
joystick1.axisChangeNotifyMask(0xFFFFFl); | |||||
} | |||||
for (uint8_t i = 0; i < 64; i++) { | |||||
psAxis[i] = joystick1.getAxis(i); | |||||
} | |||||
switch (joystick1.joystickType()) { | |||||
case JoystickController::UNKNOWN: | |||||
case JoystickController::PS4: | |||||
displayPS4Data(); | |||||
break; | |||||
case JoystickController::PS3: | |||||
displayPS3Data(); | |||||
break; | |||||
case JoystickController::PS3_MOTION: | |||||
displayPS3MotionData(); | |||||
break; | |||||
case JoystickController::XBOXONE: | |||||
case JoystickController::XBOX360: | |||||
displayXBoxData(); | |||||
break; | |||||
default: | |||||
displayRawData(); | |||||
break; | |||||
} | |||||
//for (uint8_t i = 0; i < 24; i++) { | |||||
// Serial.printf(" %d:%d", i, psAxis[i]); | |||||
//} | |||||
//Serial.println(); | |||||
delay(100); | |||||
joystick1.joystickDataClear(); | |||||
} | |||||
// See if we have some RAW data | |||||
if (rawhid1) { | |||||
int ch; | |||||
uint8_t buffer[64]; | |||||
uint8_t count_chars = 0; | |||||
memset(buffer, 0, sizeof(buffer)); | |||||
if (Serial.available()) { | |||||
while (((ch = Serial.read()) != -1) && (count_chars < sizeof(buffer))) { | |||||
buffer[count_chars++] = ch; | |||||
} | |||||
rawhid1.sendPacket(buffer); | |||||
} | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// UpdateActiveDeviceInfo | |||||
//============================================================================= | |||||
void UpdateActiveDeviceInfo() { | |||||
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); | |||||
if (drivers[i] == &bluet) { | |||||
const uint8_t *bdaddr = bluet.myBDAddr(); | |||||
// remember it... | |||||
Serial.printf(" BDADDR: %x:%x:%x:%x:%x:%x\n", bdaddr[0], bdaddr[1], bdaddr[2], bdaddr[3], bdaddr[4], bdaddr[5]); | |||||
for (uint8_t i = 0; i < 6; i++) last_bdaddr[i] = bdaddr[i]; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
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); | |||||
// See if this is our joystick object... | |||||
if (hiddrivers[i] == &joystick1) { | |||||
Serial.printf(" Joystick type: %d\n", joystick1.joystickType()); | |||||
if (joystick1.joystickType() == JoystickController::PS3_MOTION) { | |||||
Serial.println(" PS3 Motion detected"); | |||||
PS3_MOTION_timer = millis(); // set time for last event | |||||
PS3_MOTION_tried_to_pair_state = 0; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
// Then Bluetooth devices | |||||
for (uint8_t i = 0; i < CNT_BTHIDDEVICES; i++) { | |||||
if (*bthiddrivers[i] != bthid_driver_active[i]) { | |||||
if (bthid_driver_active[i]) { | |||||
Serial.printf("*** BTHID Device %s - disconnected ***\n", hid_driver_names[i]); | |||||
bthid_driver_active[i] = false; | |||||
} else { | |||||
Serial.printf("*** BTHID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||||
bthid_driver_active[i] = true; | |||||
const uint8_t *psz = bthiddrivers[i]->manufacturer(); | |||||
if (psz && *psz) Serial.printf(" manufacturer: %s\n", psz); | |||||
psz = bthiddrivers[i]->product(); | |||||
if (psz && *psz) Serial.printf(" product: %s\n", psz); | |||||
psz = bthiddrivers[i]->serialNumber(); | |||||
if (psz && *psz) Serial.printf(" Serial: %s\n", psz); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// displayPS4Data | |||||
//============================================================================= | |||||
void displayPS4Data() | |||||
{ | |||||
buttons = joystick1.getButtons(); | |||||
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[0], psAxis[1], psAxis[2], psAxis[5]); | |||||
Serial.printf("L-Trig: %d, R-Trig: %d\r\n", psAxis[3], psAxis[4]); | |||||
Serial.printf("Buttons: %x\r\n", buttons); | |||||
Serial.printf("Battery Status: %d\n", ((psAxis[30] & ((1 << 4) - 1))*10)); | |||||
printAngles(); | |||||
Serial.println(); | |||||
uint8_t ltv; | |||||
uint8_t rtv; | |||||
ltv = psAxis[3]; | |||||
rtv = psAxis[4]; | |||||
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | |||||
joystick_left_trigger_value = ltv; | |||||
joystick_right_trigger_value = rtv; | |||||
Serial.printf("Rumbling: %d, %d\r\n", ltv, rtv); | |||||
joystick1.setRumble(ltv, rtv); | |||||
} | |||||
if (buttons != buttons_prev) { | |||||
uint8_t lr = 0; | |||||
uint8_t lg = 0; | |||||
uint8_t lb = 0; | |||||
if(buttons == 0x10008){//Srq | |||||
lr = 0xff; | |||||
} | |||||
if(buttons == 0x40008){//Circ | |||||
lg = 0xff; | |||||
} | |||||
if(buttons == 0x80008){//Tri | |||||
lb = 0xff; | |||||
} | |||||
Serial.print(buttons,HEX); Serial.print(", "); | |||||
Serial.print(lr); Serial.print(", "); | |||||
Serial.print(lg); Serial.print(", "); | |||||
Serial.println(lb); | |||||
joystick1.setLEDs(lr, lg, lb); | |||||
buttons_prev = buttons; | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// displayPS3Data | |||||
//============================================================================= | |||||
void displayPS3Data() | |||||
{ | |||||
buttons = joystick1.getButtons(); | |||||
//buttons = psAxis[2] | ((uint16_t)psAxis[3] << 8); | |||||
// Use L3 (Left joystick button) to toggle Show Raw or not... | |||||
if ((buttons & 0x02) && !(buttons_prev & 0x02)) show_raw_data = !show_raw_data; | |||||
if ((buttons & 0x04) && !(buttons_prev & 0x04)) show_changed_data = !show_changed_data; | |||||
// See about maybe pair... | |||||
if ((buttons & 0x10000) && !(buttons_prev & 0x10000) && (buttons & 0x0C01)) { | |||||
// PS button just pressed and select button pressed act like PS4 share like... | |||||
// Note: you can use either R1 or L1 with the PS button, to work with Sony Move Navigation... | |||||
Serial.print("\nPS3 Pairing Request"); | |||||
if (!last_bdaddr[0] && !last_bdaddr[1] && !last_bdaddr[2] && !last_bdaddr[3] && !last_bdaddr[4] && !last_bdaddr[5]) { | |||||
Serial.println(" - failed - no Bluetooth adapter has been plugged in"); | |||||
} else if (!hiddrivers[0]) { // Kludge see if we are connected as HID? | |||||
Serial.println(" - failed - PS3 device not plugged into USB"); | |||||
} else { | |||||
Serial.printf(" - Attempt pair to: %x:%x:%x:%x:%x:%x\n", last_bdaddr[0], last_bdaddr[1], last_bdaddr[2], last_bdaddr[3], last_bdaddr[4], last_bdaddr[5]); | |||||
if (! joystick1.PS3Pair(last_bdaddr)) { | |||||
Serial.println(" Pairing call Failed"); | |||||
} else { | |||||
Serial.println(" Pairing complete (I hope), make sure Bluetooth adapter is plugged in and try PS3 without USB"); | |||||
} | |||||
} | |||||
} | |||||
if (show_raw_data) { | |||||
displayRawData(); | |||||
} else { | |||||
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[0], psAxis[1], psAxis[2], psAxis[5]); | |||||
Serial.printf("L-Trig: %d, R-Trig: %d\r\n", psAxis[3], psAxis[4]); | |||||
Serial.printf("Buttons: %x\r\n", buttons); | |||||
} | |||||
uint8_t ltv; | |||||
uint8_t rtv; | |||||
ltv = psAxis[3]; | |||||
rtv = psAxis[4]; | |||||
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | |||||
joystick_left_trigger_value = ltv; | |||||
joystick_right_trigger_value = rtv; | |||||
Serial.printf("Rumbling: %d, %d\r\n", ltv, rtv); | |||||
joystick1.setRumble(ltv, rtv); | |||||
} | |||||
if (buttons != buttons_prev) { | |||||
uint8_t leds = 0; | |||||
if (buttons & 0x8000) leds = 1; //Srq | |||||
if (buttons & 0x2000) leds = 2; //Cir | |||||
if (buttons & 0x1000) leds = 3; //Tri | |||||
//Cross = 2 | |||||
joystick1.setLEDs(leds); | |||||
buttons_prev = buttons; | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// displayPS3MotionData | |||||
//============================================================================= | |||||
void displayPS3MotionData() | |||||
{ | |||||
buttons = joystick1.getButtons(); | |||||
// Hard to know what is best here. for now just copy raw data over... | |||||
// will do this for now... Format of thought to be data. | |||||
// data[1-3] Buttons (mentioned 4 as well but appears to be counter | |||||
// axis[0-1] data[5] Trigger, Previous trigger value | |||||
// 2-5 Unknown probably place holders for Axis like data for other PS3 | |||||
// 6 - Time stamp | |||||
// 7 - Battery | |||||
// 8-19 - Accel: XL, XH, YL, YH, ZL, ZH, XL2, XH2, YL2, YH2, ZL2, ZH2 | |||||
// 20-31 - Gyro: Xl,Xh,Yl,Yh,Zl,Zh,Xl2,Xh2,Yl2,Yh2,Zl2,Zh2 | |||||
// 32 - Temp High | |||||
// 33 - Temp Low (4 bits) Maybe Magneto x High on other?? | |||||
// Use Select button to choose raw or not | |||||
if ((buttons & 0x01) && !(buttons_prev & 0x01)) show_raw_data = !show_raw_data; | |||||
if ((buttons & 0x04) && !(buttons_prev & 0x04)) show_changed_data = !show_changed_data; | |||||
if (show_raw_data) { | |||||
displayRawData(); | |||||
} else { | |||||
uint64_t changed_mask = joystick1.axisChangedMask(); | |||||
Serial.printf("Changed: %08x Buttons: %x: Trig: %d\r\n", (uint32_t)changed_mask, buttons, psAxis[0]); | |||||
Serial.printf("Battery Status: %d\n", psAxis[7]); | |||||
printPS3MotionAngles(); | |||||
Serial.println(); | |||||
} | |||||
uint8_t ltv = psAxis[0]; | |||||
if ((ltv != joystick_left_trigger_value) ) { | |||||
joystick_left_trigger_value = ltv; | |||||
Serial.printf("Rumbling: %d\r\n", ltv); | |||||
joystick1.setRumble(ltv, 0); | |||||
} | |||||
if (buttons != buttons_prev) { | |||||
uint8_t ledsR = (buttons & 0x8000)? 0xff : 0; //Srq | |||||
uint8_t ledsG = (buttons & 0x2000)? 0xff : 0; //Cir | |||||
uint8_t ledsB = (buttons & 0x1000)? 0xff : 0; //Tri | |||||
Serial.printf("Set Leds %x %x %x\r\n", ledsR, ledsG, ledsB ); | |||||
joystick1.setLEDs(ledsR, ledsG, ledsB); | |||||
buttons_prev = buttons; | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// displayXBoxData | |||||
//============================================================================= | |||||
void displayXBoxData() | |||||
{ | |||||
buttons = joystick1.getButtons(); | |||||
// Use L3 (Left joystick button) to toggle Show Raw or not... | |||||
if ((buttons & 0x4000) && !(buttons_prev & 0x4000)) show_raw_data = !show_raw_data; | |||||
if ((buttons & 0x8000) && !(buttons_prev & 0x8000)) show_changed_data = !show_changed_data; | |||||
if (show_raw_data) { | |||||
displayRawData(); | |||||
} else { | |||||
Serial.printf("LX: %d, LY: %d, RX: %d, RY: %d \r\n", psAxis[0], psAxis[1], psAxis[2], psAxis[5]); | |||||
Serial.printf("L-Trig: %d, R-Trig: %d\r\n", psAxis[3], psAxis[4]); | |||||
Serial.printf("Buttons: %x\r\n", buttons); | |||||
} | |||||
uint8_t ltv; | |||||
uint8_t rtv; | |||||
ltv = psAxis[3]; | |||||
rtv = psAxis[4]; | |||||
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | |||||
joystick_left_trigger_value = ltv; | |||||
joystick_right_trigger_value = rtv; | |||||
Serial.printf("Rumbling: %d, %d\r\n", ltv, rtv); | |||||
joystick1.setRumble(ltv, rtv); | |||||
} | |||||
if (buttons != buttons_prev) { | |||||
uint8_t leds = 0; | |||||
if (buttons & 0x8000) leds = 1; //Srq | |||||
if (buttons & 0x2000) leds = 2; //Cir | |||||
if (buttons & 0x1000) leds = 3; //Tri | |||||
//Cross = 2 | |||||
joystick1.setLEDs(leds); | |||||
buttons_prev = buttons; | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// displayRawData | |||||
//============================================================================= | |||||
void displayRawData() { | |||||
uint64_t axis_mask = joystick1.axisMask(); | |||||
uint64_t changed_mask = joystick1.axisChangedMask(); | |||||
buttons = joystick1.getButtons(); | |||||
if (!changed_mask && (buttons == buttons_prev)) return; | |||||
if (show_changed_data) { | |||||
if (!changed_mask) return; | |||||
changed_mask &= 0xfffffffffL; // try reducing which ones show... | |||||
Serial.printf("%0x - ", joystick1.getButtons()); | |||||
for (uint16_t index = 0; changed_mask; index++) { | |||||
if (changed_mask & 1) { | |||||
Serial.printf("%d:%02x ", index, psAxis[index]); | |||||
} | |||||
changed_mask >>= 1; | |||||
} | |||||
} else { | |||||
axis_mask &= 0xffffff; | |||||
Serial.printf("%06x%06x: %06x - ", (uint32_t)(changed_mask >> 32), (uint32_t)(changed_mask & 0xffffffff), joystick1.getButtons()); | |||||
for (uint16_t index = 0; axis_mask; index++) { | |||||
Serial.printf("%02x ", psAxis[index]); | |||||
axis_mask >>= 1; | |||||
} | |||||
} | |||||
Serial.println(); | |||||
buttons_prev = buttons; | |||||
} | |||||
//============================================================================= | |||||
// OnReceiveHidData | |||||
//============================================================================= | |||||
bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||||
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy | |||||
// to output to Serial. while still having Raw Hid... | |||||
if (usage == 0xffc90004) { | |||||
// Lets trim off trailing null characters. | |||||
while ((len > 0) && (data[len - 1] == 0)) { | |||||
len--; | |||||
} | |||||
if (len) { | |||||
Serial.print("RawHid Serial: "); | |||||
Serial.write(data, len); | |||||
} | |||||
} else { | |||||
Serial.print("RawHID data: "); | |||||
Serial.println(usage, HEX); | |||||
while (len) { | |||||
uint8_t cb = (len > 16) ? 16 : len; | |||||
const uint8_t *p = data; | |||||
uint8_t i; | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.printf("%02x ", *p++); | |||||
} | |||||
Serial.print(": "); | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.write(((*data >= ' ') && (*data <= '~')) ? *data : '.'); | |||||
data++; | |||||
} | |||||
len -= cb; | |||||
Serial.println(); | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
//============================================================================= | |||||
// processPS3MotionTimer | |||||
//============================================================================= | |||||
static const uint32_t PS3_MOTION_colors[] = {0, 0xff, 0xff00, 0xff0000, 0xffff, 0xff00ff, 0xffff00, 0xffffff}; | |||||
uint8_t PS3_MOTION_colors_index = 0; | |||||
void processPS3MotionTimer() { | |||||
// See if we have a PS3_MOTION connected and we have run for a certain amount of time | |||||
if (PS3_MOTION_timer && ((millis()-PS3_MOTION_timer) >= PS3_MOTION_PERIOD)) { | |||||
Serial.println("PS3 Motion Timer"); Serial.flush(); | |||||
if (joystick1) { | |||||
PS3_MOTION_timer = millis(); // joystick not there any more... | |||||
// We will first try to set feedback color for the PS3, maybe alternate colors | |||||
if (++PS3_MOTION_colors_index >= sizeof(PS3_MOTION_colors)/sizeof(PS3_MOTION_colors[0])) PS3_MOTION_colors_index = 0; | |||||
joystick1.setLEDs(PS3_MOTION_colors[PS3_MOTION_colors_index]); | |||||
// Next see if we can try to pair. | |||||
if (PS3_MOTION_tried_to_pair_state == 0) { | |||||
Serial.println("PS3_MOTION Connected"); | |||||
if (!last_bdaddr[0] && !last_bdaddr[1] && !last_bdaddr[2] && !last_bdaddr[3] && !last_bdaddr[4] && !last_bdaddr[5]) { | |||||
Serial.println(" - No Bluetooth adapter has been plugged in - so will not try to pair"); | |||||
PS3_MOTION_tried_to_pair_state = 1; | |||||
} | |||||
} | |||||
if ((PS3_MOTION_tried_to_pair_state < 2) && | |||||
(last_bdaddr[0] || last_bdaddr[1] || last_bdaddr[2] || last_bdaddr[3] || last_bdaddr[4] || last_bdaddr[5])) { | |||||
Serial.println(" - Bluetooth device detected, will try to pair"); | |||||
// Lets try to pair | |||||
if (! joystick1.PS3Pair(last_bdaddr)) { | |||||
Serial.println(" - Pairing call Failed"); | |||||
} else { | |||||
Serial.println(" - Pairing complete (I hope), make sure Bluetooth adapter is plugged in and try PS3 without USB"); | |||||
} | |||||
PS3_MOTION_tried_to_pair_state = 2; // don't try again... | |||||
} | |||||
} else { | |||||
Serial.println("PS3 Motion Joystick no longer detected"); | |||||
PS3_MOTION_timer = 0; // joystick not there any more... | |||||
} | |||||
} | |||||
} |
float pitch, roll; | |||||
float gx, gy, gz; | |||||
int16_t mx, my, mz; | |||||
uint16_t xc, yc; | |||||
uint8_t isTouch; | |||||
float ax, ay, az; | |||||
int16_t xc_old, yc_old; | |||||
/* Decode 12-bit signed value (assuming two's complement) */ | |||||
#define TWELVE_BIT_SIGNED(x) (((x) & 0x800)?(-(((~(x)) & 0xFFF) + 1)):(x)) | |||||
#define Model_ZCM1 1 | |||||
//#define Model_ZCM2 0 | |||||
void printAngles(){ | |||||
//test function calls | |||||
float gx, gy, gz; | |||||
getAccel(ax, ay, az); | |||||
Serial.printf("Accel-g's: %f, %f, %f\n", ax, ay, az); | |||||
getGyro(gx, gy, gz); | |||||
Serial.printf("Gyro-deg/sec: %f, %f, %f\n", gx, gy, gz); | |||||
getAngles(pitch, roll); | |||||
Serial.printf("Pitch/Roll: %f, %f\n", pitch, roll); | |||||
getCoords(xc, yc, isTouch); | |||||
} | |||||
void getCoords(uint16_t &xc, uint16_t &yc, uint8_t &isTouch){ | |||||
//uint8_t finger = 0; //only getting finger 1 | |||||
// Trackpad touch 1: id, active, x, y | |||||
xc = ((psAxis[37] & 0x0f) << 8) | psAxis[36]; | |||||
yc = psAxis[38] << 4 | ((psAxis[37] & 0xf0) >> 4), | |||||
isTouch = psAxis[35] >> 7; | |||||
if(xc != xc_old || yc != yc_old){ | |||||
Serial.printf("Touch: %d, %d, %d, %d\n", psAxis[33], isTouch, xc, yc); | |||||
xc_old = xc; | |||||
yc_old = yc; | |||||
} | |||||
} | |||||
void getAccel( float &ax, float &ay, float &az){ | |||||
int accelx = (int16_t)(psAxis[20]<<8) | psAxis[19]; | |||||
int accelz = (int16_t)(psAxis[22]<<8) | psAxis[21]; | |||||
int accely = (int16_t)(psAxis[24]<<8) | psAxis[23]; | |||||
ax = (float) accelx/8192; | |||||
ay = (float) accely/8192; | |||||
az = (float) accelz/8192; | |||||
} | |||||
void getAngles(float &p, float &r){ | |||||
getAccel( ax, ay, az); | |||||
p = (atan2f(ay, az) + PI) * RAD_TO_DEG; | |||||
r = (atan2f(ax, az) + PI) * RAD_TO_DEG; | |||||
} | |||||
void getGyro(float &gx, float &gy, float &gz){ | |||||
int gyroy = (int16_t)(psAxis[14]<<8) | psAxis[13]; | |||||
int gyroz = (int16_t)(psAxis[16]<<8) | psAxis[15]; | |||||
int gyrox = (int16_t)(psAxis[18]<<8) | psAxis[17]; | |||||
gx = (float) gyrox * RAD_TO_DEG/1024; | |||||
gy = (float) gyroy * RAD_TO_DEG/1024; | |||||
gz = (float) gyroz * RAD_TO_DEG/1024; | |||||
} | |||||
void printPS3MotionAngles(){ | |||||
//test function calls | |||||
float gx, gy, gz; | |||||
getPS3MotionAccel(ax, ay, az); | |||||
Serial.printf("Accel-g's: %f, %f, %f\n", ax, ay, az); | |||||
getPS3MotionGyro(gx, gy, gz); | |||||
Serial.printf("Gyro-deg/sec: %f, %f, %f\n", gx, gy, gz); | |||||
getPS3MotionMag(mx, my, mz); | |||||
Serial.printf("Mag: %d, %d, %d\n", mx, my, mz); | |||||
getPS3MotionAngles(pitch, roll); | |||||
Serial.printf("Pitch/Roll: %f, %f\n", pitch, roll); | |||||
} | |||||
void getPS3MotionAccel( float &ax, float &ay, float &az){ | |||||
int accelx = (psAxis[15]<<8 | psAxis[14]); | |||||
int accely = (psAxis[17]<<8 | psAxis[16]); | |||||
int accelz = (psAxis[19]<<8 | psAxis[18]); | |||||
#if defined(Model_ZCM1) | |||||
accelx = accelx-0x8000; | |||||
accely = accely-0x8000; | |||||
accelz = accelz-0x8000; | |||||
#elif defined(Model_ZCM2) | |||||
accelx = (accelx & 0x8000) ? (-(~accelx & 0xFFFF) + 1) : accelx; | |||||
accely = (accely & 0x8000) ? (-(~accely & 0xFFFF) + 1) : accely; | |||||
accelz = (accelz & 0x8000) ? (-(~accelz & 0xFFFF) + 1) : accelz; | |||||
#endif | |||||
ax = (float) accelx/4096; | |||||
ay = (float) accely/4096; | |||||
az = (float) accelz/4096; | |||||
} | |||||
void getPS3MotionAngles(float &p, float &r){ | |||||
getAccel( ax, ay, az); | |||||
p = (atan2f(ay, az) + PI) * RAD_TO_DEG; | |||||
r = (atan2f(ax, az) + PI) * RAD_TO_DEG; | |||||
} | |||||
void getPS3MotionGyro(float &gx, float &gy, float &gz){ | |||||
int gyrox = (psAxis[21]<<8 | psAxis[20]); | |||||
int gyroy = (psAxis[23]<<8 | psAxis[22]); | |||||
int gyroz = (psAxis[25]<<8 | psAxis[24]); | |||||
#if defined(Model_ZCM1) | |||||
gyrox = gyrox-0x8000; | |||||
gyroy = gyroy-0x8000; | |||||
gyroz = gyroz-0x8000; | |||||
#elif defined(Model_ZCM2) | |||||
gyrox = (gyrox & 0x8000) ? (-(~gyrox & 0xFFFF) + 1) : gyrox; | |||||
gyroy = (gyroy & 0x8000) ? (-(~gyroy & 0xFFFF) + 1) : gyroy; | |||||
gyroz = (gyroz & 0x8000) ? (-(~gyroz & 0xFFFF) + 1) : gyroz; | |||||
#endif | |||||
gx = (float) gyrox * RAD_TO_DEG/1024; | |||||
gy = (float) gyroy * RAD_TO_DEG/1024; | |||||
gz = (float) gyroz * RAD_TO_DEG/1024; | |||||
} | |||||
void getPS3MotionMag(int16_t &mx, int16_t &my, int16_t &mz){ | |||||
#if defined(Model_ZCM1) | |||||
mx = TWELVE_BIT_SIGNED(((psAxis[33] & 0x0F) << 8) | | |||||
psAxis[34]); | |||||
my = TWELVE_BIT_SIGNED((psAxis[35] << 4) | | |||||
(psAxis[36] & 0xF0) >> 4); | |||||
mz = TWELVE_BIT_SIGNED(((psAxis[36] & 0x0F) << 8) | | |||||
psAxis[37]); | |||||
#elif defined(Model_ZCM2) | |||||
// NOTE: This model does not have magnetometers | |||||
Serial.println("Not avail for ZCM2!"); | |||||
#endif | |||||
} |
// Simple test of USB Host Mouse/Keyboard | |||||
// | |||||
// This example is in the public domain | |||||
#include "USBHost_t36.h" | |||||
USBHost myusb; | |||||
USBHub hub1(myusb); | |||||
USBHub hub2(myusb); | |||||
KeyboardController keyboard1(myusb); | |||||
//KeyboardController keyboard2(myusb); | |||||
USBHIDParser hid1(myusb); | |||||
USBHIDParser hid2(myusb); | |||||
USBHIDParser hid3(myusb); | |||||
USBHIDParser hid4(myusb); | |||||
USBHIDParser hid5(myusb); | |||||
//MouseController mouse1(myusb); | |||||
//JoystickController joystick1(myusb); | |||||
BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
//BluetoothController bluet(myusb); // version assumes it already was paired | |||||
int user_axis[64]; | |||||
uint32_t buttons_prev = 0; | |||||
RawHIDController rawhid1(myusb); | |||||
RawHIDController rawhid2(myusb, 0xffc90004); | |||||
//USBDriver *drivers[] = {&hub1, &hub2,&keyboard1, &keyboard2, &joystick1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
USBDriver *drivers[] = {&hub1, &hub2, &keyboard1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | |||||
//const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "KB2", "JOY1D", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
bool driver_active[CNT_DEVICES] = {false, false, false, false}; | |||||
// Lets also look at HID Input devices | |||||
//USBHIDInput *hiddrivers[] = {&mouse1, &joystick1, &rawhid1, &rawhid2}; | |||||
USBHIDInput *hiddrivers[] = {&rawhid1, &rawhid2}; | |||||
#define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | |||||
//const char * hid_driver_names[CNT_DEVICES] = {"Mouse1","Joystick1", "RawHid1", "RawHid2"}; | |||||
const char * hid_driver_names[CNT_DEVICES] = {"RawHid1", "RawHid2"}; | |||||
bool hid_driver_active[CNT_DEVICES] = {false, 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() | |||||
{ | |||||
while (!Serial) ; // wait for Arduino Serial Monitor | |||||
Serial.println("\n\nUSB Host Testing"); | |||||
Serial.println(sizeof(USBHub), DEC); | |||||
myusb.begin(); | |||||
keyboard1.attachPress(OnPress); | |||||
//keyboard2.attachPress(OnPress); | |||||
keyboard1.attachExtrasPress(OnHIDExtrasPress); | |||||
keyboard1.attachExtrasRelease(OnHIDExtrasRelease); | |||||
//keyboard2.attachExtrasPress(OnHIDExtrasPress); | |||||
//keyboard2.attachExtrasRelease(OnHIDExtrasRelease); | |||||
rawhid1.attachReceive(OnReceiveHidData); | |||||
rawhid2.attachReceive(OnReceiveHidData); | |||||
} | |||||
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]) { | |||||
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); | |||||
} | |||||
} | |||||
} | |||||
/* | |||||
if(mouse1.available()) { | |||||
Serial.print("Mouse: buttons = "); | |||||
Serial.print(mouse1.getButtons()); | |||||
Serial.print(", mouseX = "); | |||||
Serial.print(mouse1.getMouseX()); | |||||
Serial.print(", mouseY = "); | |||||
Serial.print(mouse1.getMouseY()); | |||||
Serial.print(", wheel = "); | |||||
Serial.print(mouse1.getWheel()); | |||||
Serial.print(", wheelH = "); | |||||
Serial.print(mouse1.getWheelH()); | |||||
Serial.println(); | |||||
mouse1.mouseDataClear(); | |||||
} | |||||
if (joystick1.available()) { | |||||
uint64_t axis_mask = joystick1.axisMask(); | |||||
uint64_t axis_changed_mask = joystick1.axisChangedMask(); | |||||
Serial.print("Joystick: buttons = "); | |||||
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: | |||||
case JoystickController::XBOX360: | |||||
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(); | |||||
} | |||||
*/ | |||||
// See if we have some RAW data | |||||
if (rawhid1) { | |||||
int ch; | |||||
uint8_t buffer[64]; | |||||
uint8_t count_chars = 0; | |||||
memset(buffer, 0, sizeof(buffer)); | |||||
if (Serial.available()) { | |||||
while (((ch = Serial.read()) != -1) && (count_chars < sizeof(buffer))) { | |||||
buffer[count_chars++] = ch; | |||||
} | |||||
rawhid1.sendPacket(buffer); | |||||
} | |||||
} | |||||
} | |||||
void OnPress(int key) | |||||
{ | |||||
Serial.print("key '"); | |||||
switch (key) { | |||||
case KEYD_UP : Serial.print("UP"); break; | |||||
case KEYD_DOWN : Serial.print("DN"); break; | |||||
case KEYD_LEFT : Serial.print("LEFT"); break; | |||||
case KEYD_RIGHT : Serial.print("RIGHT"); break; | |||||
case KEYD_INSERT : Serial.print("Ins"); break; | |||||
case KEYD_DELETE : Serial.print("Del"); break; | |||||
case KEYD_PAGE_UP : Serial.print("PUP"); break; | |||||
case KEYD_PAGE_DOWN: Serial.print("PDN"); break; | |||||
case KEYD_HOME : Serial.print("HOME"); break; | |||||
case KEYD_END : Serial.print("END"); break; | |||||
case KEYD_F1 : Serial.print("F1"); break; | |||||
case KEYD_F2 : Serial.print("F2"); break; | |||||
case KEYD_F3 : Serial.print("F3"); break; | |||||
case KEYD_F4 : Serial.print("F4"); break; | |||||
case KEYD_F5 : Serial.print("F5"); break; | |||||
case KEYD_F6 : Serial.print("F6"); break; | |||||
case KEYD_F7 : Serial.print("F7"); break; | |||||
case KEYD_F8 : Serial.print("F8"); break; | |||||
case KEYD_F9 : Serial.print("F9"); break; | |||||
case KEYD_F10 : Serial.print("F10"); break; | |||||
case KEYD_F11 : Serial.print("F11"); break; | |||||
case KEYD_F12 : Serial.print("F12"); break; | |||||
default: Serial.print((char)key); break; | |||||
} | |||||
Serial.print("' "); | |||||
Serial.print(key); | |||||
Serial.print(" MOD: "); | |||||
if (keyboard1) { | |||||
Serial.print(keyboard1.getModifiers(), HEX); | |||||
Serial.print(" OEM: "); | |||||
Serial.print(keyboard1.getOemKey(), HEX); | |||||
Serial.print(" LEDS: "); | |||||
Serial.println(keyboard1.LEDS(), HEX); | |||||
//} else { | |||||
//Serial.print(keyboard2.getModifiers(), HEX); | |||||
//Serial.print(" OEM: "); | |||||
//Serial.print(keyboard2.getOemKey(), HEX); | |||||
//Serial.print(" LEDS: "); | |||||
//Serial.println(keyboard2.LEDS(), HEX); | |||||
} | |||||
//Serial.print("key "); | |||||
//Serial.print((char)keyboard1.getKey()); | |||||
//Serial.print(" "); | |||||
//Serial.print((char)keyboard2.getKey()); | |||||
//Serial.println(); | |||||
} | |||||
void OnHIDExtrasPress(uint32_t top, uint16_t key) | |||||
{ | |||||
Serial.print("HID ("); | |||||
Serial.print(top, HEX); | |||||
Serial.print(") key press:"); | |||||
Serial.print(key, HEX); | |||||
if (top == 0xc0000) { | |||||
switch (key) { | |||||
case 0x20 : Serial.print(" - +10"); break; | |||||
case 0x21 : Serial.print(" - +100"); break; | |||||
case 0x22 : Serial.print(" - AM/PM"); break; | |||||
case 0x30 : Serial.print(" - Power"); break; | |||||
case 0x31 : Serial.print(" - Reset"); break; | |||||
case 0x32 : Serial.print(" - Sleep"); break; | |||||
case 0x33 : Serial.print(" - Sleep After"); break; | |||||
case 0x34 : Serial.print(" - Sleep Mode"); break; | |||||
case 0x35 : Serial.print(" - Illumination"); break; | |||||
case 0x36 : Serial.print(" - Function Buttons"); break; | |||||
case 0x40 : Serial.print(" - Menu"); break; | |||||
case 0x41 : Serial.print(" - Menu Pick"); break; | |||||
case 0x42 : Serial.print(" - Menu Up"); break; | |||||
case 0x43 : Serial.print(" - Menu Down"); break; | |||||
case 0x44 : Serial.print(" - Menu Left"); break; | |||||
case 0x45 : Serial.print(" - Menu Right"); break; | |||||
case 0x46 : Serial.print(" - Menu Escape"); break; | |||||
case 0x47 : Serial.print(" - Menu Value Increase"); break; | |||||
case 0x48 : Serial.print(" - Menu Value Decrease"); break; | |||||
case 0x60 : Serial.print(" - Data On Screen"); break; | |||||
case 0x61 : Serial.print(" - Closed Caption"); break; | |||||
case 0x62 : Serial.print(" - Closed Caption Select"); break; | |||||
case 0x63 : Serial.print(" - VCR/TV"); break; | |||||
case 0x64 : Serial.print(" - Broadcast Mode"); break; | |||||
case 0x65 : Serial.print(" - Snapshot"); break; | |||||
case 0x66 : Serial.print(" - Still"); break; | |||||
case 0x80 : Serial.print(" - Selection"); break; | |||||
case 0x81 : Serial.print(" - Assign Selection"); break; | |||||
case 0x82 : Serial.print(" - Mode Step"); break; | |||||
case 0x83 : Serial.print(" - Recall Last"); break; | |||||
case 0x84 : Serial.print(" - Enter Channel"); break; | |||||
case 0x85 : Serial.print(" - Order Movie"); break; | |||||
case 0x86 : Serial.print(" - Channel"); break; | |||||
case 0x87 : Serial.print(" - Media Selection"); break; | |||||
case 0x88 : Serial.print(" - Media Select Computer"); break; | |||||
case 0x89 : Serial.print(" - Media Select TV"); break; | |||||
case 0x8A : Serial.print(" - Media Select WWW"); break; | |||||
case 0x8B : Serial.print(" - Media Select DVD"); break; | |||||
case 0x8C : Serial.print(" - Media Select Telephone"); break; | |||||
case 0x8D : Serial.print(" - Media Select Program Guide"); break; | |||||
case 0x8E : Serial.print(" - Media Select Video Phone"); break; | |||||
case 0x8F : Serial.print(" - Media Select Games"); break; | |||||
case 0x90 : Serial.print(" - Media Select Messages"); break; | |||||
case 0x91 : Serial.print(" - Media Select CD"); break; | |||||
case 0x92 : Serial.print(" - Media Select VCR"); break; | |||||
case 0x93 : Serial.print(" - Media Select Tuner"); break; | |||||
case 0x94 : Serial.print(" - Quit"); break; | |||||
case 0x95 : Serial.print(" - Help"); break; | |||||
case 0x96 : Serial.print(" - Media Select Tape"); break; | |||||
case 0x97 : Serial.print(" - Media Select Cable"); break; | |||||
case 0x98 : Serial.print(" - Media Select Satellite"); break; | |||||
case 0x99 : Serial.print(" - Media Select Security"); break; | |||||
case 0x9A : Serial.print(" - Media Select Home"); break; | |||||
case 0x9B : Serial.print(" - Media Select Call"); break; | |||||
case 0x9C : Serial.print(" - Channel Increment"); break; | |||||
case 0x9D : Serial.print(" - Channel Decrement"); break; | |||||
case 0x9E : Serial.print(" - Media Select SAP"); break; | |||||
case 0xA0 : Serial.print(" - VCR Plus"); break; | |||||
case 0xA1 : Serial.print(" - Once"); break; | |||||
case 0xA2 : Serial.print(" - Daily"); break; | |||||
case 0xA3 : Serial.print(" - Weekly"); break; | |||||
case 0xA4 : Serial.print(" - Monthly"); break; | |||||
case 0xB0 : Serial.print(" - Play"); break; | |||||
case 0xB1 : Serial.print(" - Pause"); break; | |||||
case 0xB2 : Serial.print(" - Record"); break; | |||||
case 0xB3 : Serial.print(" - Fast Forward"); break; | |||||
case 0xB4 : Serial.print(" - Rewind"); break; | |||||
case 0xB5 : Serial.print(" - Scan Next Track"); break; | |||||
case 0xB6 : Serial.print(" - Scan Previous Track"); break; | |||||
case 0xB7 : Serial.print(" - Stop"); break; | |||||
case 0xB8 : Serial.print(" - Eject"); break; | |||||
case 0xB9 : Serial.print(" - Random Play"); break; | |||||
case 0xBA : Serial.print(" - Select DisC"); break; | |||||
case 0xBB : Serial.print(" - Enter Disc"); break; | |||||
case 0xBC : Serial.print(" - Repeat"); break; | |||||
case 0xBD : Serial.print(" - Tracking"); break; | |||||
case 0xBE : Serial.print(" - Track Normal"); break; | |||||
case 0xBF : Serial.print(" - Slow Tracking"); break; | |||||
case 0xC0 : Serial.print(" - Frame Forward"); break; | |||||
case 0xC1 : Serial.print(" - Frame Back"); break; | |||||
case 0xC2 : Serial.print(" - Mark"); break; | |||||
case 0xC3 : Serial.print(" - Clear Mark"); break; | |||||
case 0xC4 : Serial.print(" - Repeat From Mark"); break; | |||||
case 0xC5 : Serial.print(" - Return To Mark"); break; | |||||
case 0xC6 : Serial.print(" - Search Mark Forward"); break; | |||||
case 0xC7 : Serial.print(" - Search Mark Backwards"); break; | |||||
case 0xC8 : Serial.print(" - Counter Reset"); break; | |||||
case 0xC9 : Serial.print(" - Show Counter"); break; | |||||
case 0xCA : Serial.print(" - Tracking Increment"); break; | |||||
case 0xCB : Serial.print(" - Tracking Decrement"); break; | |||||
case 0xCD : Serial.print(" - Pause/Continue"); break; | |||||
case 0xE0 : Serial.print(" - Volume"); break; | |||||
case 0xE1 : Serial.print(" - Balance"); break; | |||||
case 0xE2 : Serial.print(" - Mute"); break; | |||||
case 0xE3 : Serial.print(" - Bass"); break; | |||||
case 0xE4 : Serial.print(" - Treble"); break; | |||||
case 0xE5 : Serial.print(" - Bass Boost"); break; | |||||
case 0xE6 : Serial.print(" - Surround Mode"); break; | |||||
case 0xE7 : Serial.print(" - Loudness"); break; | |||||
case 0xE8 : Serial.print(" - MPX"); break; | |||||
case 0xE9 : Serial.print(" - Volume Up"); break; | |||||
case 0xEA : Serial.print(" - Volume Down"); break; | |||||
case 0xF0 : Serial.print(" - Speed Select"); break; | |||||
case 0xF1 : Serial.print(" - Playback Speed"); break; | |||||
case 0xF2 : Serial.print(" - Standard Play"); break; | |||||
case 0xF3 : Serial.print(" - Long Play"); break; | |||||
case 0xF4 : Serial.print(" - Extended Play"); break; | |||||
case 0xF5 : Serial.print(" - Slow"); break; | |||||
case 0x100: Serial.print(" - Fan Enable"); break; | |||||
case 0x101: Serial.print(" - Fan Speed"); break; | |||||
case 0x102: Serial.print(" - Light"); break; | |||||
case 0x103: Serial.print(" - Light Illumination Level"); break; | |||||
case 0x104: Serial.print(" - Climate Control Enable"); break; | |||||
case 0x105: Serial.print(" - Room Temperature"); break; | |||||
case 0x106: Serial.print(" - Security Enable"); break; | |||||
case 0x107: Serial.print(" - Fire Alarm"); break; | |||||
case 0x108: Serial.print(" - Police Alarm"); break; | |||||
case 0x150: Serial.print(" - Balance Right"); break; | |||||
case 0x151: Serial.print(" - Balance Left"); break; | |||||
case 0x152: Serial.print(" - Bass Increment"); break; | |||||
case 0x153: Serial.print(" - Bass Decrement"); break; | |||||
case 0x154: Serial.print(" - Treble Increment"); break; | |||||
case 0x155: Serial.print(" - Treble Decrement"); break; | |||||
case 0x160: Serial.print(" - Speaker System"); break; | |||||
case 0x161: Serial.print(" - Channel Left"); break; | |||||
case 0x162: Serial.print(" - Channel Right"); break; | |||||
case 0x163: Serial.print(" - Channel Center"); break; | |||||
case 0x164: Serial.print(" - Channel Front"); break; | |||||
case 0x165: Serial.print(" - Channel Center Front"); break; | |||||
case 0x166: Serial.print(" - Channel Side"); break; | |||||
case 0x167: Serial.print(" - Channel Surround"); break; | |||||
case 0x168: Serial.print(" - Channel Low Frequency Enhancement"); break; | |||||
case 0x169: Serial.print(" - Channel Top"); break; | |||||
case 0x16A: Serial.print(" - Channel Unknown"); break; | |||||
case 0x170: Serial.print(" - Sub-channel"); break; | |||||
case 0x171: Serial.print(" - Sub-channel Increment"); break; | |||||
case 0x172: Serial.print(" - Sub-channel Decrement"); break; | |||||
case 0x173: Serial.print(" - Alternate Audio Increment"); break; | |||||
case 0x174: Serial.print(" - Alternate Audio Decrement"); break; | |||||
case 0x180: Serial.print(" - Application Launch Buttons"); break; | |||||
case 0x181: Serial.print(" - AL Launch Button Configuration Tool"); break; | |||||
case 0x182: Serial.print(" - AL Programmable Button Configuration"); break; | |||||
case 0x183: Serial.print(" - AL Consumer Control Configuration"); break; | |||||
case 0x184: Serial.print(" - AL Word Processor"); break; | |||||
case 0x185: Serial.print(" - AL Text Editor"); break; | |||||
case 0x186: Serial.print(" - AL Spreadsheet"); break; | |||||
case 0x187: Serial.print(" - AL Graphics Editor"); break; | |||||
case 0x188: Serial.print(" - AL Presentation App"); break; | |||||
case 0x189: Serial.print(" - AL Database App"); break; | |||||
case 0x18A: Serial.print(" - AL Email Reader"); break; | |||||
case 0x18B: Serial.print(" - AL Newsreader"); break; | |||||
case 0x18C: Serial.print(" - AL Voicemail"); break; | |||||
case 0x18D: Serial.print(" - AL Contacts/Address Book"); break; | |||||
case 0x18E: Serial.print(" - AL Calendar/Schedule"); break; | |||||
case 0x18F: Serial.print(" - AL Task/Project Manager"); break; | |||||
case 0x190: Serial.print(" - AL Log/Journal/Timecard"); break; | |||||
case 0x191: Serial.print(" - AL Checkbook/Finance"); break; | |||||
case 0x192: Serial.print(" - AL Calculator"); break; | |||||
case 0x193: Serial.print(" - AL A/V Capture/Playback"); break; | |||||
case 0x194: Serial.print(" - AL Local Machine Browser"); break; | |||||
case 0x195: Serial.print(" - AL LAN/WAN Browser"); break; | |||||
case 0x196: Serial.print(" - AL Internet Browser"); break; | |||||
case 0x197: Serial.print(" - AL Remote Networking/ISP Connect"); break; | |||||
case 0x198: Serial.print(" - AL Network Conference"); break; | |||||
case 0x199: Serial.print(" - AL Network Chat"); break; | |||||
case 0x19A: Serial.print(" - AL Telephony/Dialer"); break; | |||||
case 0x19B: Serial.print(" - AL Logon"); break; | |||||
case 0x19C: Serial.print(" - AL Logoff"); break; | |||||
case 0x19D: Serial.print(" - AL Logon/Logoff"); break; | |||||
case 0x19E: Serial.print(" - AL Terminal Lock/Screensaver"); break; | |||||
case 0x19F: Serial.print(" - AL Control Panel"); break; | |||||
case 0x1A0: Serial.print(" - AL Command Line Processor/Run"); break; | |||||
case 0x1A1: Serial.print(" - AL Process/Task Manager"); break; | |||||
case 0x1A2: Serial.print(" - AL Select Tast/Application"); break; | |||||
case 0x1A3: Serial.print(" - AL Next Task/Application"); break; | |||||
case 0x1A4: Serial.print(" - AL Previous Task/Application"); break; | |||||
case 0x1A5: Serial.print(" - AL Preemptive Halt Task/Application"); break; | |||||
case 0x200: Serial.print(" - Generic GUI Application Controls"); break; | |||||
case 0x201: Serial.print(" - AC New"); break; | |||||
case 0x202: Serial.print(" - AC Open"); break; | |||||
case 0x203: Serial.print(" - AC Close"); break; | |||||
case 0x204: Serial.print(" - AC Exit"); break; | |||||
case 0x205: Serial.print(" - AC Maximize"); break; | |||||
case 0x206: Serial.print(" - AC Minimize"); break; | |||||
case 0x207: Serial.print(" - AC Save"); break; | |||||
case 0x208: Serial.print(" - AC Print"); break; | |||||
case 0x209: Serial.print(" - AC Properties"); break; | |||||
case 0x21A: Serial.print(" - AC Undo"); break; | |||||
case 0x21B: Serial.print(" - AC Copy"); break; | |||||
case 0x21C: Serial.print(" - AC Cut"); break; | |||||
case 0x21D: Serial.print(" - AC Paste"); break; | |||||
case 0x21E: Serial.print(" - AC Select All"); break; | |||||
case 0x21F: Serial.print(" - AC Find"); break; | |||||
case 0x220: Serial.print(" - AC Find and Replace"); break; | |||||
case 0x221: Serial.print(" - AC Search"); break; | |||||
case 0x222: Serial.print(" - AC Go To"); break; | |||||
case 0x223: Serial.print(" - AC Home"); break; | |||||
case 0x224: Serial.print(" - AC Back"); break; | |||||
case 0x225: Serial.print(" - AC Forward"); break; | |||||
case 0x226: Serial.print(" - AC Stop"); break; | |||||
case 0x227: Serial.print(" - AC Refresh"); break; | |||||
case 0x228: Serial.print(" - AC Previous Link"); break; | |||||
case 0x229: Serial.print(" - AC Next Link"); break; | |||||
case 0x22A: Serial.print(" - AC Bookmarks"); break; | |||||
case 0x22B: Serial.print(" - AC History"); break; | |||||
case 0x22C: Serial.print(" - AC Subscriptions"); break; | |||||
case 0x22D: Serial.print(" - AC Zoom In"); break; | |||||
case 0x22E: Serial.print(" - AC Zoom Out"); break; | |||||
case 0x22F: Serial.print(" - AC Zoom"); break; | |||||
case 0x230: Serial.print(" - AC Full Screen View"); break; | |||||
case 0x231: Serial.print(" - AC Normal View"); break; | |||||
case 0x232: Serial.print(" - AC View Toggle"); break; | |||||
case 0x233: Serial.print(" - AC Scroll Up"); break; | |||||
case 0x234: Serial.print(" - AC Scroll Down"); break; | |||||
case 0x235: Serial.print(" - AC Scroll"); break; | |||||
case 0x236: Serial.print(" - AC Pan Left"); break; | |||||
case 0x237: Serial.print(" - AC Pan Right"); break; | |||||
case 0x238: Serial.print(" - AC Pan"); break; | |||||
case 0x239: Serial.print(" - AC New Window"); break; | |||||
case 0x23A: Serial.print(" - AC Tile Horizontally"); break; | |||||
case 0x23B: Serial.print(" - AC Tile Vertically"); break; | |||||
case 0x23C: Serial.print(" - AC Format"); break; | |||||
} | |||||
} | |||||
Serial.println(); | |||||
} | |||||
void OnHIDExtrasRelease(uint32_t top, uint16_t key) | |||||
{ | |||||
Serial.print("HID ("); | |||||
Serial.print(top, HEX); | |||||
Serial.print(") key release:"); | |||||
Serial.println(key, HEX); | |||||
} | |||||
bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||||
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy | |||||
// to output to Serial. while still having Raw Hid... | |||||
if (usage == 0xffc90004) { | |||||
// Lets trim off trailing null characters. | |||||
while ((len > 0) && (data[len-1] == 0)) { | |||||
len--; | |||||
} | |||||
if (len) { | |||||
Serial.print("RawHid Serial: "); | |||||
Serial.write(data, len); | |||||
} | |||||
} else { | |||||
Serial.print("RawHID data: "); | |||||
Serial.println(usage, HEX); | |||||
while (len) { | |||||
uint8_t cb = (len > 16)? 16 : len; | |||||
const uint8_t *p = data; | |||||
uint8_t i; | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.printf("%02x ", *p++); | |||||
} | |||||
Serial.print(": "); | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.write(((*data >= ' ')&&(*data <= '~'))? *data : '.'); | |||||
data++; | |||||
} | |||||
len -= cb; | |||||
Serial.println(); | |||||
} | |||||
} | |||||
return true; | |||||
} |
// Simple test of USB Host Mouse/Keyboard | |||||
// | |||||
// This example is in the public domain | |||||
#include "USBHost_t36.h" | |||||
USBHost myusb; | |||||
USBHub hub1(myusb); | |||||
USBHub hub2(myusb); | |||||
KeyboardController keyboard1(myusb); | |||||
KeyboardController keyboard2(myusb); | |||||
USBHIDParser hid1(myusb); | |||||
USBHIDParser hid2(myusb); | |||||
USBHIDParser hid3(myusb); | |||||
USBHIDParser hid4(myusb); | |||||
USBHIDParser hid5(myusb); | |||||
MouseController mouse1(myusb); | |||||
JoystickController joystick1(myusb); | |||||
BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
//BluetoothController bluet(myusb); // version assumes it already was paired | |||||
int user_axis[64]; | |||||
uint32_t buttons_prev = 0; | |||||
RawHIDController rawhid1(myusb); | |||||
RawHIDController rawhid2(myusb, 0xffc90004); | |||||
USBDriver *drivers[] = {&hub1, &hub2,&keyboard1, &keyboard2, &joystick1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | |||||
const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "KB2", "JOY1D", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
bool driver_active[CNT_DEVICES] = {false, false, false, false}; | |||||
// Lets also look at HID Input devices | |||||
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() | |||||
{ | |||||
while (!Serial) ; // wait for Arduino Serial Monitor | |||||
Serial.println("\n\nUSB Host Testing"); | |||||
Serial.println(sizeof(USBHub), DEC); | |||||
myusb.begin(); | |||||
keyboard1.attachPress(OnPress); | |||||
keyboard2.attachPress(OnPress); | |||||
keyboard1.attachExtrasPress(OnHIDExtrasPress); | |||||
keyboard1.attachExtrasRelease(OnHIDExtrasRelease); | |||||
keyboard2.attachExtrasPress(OnHIDExtrasPress); | |||||
keyboard2.attachExtrasRelease(OnHIDExtrasRelease); | |||||
// The below forceBootProtocol will force which ever | |||||
// next keyboard that attaches to this device to be in boot protocol | |||||
// Only try this if you run into keyboard with issues. If this is a combined | |||||
// device like wireless mouse and keyboard this can cause mouse problems. | |||||
//keyboard1.forceBootProtocol(); | |||||
rawhid1.attachReceive(OnReceiveHidData); | |||||
rawhid2.attachReceive(OnReceiveHidData); | |||||
} | |||||
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]) { | |||||
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); | |||||
// Note: with some keyboards there is an issue that they don't output in boot protocol mode | |||||
// and may not work. The above code can try to force the keyboard into boot mode, but there | |||||
// are issues with doing this blindly with combo devices like wireless keyboard/mouse, which | |||||
// may cause the mouse to not work. Note: the above id is in the builtin list of | |||||
// vendor IDs that are already forced | |||||
if (drivers[i] == &keyboard1) { | |||||
if (keyboard1.idVendor() == 0x04D9) { | |||||
Serial.println("Gigabyte vendor: force boot protocol"); | |||||
// Gigabyte keyboard | |||||
keyboard1.forceBootProtocol(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
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); | |||||
} | |||||
} | |||||
} | |||||
if (mouse1.available()) { | |||||
Serial.print("Mouse: buttons = "); | |||||
Serial.print(mouse1.getButtons()); | |||||
Serial.print(", mouseX = "); | |||||
Serial.print(mouse1.getMouseX()); | |||||
Serial.print(", mouseY = "); | |||||
Serial.print(mouse1.getMouseY()); | |||||
Serial.print(", wheel = "); | |||||
Serial.print(mouse1.getWheel()); | |||||
Serial.print(", wheelH = "); | |||||
Serial.print(mouse1.getWheelH()); | |||||
Serial.println(); | |||||
mouse1.mouseDataClear(); | |||||
} | |||||
if (joystick1.available()) { | |||||
uint64_t axis_mask = joystick1.axisMask(); | |||||
uint64_t axis_changed_mask = joystick1.axisChangedMask(); | |||||
Serial.print("Joystick: buttons = "); | |||||
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: | |||||
case JoystickController::XBOX360: | |||||
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(); | |||||
} | |||||
// See if we have some RAW data | |||||
if (rawhid1) { | |||||
int ch; | |||||
uint8_t buffer[64]; | |||||
uint8_t count_chars = 0; | |||||
memset(buffer, 0, sizeof(buffer)); | |||||
if (Serial.available()) { | |||||
while (((ch = Serial.read()) != -1) && (count_chars < sizeof(buffer))) { | |||||
buffer[count_chars++] = ch; | |||||
} | |||||
rawhid1.sendPacket(buffer); | |||||
} | |||||
} | |||||
} | |||||
void OnPress(int key) | |||||
{ | |||||
Serial.print("key '"); | |||||
switch (key) { | |||||
case KEYD_UP : Serial.print("UP"); break; | |||||
case KEYD_DOWN : Serial.print("DN"); break; | |||||
case KEYD_LEFT : Serial.print("LEFT"); break; | |||||
case KEYD_RIGHT : Serial.print("RIGHT"); break; | |||||
case KEYD_INSERT : Serial.print("Ins"); break; | |||||
case KEYD_DELETE : Serial.print("Del"); break; | |||||
case KEYD_PAGE_UP : Serial.print("PUP"); break; | |||||
case KEYD_PAGE_DOWN: Serial.print("PDN"); break; | |||||
case KEYD_HOME : Serial.print("HOME"); break; | |||||
case KEYD_END : Serial.print("END"); break; | |||||
case KEYD_F1 : Serial.print("F1"); break; | |||||
case KEYD_F2 : Serial.print("F2"); break; | |||||
case KEYD_F3 : Serial.print("F3"); break; | |||||
case KEYD_F4 : Serial.print("F4"); break; | |||||
case KEYD_F5 : Serial.print("F5"); break; | |||||
case KEYD_F6 : Serial.print("F6"); break; | |||||
case KEYD_F7 : Serial.print("F7"); break; | |||||
case KEYD_F8 : Serial.print("F8"); break; | |||||
case KEYD_F9 : Serial.print("F9"); break; | |||||
case KEYD_F10 : Serial.print("F10"); break; | |||||
case KEYD_F11 : Serial.print("F11"); break; | |||||
case KEYD_F12 : Serial.print("F12"); break; | |||||
default: Serial.print((char)key); break; | |||||
} | |||||
Serial.print("' "); | |||||
Serial.print(key); | |||||
Serial.print(" MOD: "); | |||||
if (keyboard1) { | |||||
Serial.print(keyboard1.getModifiers(), HEX); | |||||
Serial.print(" OEM: "); | |||||
Serial.print(keyboard1.getOemKey(), HEX); | |||||
Serial.print(" LEDS: "); | |||||
Serial.println(keyboard1.LEDS(), HEX); | |||||
} else { | |||||
Serial.print(keyboard2.getModifiers(), HEX); | |||||
Serial.print(" OEM: "); | |||||
Serial.print(keyboard2.getOemKey(), HEX); | |||||
Serial.print(" LEDS: "); | |||||
Serial.println(keyboard2.LEDS(), HEX); | |||||
} | |||||
//Serial.print("key "); | |||||
//Serial.print((char)keyboard1.getKey()); | |||||
//Serial.print(" "); | |||||
//Serial.print((char)keyboard2.getKey()); | |||||
//Serial.println(); | |||||
} | |||||
void OnHIDExtrasPress(uint32_t top, uint16_t key) | |||||
{ | |||||
Serial.print("HID ("); | |||||
Serial.print(top, HEX); | |||||
Serial.print(") key press:"); | |||||
Serial.print(key, HEX); | |||||
if (top == 0xc0000) { | |||||
switch (key) { | |||||
case 0x20 : Serial.print(" - +10"); break; | |||||
case 0x21 : Serial.print(" - +100"); break; | |||||
case 0x22 : Serial.print(" - AM/PM"); break; | |||||
case 0x30 : Serial.print(" - Power"); break; | |||||
case 0x31 : Serial.print(" - Reset"); break; | |||||
case 0x32 : Serial.print(" - Sleep"); break; | |||||
case 0x33 : Serial.print(" - Sleep After"); break; | |||||
case 0x34 : Serial.print(" - Sleep Mode"); break; | |||||
case 0x35 : Serial.print(" - Illumination"); break; | |||||
case 0x36 : Serial.print(" - Function Buttons"); break; | |||||
case 0x40 : Serial.print(" - Menu"); break; | |||||
case 0x41 : Serial.print(" - Menu Pick"); break; | |||||
case 0x42 : Serial.print(" - Menu Up"); break; | |||||
case 0x43 : Serial.print(" - Menu Down"); break; | |||||
case 0x44 : Serial.print(" - Menu Left"); break; | |||||
case 0x45 : Serial.print(" - Menu Right"); break; | |||||
case 0x46 : Serial.print(" - Menu Escape"); break; | |||||
case 0x47 : Serial.print(" - Menu Value Increase"); break; | |||||
case 0x48 : Serial.print(" - Menu Value Decrease"); break; | |||||
case 0x60 : Serial.print(" - Data On Screen"); break; | |||||
case 0x61 : Serial.print(" - Closed Caption"); break; | |||||
case 0x62 : Serial.print(" - Closed Caption Select"); break; | |||||
case 0x63 : Serial.print(" - VCR/TV"); break; | |||||
case 0x64 : Serial.print(" - Broadcast Mode"); break; | |||||
case 0x65 : Serial.print(" - Snapshot"); break; | |||||
case 0x66 : Serial.print(" - Still"); break; | |||||
case 0x80 : Serial.print(" - Selection"); break; | |||||
case 0x81 : Serial.print(" - Assign Selection"); break; | |||||
case 0x82 : Serial.print(" - Mode Step"); break; | |||||
case 0x83 : Serial.print(" - Recall Last"); break; | |||||
case 0x84 : Serial.print(" - Enter Channel"); break; | |||||
case 0x85 : Serial.print(" - Order Movie"); break; | |||||
case 0x86 : Serial.print(" - Channel"); break; | |||||
case 0x87 : Serial.print(" - Media Selection"); break; | |||||
case 0x88 : Serial.print(" - Media Select Computer"); break; | |||||
case 0x89 : Serial.print(" - Media Select TV"); break; | |||||
case 0x8A : Serial.print(" - Media Select WWW"); break; | |||||
case 0x8B : Serial.print(" - Media Select DVD"); break; | |||||
case 0x8C : Serial.print(" - Media Select Telephone"); break; | |||||
case 0x8D : Serial.print(" - Media Select Program Guide"); break; | |||||
case 0x8E : Serial.print(" - Media Select Video Phone"); break; | |||||
case 0x8F : Serial.print(" - Media Select Games"); break; | |||||
case 0x90 : Serial.print(" - Media Select Messages"); break; | |||||
case 0x91 : Serial.print(" - Media Select CD"); break; | |||||
case 0x92 : Serial.print(" - Media Select VCR"); break; | |||||
case 0x93 : Serial.print(" - Media Select Tuner"); break; | |||||
case 0x94 : Serial.print(" - Quit"); break; | |||||
case 0x95 : Serial.print(" - Help"); break; | |||||
case 0x96 : Serial.print(" - Media Select Tape"); break; | |||||
case 0x97 : Serial.print(" - Media Select Cable"); break; | |||||
case 0x98 : Serial.print(" - Media Select Satellite"); break; | |||||
case 0x99 : Serial.print(" - Media Select Security"); break; | |||||
case 0x9A : Serial.print(" - Media Select Home"); break; | |||||
case 0x9B : Serial.print(" - Media Select Call"); break; | |||||
case 0x9C : Serial.print(" - Channel Increment"); break; | |||||
case 0x9D : Serial.print(" - Channel Decrement"); break; | |||||
case 0x9E : Serial.print(" - Media Select SAP"); break; | |||||
case 0xA0 : Serial.print(" - VCR Plus"); break; | |||||
case 0xA1 : Serial.print(" - Once"); break; | |||||
case 0xA2 : Serial.print(" - Daily"); break; | |||||
case 0xA3 : Serial.print(" - Weekly"); break; | |||||
case 0xA4 : Serial.print(" - Monthly"); break; | |||||
case 0xB0 : Serial.print(" - Play"); break; | |||||
case 0xB1 : Serial.print(" - Pause"); break; | |||||
case 0xB2 : Serial.print(" - Record"); break; | |||||
case 0xB3 : Serial.print(" - Fast Forward"); break; | |||||
case 0xB4 : Serial.print(" - Rewind"); break; | |||||
case 0xB5 : Serial.print(" - Scan Next Track"); break; | |||||
case 0xB6 : Serial.print(" - Scan Previous Track"); break; | |||||
case 0xB7 : Serial.print(" - Stop"); break; | |||||
case 0xB8 : Serial.print(" - Eject"); break; | |||||
case 0xB9 : Serial.print(" - Random Play"); break; | |||||
case 0xBA : Serial.print(" - Select DisC"); break; | |||||
case 0xBB : Serial.print(" - Enter Disc"); break; | |||||
case 0xBC : Serial.print(" - Repeat"); break; | |||||
case 0xBD : Serial.print(" - Tracking"); break; | |||||
case 0xBE : Serial.print(" - Track Normal"); break; | |||||
case 0xBF : Serial.print(" - Slow Tracking"); break; | |||||
case 0xC0 : Serial.print(" - Frame Forward"); break; | |||||
case 0xC1 : Serial.print(" - Frame Back"); break; | |||||
case 0xC2 : Serial.print(" - Mark"); break; | |||||
case 0xC3 : Serial.print(" - Clear Mark"); break; | |||||
case 0xC4 : Serial.print(" - Repeat From Mark"); break; | |||||
case 0xC5 : Serial.print(" - Return To Mark"); break; | |||||
case 0xC6 : Serial.print(" - Search Mark Forward"); break; | |||||
case 0xC7 : Serial.print(" - Search Mark Backwards"); break; | |||||
case 0xC8 : Serial.print(" - Counter Reset"); break; | |||||
case 0xC9 : Serial.print(" - Show Counter"); break; | |||||
case 0xCA : Serial.print(" - Tracking Increment"); break; | |||||
case 0xCB : Serial.print(" - Tracking Decrement"); break; | |||||
case 0xCD : Serial.print(" - Pause/Continue"); break; | |||||
case 0xE0 : Serial.print(" - Volume"); break; | |||||
case 0xE1 : Serial.print(" - Balance"); break; | |||||
case 0xE2 : Serial.print(" - Mute"); break; | |||||
case 0xE3 : Serial.print(" - Bass"); break; | |||||
case 0xE4 : Serial.print(" - Treble"); break; | |||||
case 0xE5 : Serial.print(" - Bass Boost"); break; | |||||
case 0xE6 : Serial.print(" - Surround Mode"); break; | |||||
case 0xE7 : Serial.print(" - Loudness"); break; | |||||
case 0xE8 : Serial.print(" - MPX"); break; | |||||
case 0xE9 : Serial.print(" - Volume Up"); break; | |||||
case 0xEA : Serial.print(" - Volume Down"); break; | |||||
case 0xF0 : Serial.print(" - Speed Select"); break; | |||||
case 0xF1 : Serial.print(" - Playback Speed"); break; | |||||
case 0xF2 : Serial.print(" - Standard Play"); break; | |||||
case 0xF3 : Serial.print(" - Long Play"); break; | |||||
case 0xF4 : Serial.print(" - Extended Play"); break; | |||||
case 0xF5 : Serial.print(" - Slow"); break; | |||||
case 0x100: Serial.print(" - Fan Enable"); break; | |||||
case 0x101: Serial.print(" - Fan Speed"); break; | |||||
case 0x102: Serial.print(" - Light"); break; | |||||
case 0x103: Serial.print(" - Light Illumination Level"); break; | |||||
case 0x104: Serial.print(" - Climate Control Enable"); break; | |||||
case 0x105: Serial.print(" - Room Temperature"); break; | |||||
case 0x106: Serial.print(" - Security Enable"); break; | |||||
case 0x107: Serial.print(" - Fire Alarm"); break; | |||||
case 0x108: Serial.print(" - Police Alarm"); break; | |||||
case 0x150: Serial.print(" - Balance Right"); break; | |||||
case 0x151: Serial.print(" - Balance Left"); break; | |||||
case 0x152: Serial.print(" - Bass Increment"); break; | |||||
case 0x153: Serial.print(" - Bass Decrement"); break; | |||||
case 0x154: Serial.print(" - Treble Increment"); break; | |||||
case 0x155: Serial.print(" - Treble Decrement"); break; | |||||
case 0x160: Serial.print(" - Speaker System"); break; | |||||
case 0x161: Serial.print(" - Channel Left"); break; | |||||
case 0x162: Serial.print(" - Channel Right"); break; | |||||
case 0x163: Serial.print(" - Channel Center"); break; | |||||
case 0x164: Serial.print(" - Channel Front"); break; | |||||
case 0x165: Serial.print(" - Channel Center Front"); break; | |||||
case 0x166: Serial.print(" - Channel Side"); break; | |||||
case 0x167: Serial.print(" - Channel Surround"); break; | |||||
case 0x168: Serial.print(" - Channel Low Frequency Enhancement"); break; | |||||
case 0x169: Serial.print(" - Channel Top"); break; | |||||
case 0x16A: Serial.print(" - Channel Unknown"); break; | |||||
case 0x170: Serial.print(" - Sub-channel"); break; | |||||
case 0x171: Serial.print(" - Sub-channel Increment"); break; | |||||
case 0x172: Serial.print(" - Sub-channel Decrement"); break; | |||||
case 0x173: Serial.print(" - Alternate Audio Increment"); break; | |||||
case 0x174: Serial.print(" - Alternate Audio Decrement"); break; | |||||
case 0x180: Serial.print(" - Application Launch Buttons"); break; | |||||
case 0x181: Serial.print(" - AL Launch Button Configuration Tool"); break; | |||||
case 0x182: Serial.print(" - AL Programmable Button Configuration"); break; | |||||
case 0x183: Serial.print(" - AL Consumer Control Configuration"); break; | |||||
case 0x184: Serial.print(" - AL Word Processor"); break; | |||||
case 0x185: Serial.print(" - AL Text Editor"); break; | |||||
case 0x186: Serial.print(" - AL Spreadsheet"); break; | |||||
case 0x187: Serial.print(" - AL Graphics Editor"); break; | |||||
case 0x188: Serial.print(" - AL Presentation App"); break; | |||||
case 0x189: Serial.print(" - AL Database App"); break; | |||||
case 0x18A: Serial.print(" - AL Email Reader"); break; | |||||
case 0x18B: Serial.print(" - AL Newsreader"); break; | |||||
case 0x18C: Serial.print(" - AL Voicemail"); break; | |||||
case 0x18D: Serial.print(" - AL Contacts/Address Book"); break; | |||||
case 0x18E: Serial.print(" - AL Calendar/Schedule"); break; | |||||
case 0x18F: Serial.print(" - AL Task/Project Manager"); break; | |||||
case 0x190: Serial.print(" - AL Log/Journal/Timecard"); break; | |||||
case 0x191: Serial.print(" - AL Checkbook/Finance"); break; | |||||
case 0x192: Serial.print(" - AL Calculator"); break; | |||||
case 0x193: Serial.print(" - AL A/V Capture/Playback"); break; | |||||
case 0x194: Serial.print(" - AL Local Machine Browser"); break; | |||||
case 0x195: Serial.print(" - AL LAN/WAN Browser"); break; | |||||
case 0x196: Serial.print(" - AL Internet Browser"); break; | |||||
case 0x197: Serial.print(" - AL Remote Networking/ISP Connect"); break; | |||||
case 0x198: Serial.print(" - AL Network Conference"); break; | |||||
case 0x199: Serial.print(" - AL Network Chat"); break; | |||||
case 0x19A: Serial.print(" - AL Telephony/Dialer"); break; | |||||
case 0x19B: Serial.print(" - AL Logon"); break; | |||||
case 0x19C: Serial.print(" - AL Logoff"); break; | |||||
case 0x19D: Serial.print(" - AL Logon/Logoff"); break; | |||||
case 0x19E: Serial.print(" - AL Terminal Lock/Screensaver"); break; | |||||
case 0x19F: Serial.print(" - AL Control Panel"); break; | |||||
case 0x1A0: Serial.print(" - AL Command Line Processor/Run"); break; | |||||
case 0x1A1: Serial.print(" - AL Process/Task Manager"); break; | |||||
case 0x1A2: Serial.print(" - AL Select Tast/Application"); break; | |||||
case 0x1A3: Serial.print(" - AL Next Task/Application"); break; | |||||
case 0x1A4: Serial.print(" - AL Previous Task/Application"); break; | |||||
case 0x1A5: Serial.print(" - AL Preemptive Halt Task/Application"); break; | |||||
case 0x200: Serial.print(" - Generic GUI Application Controls"); break; | |||||
case 0x201: Serial.print(" - AC New"); break; | |||||
case 0x202: Serial.print(" - AC Open"); break; | |||||
case 0x203: Serial.print(" - AC Close"); break; | |||||
case 0x204: Serial.print(" - AC Exit"); break; | |||||
case 0x205: Serial.print(" - AC Maximize"); break; | |||||
case 0x206: Serial.print(" - AC Minimize"); break; | |||||
case 0x207: Serial.print(" - AC Save"); break; | |||||
case 0x208: Serial.print(" - AC Print"); break; | |||||
case 0x209: Serial.print(" - AC Properties"); break; | |||||
case 0x21A: Serial.print(" - AC Undo"); break; | |||||
case 0x21B: Serial.print(" - AC Copy"); break; | |||||
case 0x21C: Serial.print(" - AC Cut"); break; | |||||
case 0x21D: Serial.print(" - AC Paste"); break; | |||||
case 0x21E: Serial.print(" - AC Select All"); break; | |||||
case 0x21F: Serial.print(" - AC Find"); break; | |||||
case 0x220: Serial.print(" - AC Find and Replace"); break; | |||||
case 0x221: Serial.print(" - AC Search"); break; | |||||
case 0x222: Serial.print(" - AC Go To"); break; | |||||
case 0x223: Serial.print(" - AC Home"); break; | |||||
case 0x224: Serial.print(" - AC Back"); break; | |||||
case 0x225: Serial.print(" - AC Forward"); break; | |||||
case 0x226: Serial.print(" - AC Stop"); break; | |||||
case 0x227: Serial.print(" - AC Refresh"); break; | |||||
case 0x228: Serial.print(" - AC Previous Link"); break; | |||||
case 0x229: Serial.print(" - AC Next Link"); break; | |||||
case 0x22A: Serial.print(" - AC Bookmarks"); break; | |||||
case 0x22B: Serial.print(" - AC History"); break; | |||||
case 0x22C: Serial.print(" - AC Subscriptions"); break; | |||||
case 0x22D: Serial.print(" - AC Zoom In"); break; | |||||
case 0x22E: Serial.print(" - AC Zoom Out"); break; | |||||
case 0x22F: Serial.print(" - AC Zoom"); break; | |||||
case 0x230: Serial.print(" - AC Full Screen View"); break; | |||||
case 0x231: Serial.print(" - AC Normal View"); break; | |||||
case 0x232: Serial.print(" - AC View Toggle"); break; | |||||
case 0x233: Serial.print(" - AC Scroll Up"); break; | |||||
case 0x234: Serial.print(" - AC Scroll Down"); break; | |||||
case 0x235: Serial.print(" - AC Scroll"); break; | |||||
case 0x236: Serial.print(" - AC Pan Left"); break; | |||||
case 0x237: Serial.print(" - AC Pan Right"); break; | |||||
case 0x238: Serial.print(" - AC Pan"); break; | |||||
case 0x239: Serial.print(" - AC New Window"); break; | |||||
case 0x23A: Serial.print(" - AC Tile Horizontally"); break; | |||||
case 0x23B: Serial.print(" - AC Tile Vertically"); break; | |||||
case 0x23C: Serial.print(" - AC Format"); break; | |||||
} | |||||
} | |||||
Serial.println(); | |||||
} | |||||
void OnHIDExtrasRelease(uint32_t top, uint16_t key) | |||||
{ | |||||
Serial.print("HID ("); | |||||
Serial.print(top, HEX); | |||||
Serial.print(") key release:"); | |||||
Serial.println(key, HEX); | |||||
} | |||||
bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||||
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy | |||||
// to output to Serial. while still having Raw Hid... | |||||
if (usage == 0xffc90004) { | |||||
// Lets trim off trailing null characters. | |||||
while ((len > 0) && (data[len - 1] == 0)) { | |||||
len--; | |||||
} | |||||
if (len) { | |||||
Serial.print("RawHid Serial: "); | |||||
Serial.write(data, len); | |||||
} | |||||
} else { | |||||
Serial.print("RawHID data: "); | |||||
Serial.println(usage, HEX); | |||||
while (len) { | |||||
uint8_t cb = (len > 16) ? 16 : len; | |||||
const uint8_t *p = data; | |||||
uint8_t i; | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.printf("%02x ", *p++); | |||||
} | |||||
Serial.print(": "); | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.write(((*data >= ' ') && (*data <= '~')) ? *data : '.'); | |||||
data++; | |||||
} | |||||
len -= cb; | |||||
Serial.println(); | |||||
} | |||||
} | |||||
return true; | |||||
} |
# Pacman-Arduino-Due / Modified for Teensy 3.6 and T4.x | |||||
Pacman Game for Arduino Due with tft ILI9341 and VGA output support | |||||
Pacman Game on Arduino Due with ILI9341 and VGA support (available 2 outputs at the same time), playable with keypad, 5 sample levels, VGA output is 240x320, source code avaliable on Github, Licensed under MIT License. | |||||
Original Pacman sketch modified to use a Teensy 3.6/T4 with ILI9341_t3n and USBHost_t36 libraries. Intended as demo for the incorporating BT or Serial gamepads such as the PS3 and PS4 into a user application. | |||||
Originally posted on: | |||||
Arduino Forum: | |||||
http://forum.arduino.cc/index.php?topic=375394.0 | |||||
Video: | |||||
https://www.youtube.com/watch?v=2Hdzr6m4QdU | |||||
<pre> | |||||
/******************************************************************************/ | |||||
/* */ | |||||
/* PACMAN GAME FOR TEENSY */ | |||||
/* */ | |||||
/******************************************************************************/ | |||||
/* Copyright (c) 2014 Dr. NCX (mirracle.mxx@gmail.com) */ | |||||
/* */ | |||||
/* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL */ | |||||
/* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED */ | |||||
/* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR */ | |||||
/* BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES */ | |||||
/* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, */ | |||||
/* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */ | |||||
/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS */ | |||||
/* SOFTWARE. */ | |||||
/* */ | |||||
/* MIT license, all text above must be included in any redistribution. */ | |||||
/******************************************************************************/ | |||||
/* Original Pacman sketch modified to use a Teensy 3.6/T4 with ILI9341_t3n */ | |||||
/* and USBHost_t36 libraries. Intended as demo for the incorporating BT */ | |||||
/* or Serial gamepads such as the PS3 and PS4 into a user application. */ | |||||
/* The original version for the Arduino Due and SNES controllers can be */ | |||||
/* found at */ | |||||
/* https://forum.arduino.cc/index.php?topic=375394.0 */ | |||||
/* and */ | |||||
/* https://github.com/DrNCXCortex/Pacman-Arduino-Due */ | |||||
/* */ | |||||
/******************************************************************************/ | |||||
/* ILI9341: */ | |||||
/*----------------------------------------------------------------------------*/ | |||||
/* 8 = RST */ | |||||
/* 9 = D/C */ | |||||
/* 10 = CS */ | |||||
/* can be changed at user discretion */ | |||||
/*----------------------------------------------------------------------------*/ | |||||
/*----------------------------------------------------------------------------*/ | |||||
/* KEYPAD: */ | |||||
/*----------------------------------------------------------------------------*/ | |||||
/* PS3: button START/Pause */ | |||||
/* button SELECT */ | |||||
/* button A/Diamond */ | |||||
/* button B /Circle */ | |||||
/* button UP */ | |||||
/* button DOWN */ | |||||
/* button LEFT */ | |||||
/* button RIGHT */ | |||||
/* */ | |||||
/* PS4: button START/Pause = Share on PS4 */ | |||||
/* button SELECT = Options on PS4 */ | |||||
/* button A/Square */ | |||||
/* button B /Circle */ | |||||
/* button UP */ | |||||
/* button DOWN */ | |||||
/* button LEFT */ | |||||
/* button RIGHT */ | |||||
/* *//******************************************************************************/ | |||||
</pre> |
// Simple test of USB Host Mouse/Keyboard | |||||
// | |||||
// This example is in the public domain | |||||
#include "USBHost_t36.h" | |||||
int mousex, mousey; | |||||
USBHost myusb; | |||||
USBHub hub1(myusb); | |||||
USBHub hub2(myusb); | |||||
KeyboardController keyboard1(myusb); | |||||
KeyboardController keyboard2(myusb); | |||||
USBHIDParser hid1(myusb); | |||||
USBHIDParser hid2(myusb); | |||||
USBHIDParser hid3(myusb); | |||||
USBHIDParser hid4(myusb); | |||||
USBHIDParser hid5(myusb); | |||||
DigitizerController digi1(myusb); | |||||
JoystickController joystick1(myusb); | |||||
//BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
BluetoothController bluet(myusb); // version assumes it already was paired | |||||
int user_axis[64]; | |||||
uint8_t digi_axis[64]; | |||||
uint32_t buttons_prev = 0; | |||||
//RawHIDController rawhid1(myusb); | |||||
RawHIDController rawhid2(myusb, 0xff000080); | |||||
USBDriver *drivers[] = {&hub1, &hub2,&keyboard1, &keyboard2, &joystick1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | |||||
const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "KB2", "JOY1D", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
bool driver_active[CNT_DEVICES] = {false, false, false, false}; | |||||
// Lets also look at HID Input devices | |||||
USBHIDInput *hiddrivers[] = {&digi1, &joystick1, &rawhid2}; | |||||
#define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | |||||
const char * hid_driver_names[CNT_DEVICES] = {"digi1", "Joystick1", "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() | |||||
{ | |||||
Serial1.begin(2000000); | |||||
while (!Serial) ; // wait for Arduino Serial Monitor | |||||
Serial.println("\n\nUSB Host Testing"); | |||||
Serial.println(sizeof(USBHub), DEC); | |||||
myusb.begin(); | |||||
keyboard1.attachPress(OnPress); | |||||
keyboard2.attachPress(OnPress); | |||||
keyboard1.attachExtrasPress(OnHIDExtrasPress); | |||||
keyboard1.attachExtrasRelease(OnHIDExtrasRelease); | |||||
keyboard2.attachExtrasPress(OnHIDExtrasPress); | |||||
keyboard2.attachExtrasRelease(OnHIDExtrasRelease); | |||||
// The below forceBootProtocol will force which ever | |||||
// next keyboard that attaches to this device to be in boot protocol | |||||
// Only try this if you run into keyboard with issues. If this is a combined | |||||
// device like wireless mouse and keyboard this can cause mouse problems. | |||||
//keyboard1.forceBootProtocol(); | |||||
//rawhid1.attachReceive(OnReceiveHidData); | |||||
rawhid2.attachReceive(OnReceiveHidData); | |||||
} | |||||
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]) { | |||||
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); | |||||
// Note: with some keyboards there is an issue that they don't output in boot protocol mode | |||||
// and may not work. The above code can try to force the keyboard into boot mode, but there | |||||
// are issues with doing this blindly with combo devices like wireless keyboard/mouse, which | |||||
// may cause the mouse to not work. Note: the above id is in the builtin list of | |||||
// vendor IDs that are already forced | |||||
if (drivers[i] == &keyboard1) { | |||||
if (keyboard1.idVendor() == 0x04D9) { | |||||
Serial.println("Gigabyte vendor: force boot protocol"); | |||||
// Gigabyte keyboard | |||||
keyboard1.forceBootProtocol(); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
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); | |||||
} | |||||
} | |||||
} | |||||
if (digi1.available()) { | |||||
Serial.print("Mouse: buttons = "); | |||||
Serial.print(digi1.getButtons()); | |||||
Serial.print(", mouseX = "); | |||||
Serial.print(digi1.getMouseX()); | |||||
Serial.print(", mouseY = "); | |||||
Serial.print(digi1.getMouseY()); | |||||
Serial.print(", wheel = "); | |||||
Serial.print(digi1.getWheel()); | |||||
Serial.print(", wheelH = "); | |||||
Serial.print(digi1.getWheelH()); | |||||
Serial.println(); | |||||
digi1.digitizerDataClear(); | |||||
for (uint8_t i = 0; i<10; i++) { | |||||
Serial.printf(" %d:%d", i, digi1.getAxis(i)); | |||||
} | |||||
Serial.println(); | |||||
} | |||||
if (joystick1.available()) { | |||||
uint64_t axis_mask = joystick1.axisMask(); | |||||
uint64_t axis_changed_mask = joystick1.axisChangedMask(); | |||||
Serial.print("Joystick: buttons = "); | |||||
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: | |||||
case JoystickController::XBOX360: | |||||
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(); | |||||
} | |||||
// See if we have some RAW data | |||||
/* if (rawhid1) { | |||||
int ch; | |||||
uint8_t buffer[64]; | |||||
uint8_t count_chars = 0; | |||||
memset(buffer, 0, sizeof(buffer)); | |||||
if (Serial.available()) { | |||||
while (((ch = Serial.read()) != -1) && (count_chars < sizeof(buffer))) { | |||||
buffer[count_chars++] = ch; | |||||
} | |||||
rawhid1.sendPacket(buffer); | |||||
} | |||||
} | |||||
*/ | |||||
} | |||||
void OnPress(int key) | |||||
{ | |||||
Serial.print("key '"); | |||||
switch (key) { | |||||
case KEYD_UP : Serial.print("UP"); break; | |||||
case KEYD_DOWN : Serial.print("DN"); break; | |||||
case KEYD_LEFT : Serial.print("LEFT"); break; | |||||
case KEYD_RIGHT : Serial.print("RIGHT"); break; | |||||
case KEYD_INSERT : Serial.print("Ins"); break; | |||||
case KEYD_DELETE : Serial.print("Del"); break; | |||||
case KEYD_PAGE_UP : Serial.print("PUP"); break; | |||||
case KEYD_PAGE_DOWN: Serial.print("PDN"); break; | |||||
case KEYD_HOME : Serial.print("HOME"); break; | |||||
case KEYD_END : Serial.print("END"); break; | |||||
case KEYD_F1 : Serial.print("F1"); break; | |||||
case KEYD_F2 : Serial.print("F2"); break; | |||||
case KEYD_F3 : Serial.print("F3"); break; | |||||
case KEYD_F4 : Serial.print("F4"); break; | |||||
case KEYD_F5 : Serial.print("F5"); break; | |||||
case KEYD_F6 : Serial.print("F6"); break; | |||||
case KEYD_F7 : Serial.print("F7"); break; | |||||
case KEYD_F8 : Serial.print("F8"); break; | |||||
case KEYD_F9 : Serial.print("F9"); break; | |||||
case KEYD_F10 : Serial.print("F10"); break; | |||||
case KEYD_F11 : Serial.print("F11"); break; | |||||
case KEYD_F12 : Serial.print("F12"); break; | |||||
default: Serial.print((char)key); break; | |||||
} | |||||
Serial.print("' "); | |||||
Serial.print(key); | |||||
Serial.print(" MOD: "); | |||||
if (keyboard1) { | |||||
Serial.print(keyboard1.getModifiers(), HEX); | |||||
Serial.print(" OEM: "); | |||||
Serial.print(keyboard1.getOemKey(), HEX); | |||||
Serial.print(" LEDS: "); | |||||
Serial.println(keyboard1.LEDS(), HEX); | |||||
} else { | |||||
Serial.print(keyboard2.getModifiers(), HEX); | |||||
Serial.print(" OEM: "); | |||||
Serial.print(keyboard2.getOemKey(), HEX); | |||||
Serial.print(" LEDS: "); | |||||
Serial.println(keyboard2.LEDS(), HEX); | |||||
} | |||||
//Serial.print("key "); | |||||
//Serial.print((char)keyboard1.getKey()); | |||||
//Serial.print(" "); | |||||
//Serial.print((char)keyboard2.getKey()); | |||||
//Serial.println(); | |||||
} | |||||
void OnHIDExtrasPress(uint32_t top, uint16_t key) | |||||
{ | |||||
Serial.print("HID ("); | |||||
Serial.print(top, HEX); | |||||
Serial.print(") key press:"); | |||||
Serial.print(key, HEX); | |||||
if (top == 0xc0000) { | |||||
switch (key) { | |||||
case 0x20 : Serial.print(" - +10"); break; | |||||
case 0x21 : Serial.print(" - +100"); break; | |||||
case 0x22 : Serial.print(" - AM/PM"); break; | |||||
case 0x30 : Serial.print(" - Power"); break; | |||||
case 0x31 : Serial.print(" - Reset"); break; | |||||
case 0x32 : Serial.print(" - Sleep"); break; | |||||
case 0x33 : Serial.print(" - Sleep After"); break; | |||||
case 0x34 : Serial.print(" - Sleep Mode"); break; | |||||
case 0x35 : Serial.print(" - Illumination"); break; | |||||
case 0x36 : Serial.print(" - Function Buttons"); break; | |||||
case 0x40 : Serial.print(" - Menu"); break; | |||||
case 0x41 : Serial.print(" - Menu Pick"); break; | |||||
case 0x42 : Serial.print(" - Menu Up"); break; | |||||
case 0x43 : Serial.print(" - Menu Down"); break; | |||||
case 0x44 : Serial.print(" - Menu Left"); break; | |||||
case 0x45 : Serial.print(" - Menu Right"); break; | |||||
case 0x46 : Serial.print(" - Menu Escape"); break; | |||||
case 0x47 : Serial.print(" - Menu Value Increase"); break; | |||||
case 0x48 : Serial.print(" - Menu Value Decrease"); break; | |||||
case 0x60 : Serial.print(" - Data On Screen"); break; | |||||
case 0x61 : Serial.print(" - Closed Caption"); break; | |||||
case 0x62 : Serial.print(" - Closed Caption Select"); break; | |||||
case 0x63 : Serial.print(" - VCR/TV"); break; | |||||
case 0x64 : Serial.print(" - Broadcast Mode"); break; | |||||
case 0x65 : Serial.print(" - Snapshot"); break; | |||||
case 0x66 : Serial.print(" - Still"); break; | |||||
case 0x80 : Serial.print(" - Selection"); break; | |||||
case 0x81 : Serial.print(" - Assign Selection"); break; | |||||
case 0x82 : Serial.print(" - Mode Step"); break; | |||||
case 0x83 : Serial.print(" - Recall Last"); break; | |||||
case 0x84 : Serial.print(" - Enter Channel"); break; | |||||
case 0x85 : Serial.print(" - Order Movie"); break; | |||||
case 0x86 : Serial.print(" - Channel"); break; | |||||
case 0x87 : Serial.print(" - Media Selection"); break; | |||||
case 0x88 : Serial.print(" - Media Select Computer"); break; | |||||
case 0x89 : Serial.print(" - Media Select TV"); break; | |||||
case 0x8A : Serial.print(" - Media Select WWW"); break; | |||||
case 0x8B : Serial.print(" - Media Select DVD"); break; | |||||
case 0x8C : Serial.print(" - Media Select Telephone"); break; | |||||
case 0x8D : Serial.print(" - Media Select Program Guide"); break; | |||||
case 0x8E : Serial.print(" - Media Select Video Phone"); break; | |||||
case 0x8F : Serial.print(" - Media Select Games"); break; | |||||
case 0x90 : Serial.print(" - Media Select Messages"); break; | |||||
case 0x91 : Serial.print(" - Media Select CD"); break; | |||||
case 0x92 : Serial.print(" - Media Select VCR"); break; | |||||
case 0x93 : Serial.print(" - Media Select Tuner"); break; | |||||
case 0x94 : Serial.print(" - Quit"); break; | |||||
case 0x95 : Serial.print(" - Help"); break; | |||||
case 0x96 : Serial.print(" - Media Select Tape"); break; | |||||
case 0x97 : Serial.print(" - Media Select Cable"); break; | |||||
case 0x98 : Serial.print(" - Media Select Satellite"); break; | |||||
case 0x99 : Serial.print(" - Media Select Security"); break; | |||||
case 0x9A : Serial.print(" - Media Select Home"); break; | |||||
case 0x9B : Serial.print(" - Media Select Call"); break; | |||||
case 0x9C : Serial.print(" - Channel Increment"); break; | |||||
case 0x9D : Serial.print(" - Channel Decrement"); break; | |||||
case 0x9E : Serial.print(" - Media Select SAP"); break; | |||||
case 0xA0 : Serial.print(" - VCR Plus"); break; | |||||
case 0xA1 : Serial.print(" - Once"); break; | |||||
case 0xA2 : Serial.print(" - Daily"); break; | |||||
case 0xA3 : Serial.print(" - Weekly"); break; | |||||
case 0xA4 : Serial.print(" - Monthly"); break; | |||||
case 0xB0 : Serial.print(" - Play"); break; | |||||
case 0xB1 : Serial.print(" - Pause"); break; | |||||
case 0xB2 : Serial.print(" - Record"); break; | |||||
case 0xB3 : Serial.print(" - Fast Forward"); break; | |||||
case 0xB4 : Serial.print(" - Rewind"); break; | |||||
case 0xB5 : Serial.print(" - Scan Next Track"); break; | |||||
case 0xB6 : Serial.print(" - Scan Previous Track"); break; | |||||
case 0xB7 : Serial.print(" - Stop"); break; | |||||
case 0xB8 : Serial.print(" - Eject"); break; | |||||
case 0xB9 : Serial.print(" - Random Play"); break; | |||||
case 0xBA : Serial.print(" - Select DisC"); break; | |||||
case 0xBB : Serial.print(" - Enter Disc"); break; | |||||
case 0xBC : Serial.print(" - Repeat"); break; | |||||
case 0xBD : Serial.print(" - Tracking"); break; | |||||
case 0xBE : Serial.print(" - Track Normal"); break; | |||||
case 0xBF : Serial.print(" - Slow Tracking"); break; | |||||
case 0xC0 : Serial.print(" - Frame Forward"); break; | |||||
case 0xC1 : Serial.print(" - Frame Back"); break; | |||||
case 0xC2 : Serial.print(" - Mark"); break; | |||||
case 0xC3 : Serial.print(" - Clear Mark"); break; | |||||
case 0xC4 : Serial.print(" - Repeat From Mark"); break; | |||||
case 0xC5 : Serial.print(" - Return To Mark"); break; | |||||
case 0xC6 : Serial.print(" - Search Mark Forward"); break; | |||||
case 0xC7 : Serial.print(" - Search Mark Backwards"); break; | |||||
case 0xC8 : Serial.print(" - Counter Reset"); break; | |||||
case 0xC9 : Serial.print(" - Show Counter"); break; | |||||
case 0xCA : Serial.print(" - Tracking Increment"); break; | |||||
case 0xCB : Serial.print(" - Tracking Decrement"); break; | |||||
case 0xCD : Serial.print(" - Pause/Continue"); break; | |||||
case 0xE0 : Serial.print(" - Volume"); break; | |||||
case 0xE1 : Serial.print(" - Balance"); break; | |||||
case 0xE2 : Serial.print(" - Mute"); break; | |||||
case 0xE3 : Serial.print(" - Bass"); break; | |||||
case 0xE4 : Serial.print(" - Treble"); break; | |||||
case 0xE5 : Serial.print(" - Bass Boost"); break; | |||||
case 0xE6 : Serial.print(" - Surround Mode"); break; | |||||
case 0xE7 : Serial.print(" - Loudness"); break; | |||||
case 0xE8 : Serial.print(" - MPX"); break; | |||||
case 0xE9 : Serial.print(" - Volume Up"); break; | |||||
case 0xEA : Serial.print(" - Volume Down"); break; | |||||
case 0xF0 : Serial.print(" - Speed Select"); break; | |||||
case 0xF1 : Serial.print(" - Playback Speed"); break; | |||||
case 0xF2 : Serial.print(" - Standard Play"); break; | |||||
case 0xF3 : Serial.print(" - Long Play"); break; | |||||
case 0xF4 : Serial.print(" - Extended Play"); break; | |||||
case 0xF5 : Serial.print(" - Slow"); break; | |||||
case 0x100: Serial.print(" - Fan Enable"); break; | |||||
case 0x101: Serial.print(" - Fan Speed"); break; | |||||
case 0x102: Serial.print(" - Light"); break; | |||||
case 0x103: Serial.print(" - Light Illumination Level"); break; | |||||
case 0x104: Serial.print(" - Climate Control Enable"); break; | |||||
case 0x105: Serial.print(" - Room Temperature"); break; | |||||
case 0x106: Serial.print(" - Security Enable"); break; | |||||
case 0x107: Serial.print(" - Fire Alarm"); break; | |||||
case 0x108: Serial.print(" - Police Alarm"); break; | |||||
case 0x150: Serial.print(" - Balance Right"); break; | |||||
case 0x151: Serial.print(" - Balance Left"); break; | |||||
case 0x152: Serial.print(" - Bass Increment"); break; | |||||
case 0x153: Serial.print(" - Bass Decrement"); break; | |||||
case 0x154: Serial.print(" - Treble Increment"); break; | |||||
case 0x155: Serial.print(" - Treble Decrement"); break; | |||||
case 0x160: Serial.print(" - Speaker System"); break; | |||||
case 0x161: Serial.print(" - Channel Left"); break; | |||||
case 0x162: Serial.print(" - Channel Right"); break; | |||||
case 0x163: Serial.print(" - Channel Center"); break; | |||||
case 0x164: Serial.print(" - Channel Front"); break; | |||||
case 0x165: Serial.print(" - Channel Center Front"); break; | |||||
case 0x166: Serial.print(" - Channel Side"); break; | |||||
case 0x167: Serial.print(" - Channel Surround"); break; | |||||
case 0x168: Serial.print(" - Channel Low Frequency Enhancement"); break; | |||||
case 0x169: Serial.print(" - Channel Top"); break; | |||||
case 0x16A: Serial.print(" - Channel Unknown"); break; | |||||
case 0x170: Serial.print(" - Sub-channel"); break; | |||||
case 0x171: Serial.print(" - Sub-channel Increment"); break; | |||||
case 0x172: Serial.print(" - Sub-channel Decrement"); break; | |||||
case 0x173: Serial.print(" - Alternate Audio Increment"); break; | |||||
case 0x174: Serial.print(" - Alternate Audio Decrement"); break; | |||||
case 0x180: Serial.print(" - Application Launch Buttons"); break; | |||||
case 0x181: Serial.print(" - AL Launch Button Configuration Tool"); break; | |||||
case 0x182: Serial.print(" - AL Programmable Button Configuration"); break; | |||||
case 0x183: Serial.print(" - AL Consumer Control Configuration"); break; | |||||
case 0x184: Serial.print(" - AL Word Processor"); break; | |||||
case 0x185: Serial.print(" - AL Text Editor"); break; | |||||
case 0x186: Serial.print(" - AL Spreadsheet"); break; | |||||
case 0x187: Serial.print(" - AL Graphics Editor"); break; | |||||
case 0x188: Serial.print(" - AL Presentation App"); break; | |||||
case 0x189: Serial.print(" - AL Database App"); break; | |||||
case 0x18A: Serial.print(" - AL Email Reader"); break; | |||||
case 0x18B: Serial.print(" - AL Newsreader"); break; | |||||
case 0x18C: Serial.print(" - AL Voicemail"); break; | |||||
case 0x18D: Serial.print(" - AL Contacts/Address Book"); break; | |||||
case 0x18E: Serial.print(" - AL Calendar/Schedule"); break; | |||||
case 0x18F: Serial.print(" - AL Task/Project Manager"); break; | |||||
case 0x190: Serial.print(" - AL Log/Journal/Timecard"); break; | |||||
case 0x191: Serial.print(" - AL Checkbook/Finance"); break; | |||||
case 0x192: Serial.print(" - AL Calculator"); break; | |||||
case 0x193: Serial.print(" - AL A/V Capture/Playback"); break; | |||||
case 0x194: Serial.print(" - AL Local Machine Browser"); break; | |||||
case 0x195: Serial.print(" - AL LAN/WAN Browser"); break; | |||||
case 0x196: Serial.print(" - AL Internet Browser"); break; | |||||
case 0x197: Serial.print(" - AL Remote Networking/ISP Connect"); break; | |||||
case 0x198: Serial.print(" - AL Network Conference"); break; | |||||
case 0x199: Serial.print(" - AL Network Chat"); break; | |||||
case 0x19A: Serial.print(" - AL Telephony/Dialer"); break; | |||||
case 0x19B: Serial.print(" - AL Logon"); break; | |||||
case 0x19C: Serial.print(" - AL Logoff"); break; | |||||
case 0x19D: Serial.print(" - AL Logon/Logoff"); break; | |||||
case 0x19E: Serial.print(" - AL Terminal Lock/Screensaver"); break; | |||||
case 0x19F: Serial.print(" - AL Control Panel"); break; | |||||
case 0x1A0: Serial.print(" - AL Command Line Processor/Run"); break; | |||||
case 0x1A1: Serial.print(" - AL Process/Task Manager"); break; | |||||
case 0x1A2: Serial.print(" - AL Select Tast/Application"); break; | |||||
case 0x1A3: Serial.print(" - AL Next Task/Application"); break; | |||||
case 0x1A4: Serial.print(" - AL Previous Task/Application"); break; | |||||
case 0x1A5: Serial.print(" - AL Preemptive Halt Task/Application"); break; | |||||
case 0x200: Serial.print(" - Generic GUI Application Controls"); break; | |||||
case 0x201: Serial.print(" - AC New"); break; | |||||
case 0x202: Serial.print(" - AC Open"); break; | |||||
case 0x203: Serial.print(" - AC Close"); break; | |||||
case 0x204: Serial.print(" - AC Exit"); break; | |||||
case 0x205: Serial.print(" - AC Maximize"); break; | |||||
case 0x206: Serial.print(" - AC Minimize"); break; | |||||
case 0x207: Serial.print(" - AC Save"); break; | |||||
case 0x208: Serial.print(" - AC Print"); break; | |||||
case 0x209: Serial.print(" - AC Properties"); break; | |||||
case 0x21A: Serial.print(" - AC Undo"); break; | |||||
case 0x21B: Serial.print(" - AC Copy"); break; | |||||
case 0x21C: Serial.print(" - AC Cut"); break; | |||||
case 0x21D: Serial.print(" - AC Paste"); break; | |||||
case 0x21E: Serial.print(" - AC Select All"); break; | |||||
case 0x21F: Serial.print(" - AC Find"); break; | |||||
case 0x220: Serial.print(" - AC Find and Replace"); break; | |||||
case 0x221: Serial.print(" - AC Search"); break; | |||||
case 0x222: Serial.print(" - AC Go To"); break; | |||||
case 0x223: Serial.print(" - AC Home"); break; | |||||
case 0x224: Serial.print(" - AC Back"); break; | |||||
case 0x225: Serial.print(" - AC Forward"); break; | |||||
case 0x226: Serial.print(" - AC Stop"); break; | |||||
case 0x227: Serial.print(" - AC Refresh"); break; | |||||
case 0x228: Serial.print(" - AC Previous Link"); break; | |||||
case 0x229: Serial.print(" - AC Next Link"); break; | |||||
case 0x22A: Serial.print(" - AC Bookmarks"); break; | |||||
case 0x22B: Serial.print(" - AC History"); break; | |||||
case 0x22C: Serial.print(" - AC Subscriptions"); break; | |||||
case 0x22D: Serial.print(" - AC Zoom In"); break; | |||||
case 0x22E: Serial.print(" - AC Zoom Out"); break; | |||||
case 0x22F: Serial.print(" - AC Zoom"); break; | |||||
case 0x230: Serial.print(" - AC Full Screen View"); break; | |||||
case 0x231: Serial.print(" - AC Normal View"); break; | |||||
case 0x232: Serial.print(" - AC View Toggle"); break; | |||||
case 0x233: Serial.print(" - AC Scroll Up"); break; | |||||
case 0x234: Serial.print(" - AC Scroll Down"); break; | |||||
case 0x235: Serial.print(" - AC Scroll"); break; | |||||
case 0x236: Serial.print(" - AC Pan Left"); break; | |||||
case 0x237: Serial.print(" - AC Pan Right"); break; | |||||
case 0x238: Serial.print(" - AC Pan"); break; | |||||
case 0x239: Serial.print(" - AC New Window"); break; | |||||
case 0x23A: Serial.print(" - AC Tile Horizontally"); break; | |||||
case 0x23B: Serial.print(" - AC Tile Vertically"); break; | |||||
case 0x23C: Serial.print(" - AC Format"); break; | |||||
} | |||||
} | |||||
Serial.println(); | |||||
} | |||||
void OnHIDExtrasRelease(uint32_t top, uint16_t key) | |||||
{ | |||||
Serial.print("HID ("); | |||||
Serial.print(top, HEX); | |||||
Serial.print(") key release:"); | |||||
Serial.println(key, HEX); | |||||
} | |||||
bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||||
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy | |||||
// to output to Serial. while still having Raw Hid... | |||||
if (usage == 0xffc90004) { | |||||
// Lets trim off trailing null characters. | |||||
while ((len > 0) && (data[len - 1] == 0)) { | |||||
len--; | |||||
} | |||||
if (len) { | |||||
Serial.print("RawHid Serial: "); | |||||
Serial.write(data, len); | |||||
} | |||||
} else { | |||||
Serial.print("RawHIDx data: "); | |||||
Serial.println(usage, HEX); | |||||
uint8_t len1 = len; | |||||
for(int j = 0; j < len; j++){ | |||||
user_axis[j] = data[j]; | |||||
} | |||||
/* | |||||
while (len) { | |||||
uint8_t cb = (len > 16) ? 16 : len; | |||||
const uint8_t *p = data; | |||||
uint8_t i; | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.printf("%02x ", *p++); | |||||
} | |||||
Serial.print(": "); | |||||
for (i = 0; i < cb; i++) { | |||||
Serial.write(((*data >= ' ') && (*data <= '~')) ? *data : '.'); | |||||
data++; | |||||
} | |||||
len -= cb; | |||||
Serial.println(); | |||||
} | |||||
*/ | |||||
} | |||||
for (uint8_t i = 0; i<9; i++) { | |||||
Serial.printf(" %d:%d", i, user_axis[i]); | |||||
} | |||||
Serial.println(); | |||||
Serial.print("Mouse: buttons = "); | |||||
Serial.print(user_axis[3]); | |||||
Serial.print(", mouseX = "); | |||||
Serial.print(user_axis[4]); | |||||
Serial.print(", mouseY = "); | |||||
Serial.print(user_axis[5]); | |||||
Serial.println(); | |||||
return true; | |||||
} |
} | } | ||||
uint8_t ltv; | uint8_t ltv; | ||||
uint8_t rtv; | uint8_t rtv; | ||||
switch (joysticks[joystick_index].joystickType) { | |||||
switch (joysticks[joystick_index].joystickType()) { | |||||
default: | default: | ||||
break; | break; | ||||
case JoystickController::PS4: | case JoystickController::PS4: | ||||
break; | break; | ||||
} | } | ||||
if (buttons != buttons_prev) { | if (buttons != buttons_prev) { | ||||
if (joysticks[joystick_index].joystickType == JoystickController::PS3) { | |||||
if (joysticks[joystick_index].joystickType() == JoystickController::PS3) { | |||||
joysticks[joystick_index].setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | joysticks[joystick_index].setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | ||||
} else { | } else { | ||||
uint8_t lr = (buttons & 1) ? 0xff : 0; | uint8_t lr = (buttons & 1) ? 0xff : 0; |
// 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); | |||||
#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}; | |||||
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | |||||
const char * driver_names[CNT_DEVICES] = {"Hub1", "joystick[0D]", "joystick[1D]", "joystick[2D]", "joystick[3D]", "HID1"}; | |||||
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; | |||||
int psAxis[64]; | |||||
//============================================================================= | |||||
// Setup | |||||
//============================================================================= | |||||
void setup() | |||||
{ | |||||
Serial1.begin(2000000); | |||||
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; | |||||
for (uint8_t i = 0; i<64; i++) { | |||||
psAxis[i] = joysticks[joystick_index].getAxis(i); | |||||
} | |||||
switch (joysticks[joystick_index].joystickType()) { | |||||
default: | |||||
break; | |||||
case JoystickController::PS4: | |||||
printAngles(); | |||||
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(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,50); | |||||
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 | |||||
uint8_t leds = 0; | |||||
if (buttons & 0x8000) leds = 1; //Srq | |||||
if (buttons & 0x2000) leds = 2; //Cir | |||||
if (buttons & 0x1000) leds = 4; //Tri | |||||
if (buttons & 0x4000) leds = 8; //X //Tri | |||||
joysticks[joystick_index].setLEDs(leds); | |||||
} 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); | |||||
} | |||||
} | |||||
} | |||||
} |
float gx, gy, gz; | |||||
float ax, ay, az; | |||||
float pitch, roll; | |||||
uint16_t xc, yc; | |||||
uint8_t isTouch; | |||||
int16_t xc_old, yc_old; | |||||
void printAngles(){ | |||||
//test function calls | |||||
float gx, gy, gz; | |||||
getAccel(ax, ay, az); | |||||
Serial.printf("Accel-g's: %f, %f, %f\n", ax, ay, az); | |||||
getGyro(gx, gy, gz); | |||||
Serial.printf("Gyro-deg/sec: %f, %f, %f\n", gx, gy, gz); | |||||
getAngles(pitch, roll); | |||||
Serial.printf("Pitch/Roll: %f, %f\n", pitch, roll); | |||||
getCoords(xc, yc, isTouch); | |||||
} | |||||
void getCoords(uint16_t &xc, uint16_t &yc, uint8_t &isTouch){ | |||||
//uint8_t finger = 0; //only getting finger 1 | |||||
uint8_t Id = 0; | |||||
// Trackpad touch 1: id, active, x, y | |||||
xc = ((psAxis[37] & 0x0f) << 8) | psAxis[36]; | |||||
yc = psAxis[38] << 4 | ((psAxis[37] & 0xf0) >> 4), | |||||
isTouch = psAxis[35] >> 7; | |||||
if(xc != xc_old || yc != yc_old){ | |||||
Serial.printf("Touch: %d, %d, %d, %d\n", psAxis[33], isTouch, xc, yc); | |||||
xc_old = xc; | |||||
yc_old = yc; | |||||
} | |||||
} | |||||
void getAccel( float &ax, float &ay, float &az){ | |||||
int accelx = (int16_t)(psAxis[20]<<8) | psAxis[19]; | |||||
int accelz = (int16_t)(psAxis[22]<<8) | psAxis[21]; | |||||
int accely = (int16_t)(psAxis[24]<<8) | psAxis[23]; | |||||
ax = (float) accelx/8192; | |||||
ay = (float) accely/8192; | |||||
az = (float) accelz/8192; | |||||
} | |||||
void getAngles(float &p, float &r){ | |||||
getAccel( ax, ay, az); | |||||
p = (atan2f(ay, az) + PI) * RAD_TO_DEG; | |||||
r = (atan2f(ax, az) + PI) * RAD_TO_DEG; | |||||
} | |||||
void getGyro(float &gx, float &gy, float &gz){ | |||||
int gyroy = (int16_t)(psAxis[14]<<8) | psAxis[13]; | |||||
int gyroz = (int16_t)(psAxis[16]<<8) | psAxis[15]; | |||||
int gyrox = (int16_t)(psAxis[18]<<8) | psAxis[17]; | |||||
gx = (float) gyrox * RAD_TO_DEG/1024; | |||||
gy = (float) gyroy * RAD_TO_DEG/1024; | |||||
gz = (float) gyroz * RAD_TO_DEG/1024; | |||||
} | |||||
USBHIDParser hid5(myusb); | USBHIDParser hid5(myusb); | ||||
MouseController mouse1(myusb); | MouseController mouse1(myusb); | ||||
JoystickController joystick1(myusb); | JoystickController joystick1(myusb); | ||||
//BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
BluetoothController bluet(myusb); // version assumes it already was paired | |||||
int user_axis[64]; | int user_axis[64]; | ||||
uint32_t buttons_prev = 0; | uint32_t buttons_prev = 0; | ||||
RawHIDController rawhid1(myusb); | RawHIDController rawhid1(myusb); | ||||
RawHIDController rawhid2(myusb, 0xffc90004); | RawHIDController rawhid2(myusb, 0xffc90004); | ||||
USBDriver *drivers[] = {&hub1, &hub2, &keyboard1, &keyboard2, &joystick1, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
USBDriver *drivers[] = {&hub1, &hub2,&keyboard1, &keyboard2, &joystick1, &bluet, &hid1, &hid2, &hid3, &hid4, &hid5}; | |||||
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | #define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | ||||
const char * driver_names[CNT_DEVICES] = {"Hub1", "Hub2", "KB1", "KB2", "JOY1D", "HID1", "HID2", "HID3", "HID4", "HID5"}; | |||||
const char * driver_names[CNT_DEVICES] = {"Hub1","Hub2", "KB1", "KB2", "JOY1D", "Bluet", "HID1" , "HID2", "HID3", "HID4", "HID5"}; | |||||
bool driver_active[CNT_DEVICES] = {false, false, false, false}; | bool driver_active[CNT_DEVICES] = {false, false, false, false}; | ||||
// Lets also look at HID Input devices | // Lets also look at HID Input devices | ||||
} | } | ||||
uint8_t ltv; | uint8_t ltv; | ||||
uint8_t rtv; | uint8_t rtv; | ||||
switch (joystick1.joystickType) { | |||||
switch (joystick1.joystickType()) { | |||||
default: | default: | ||||
break; | break; | ||||
case JoystickController::PS4: | case JoystickController::PS4: | ||||
break; | break; | ||||
} | } | ||||
if (buttons != buttons_prev) { | if (buttons != buttons_prev) { | ||||
if (joystick1.joystickType == JoystickController::PS3) { | |||||
if (joystick1.joystickType() == JoystickController::PS3) { | |||||
joystick1.setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | joystick1.setLEDs((buttons >> 12) & 0xf); // try to get to TRI/CIR/X/SQuare | ||||
} else { | } else { | ||||
uint8_t lr = (buttons & 1) ? 0xff : 0; | uint8_t lr = (buttons & 1) ? 0xff : 0; |
//============================================================================= | |||||
// Simple test viewer app for several of the USB devices on ili9341 display | |||||
// | |||||
// Currently requires the libraries | |||||
// ili9341_t3n that can be located: https://github.com/KurtE/ILI9341_t3n | |||||
// spin: https://github.com/KurtE/SPIN | |||||
// | |||||
// Teensy 3.6 Pins | |||||
// 8 = RST | |||||
// 9 = D/C | |||||
// 10 = CS | |||||
// | |||||
// Teensy 4.0 Beta Pins | |||||
// 23 = RST (Marked MCLK on T4 beta breakout) | |||||
// 10 = CS (Marked CS) | |||||
// 9 = DC (Marked MEMCS) | |||||
// | |||||
// This example is in the public domain | |||||
//============================================================================= | |||||
#include "USBHost_t36.h" | |||||
#include <ili9341_t3n_font_Arial.h> | |||||
#define TEENSY64 | |||||
//============================================================================= | |||||
// Connection configuration of ILI9341 LCD TFT | |||||
//============================================================================= | |||||
DMAMEM uint16_t frame_buffer[ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT]; | |||||
#if defined(__MK66FX1M0__) && !defined(TEENSY64) | |||||
#define TFT_RST 255 | |||||
#define TFT_DC 20 | |||||
#define TFT_CS 21 | |||||
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST); | |||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__) | |||||
// On Teensy 4 beta with Paul's breakout out: | |||||
// Using pins (MOSI, MISO, SCK which are labeled on Audio board breakout location | |||||
// which are not in the Normal processor positions | |||||
// Also DC=10(CS), CS=9(BCLK) and RST 23(MCLK) | |||||
#define TFT_RST 23 | |||||
#define TFT_DC 9 | |||||
#define TFT_CS 10 | |||||
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST); | |||||
#elif defined(TEENSY64) | |||||
#define TFT_RST 255 | |||||
#define TFT_DC 20 | |||||
#define TFT_CS 21 | |||||
#define TFT_SCK 14 | |||||
#define TFT_MISO 39 | |||||
#define TFT_MOSI 28 | |||||
ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO); | |||||
#else | |||||
#error "This example App will only work with Teensy 3.6 or Teensy 4." | |||||
#endif | |||||
//============================================================================= | |||||
// USB Host Ojbects | |||||
//============================================================================= | |||||
USBHost myusb; | |||||
USBHub hub1(myusb); | |||||
USBHub hub2(myusb); | |||||
KeyboardController keyboard1(myusb); | |||||
KeyboardController keyboard2(myusb); | |||||
USBHIDParser hid1(myusb); | |||||
USBHIDParser hid2(myusb); | |||||
USBHIDParser hid3(myusb); | |||||
USBHIDParser hid4(myusb); | |||||
USBHIDParser hid5(myusb); | |||||
MouseController mouse(myusb); | |||||
DigitizerController tablet(myusb); | |||||
JoystickController joystick(myusb); | |||||
BluetoothController bluet(myusb, true, "0000"); // Version does pairing to device | |||||
//BluetoothController bluet(myusb); // version assumes it already was paired | |||||
RawHIDController rawhid2(myusb); | |||||
// Lets only include in the lists The most top level type devices we wish to show information for. | |||||
//USBDriver *drivers[] = {&keyboard1, &keyboard2, &joystick}; | |||||
USBDriver *drivers[] = {&keyboard1, &keyboard2, &joystick, &bluet, &hid1, &hid2}; | |||||
#define CNT_DEVICES (sizeof(drivers)/sizeof(drivers[0])) | |||||
//const char * driver_names[CNT_DEVICES] = {"KB1", "KB2", "Joystick(device)"}; | |||||
const char * driver_names[CNT_DEVICES] = {"KB1", "KB2", "Joystick(device)", "Bluet", "HID1" , "HID2"}; | |||||
//bool driver_active[CNT_DEVICES] = {false, false, false}; | |||||
bool driver_active[CNT_DEVICES] = {false, false, false, false, false}; | |||||
// Lets also look at HID Input devices | |||||
USBHIDInput *hiddrivers[] = {&tablet, &joystick, &mouse, &rawhid2}; | |||||
#define CNT_HIDDEVICES (sizeof(hiddrivers)/sizeof(hiddrivers[0])) | |||||
const char * hid_driver_names[CNT_HIDDEVICES] = {"tablet", "joystick", "mouse", "RawHid2"}; | |||||
bool hid_driver_active[CNT_HIDDEVICES] = {false, false, false, false}; | |||||
BTHIDInput *bthiddrivers[] = {&joystick, &mouse}; | |||||
#define CNT_BTHIDDEVICES (sizeof(bthiddrivers)/sizeof(bthiddrivers[0])) | |||||
const char * bthid_driver_names[CNT_HIDDEVICES] = {"joystick", "mouse"}; | |||||
bool bthid_driver_active[CNT_HIDDEVICES] = {false, false}; | |||||
//============================================================================= | |||||
// Other state variables. | |||||
//============================================================================= | |||||
// Save away values for buttons, x, y, wheel, wheelh | |||||
int buttons_cur = 0; | |||||
int x_cur = 0, | |||||
y_cur = 0, | |||||
z_cur = 0; | |||||
int x2_cur = 0, | |||||
y2_cur = 0, | |||||
z2_cur = 0, | |||||
L1_cur = 0, | |||||
R1_cur = 0; | |||||
int wheel_cur = 0; | |||||
int wheelH_cur = 0; | |||||
int axis_cur[10]; | |||||
String p = "KB1"; | |||||
bool BT = 0; | |||||
int user_axis[64]; | |||||
uint32_t buttons_prev = 0; | |||||
uint32_t buttons; | |||||
bool show_changed_only = false; | |||||
bool new_device_detected = false; | |||||
int16_t y_position_after_device_info = 0; | |||||
uint8_t joystick_left_trigger_value = 0; | |||||
uint8_t joystick_right_trigger_value = 0; | |||||
uint64_t joystick_full_notify_mask = (uint64_t) - 1; | |||||
//============================================================================= | |||||
// Setup | |||||
//============================================================================= | |||||
void setup() | |||||
{ | |||||
Serial1.begin(2000000); | |||||
while (!Serial && millis() < 3000) ; // wait for Arduino Serial Monitor | |||||
Serial.println("\n\nUSB Host Testing"); | |||||
myusb.begin(); | |||||
rawhid2.attachReceive(OnReceiveHidData); | |||||
keyboard1.attachPress(OnPress); | |||||
keyboard2.attachPress(OnPress); | |||||
keyboard1.attachExtrasPress(OnHIDExtrasPress); | |||||
keyboard1.attachExtrasRelease(OnHIDExtrasRelease); | |||||
keyboard2.attachExtrasPress(OnHIDExtrasPress); | |||||
keyboard2.attachExtrasRelease(OnHIDExtrasRelease); | |||||
// The below forceBootProtocol will force which ever | |||||
// next keyboard that attaches to this device to be in boot protocol | |||||
// Only try this if you run into keyboard with issues. If this is a combined | |||||
// device like wireless mouse and keyboard this can cause mouse problems. | |||||
//keyboard1.forceBootProtocol(); | |||||
tft.begin(); | |||||
// explicitly set the frame buffer | |||||
tft.setFrameBuffer(frame_buffer); | |||||
delay(100); | |||||
tft.setRotation(3); // 180 | |||||
delay(100); | |||||
tft.fillScreen(ILI9341_BLACK); | |||||
tft.setTextColor(ILI9341_YELLOW); | |||||
tft.setTextSize(2); | |||||
tft.println("Waiting for Device..."); | |||||
tft.useFrameBuffer(true); | |||||
} | |||||
//============================================================================= | |||||
// Loop | |||||
//============================================================================= | |||||
void loop() | |||||
{ | |||||
myusb.Task(); | |||||
// Update the display with | |||||
UpdateActiveDeviceInfo(); | |||||
// Now lets try displaying Tablet data | |||||
ProcessTabletData(); | |||||
// And joystick data | |||||
ProcessJoystickData(); | |||||
// Process Mouse Data | |||||
ProcessMouseData(); | |||||
} | |||||
//============================================================================= | |||||
// UpdateActiveDeviceInfo | |||||
//============================================================================= | |||||
//============================================================================= | |||||
// UpdateActiveDeviceInfo | |||||
//============================================================================= | |||||
void UpdateActiveDeviceInfo() { | |||||
// First see if any high level devices | |||||
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 { | |||||
new_device_detected = true; | |||||
Serial.printf("*** Device %s %x:%x - connected ***\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct()); | |||||
driver_active[i] = true; | |||||
tft.fillScreen(ILI9341_BLACK); // clear the screen. | |||||
tft.setCursor(0, 0); | |||||
tft.setTextColor(ILI9341_YELLOW); | |||||
tft.setFont(Arial_12); | |||||
tft.printf("Device %s %x:%x\n", driver_names[i], drivers[i]->idVendor(), drivers[i]->idProduct()); | |||||
const uint8_t *psz = drivers[i]->manufacturer(); | |||||
if (psz && *psz) tft.printf(" manufacturer: %s\n", psz); | |||||
psz = drivers[i]->product(); | |||||
if (psz && *psz) tft.printf(" product: %s\n", psz); | |||||
psz = drivers[i]->serialNumber(); | |||||
if (psz && *psz) tft.printf(" Serial: %s\n", psz); | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
} | |||||
} | |||||
// Then Hid Devices | |||||
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 { | |||||
new_device_detected = true; | |||||
Serial.printf("*** HID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||||
hid_driver_active[i] = true; | |||||
tft.fillScreen(ILI9341_BLACK); // clear the screen. | |||||
tft.setCursor(0, 0); | |||||
tft.setTextColor(ILI9341_YELLOW); | |||||
tft.setFont(Arial_12); | |||||
tft.printf("HID Device %s %x:%x\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||||
const uint8_t *psz = hiddrivers[i]->manufacturer(); | |||||
if (psz && *psz) tft.printf(" manufacturer: %s\n", psz); | |||||
psz = hiddrivers[i]->product(); | |||||
if (psz && *psz) tft.printf(" product: %s\n", psz); | |||||
psz = hiddrivers[i]->serialNumber(); | |||||
if (psz && *psz) tft.printf(" Serial: %s\n", psz); | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
} | |||||
} | |||||
// Then Bluetooth devices | |||||
for (uint8_t i = 0; i < CNT_BTHIDDEVICES; i++) { | |||||
if (*bthiddrivers[i] != bthid_driver_active[i]) { | |||||
if (bthid_driver_active[i]) { | |||||
Serial.printf("*** BTHID Device %s - disconnected ***\n", hid_driver_names[i]); | |||||
bthid_driver_active[i] = false; | |||||
} else { | |||||
new_device_detected = true; | |||||
Serial.printf("*** BTHID Device %s %x:%x - connected ***\n", hid_driver_names[i], hiddrivers[i]->idVendor(), hiddrivers[i]->idProduct()); | |||||
bthid_driver_active[i] = true; | |||||
tft.fillScreen(ILI9341_BLACK); // clear the screen. | |||||
tft.setCursor(0, 0); | |||||
tft.setTextColor(ILI9341_YELLOW); | |||||
tft.setFont(Arial_12); | |||||
tft.printf("Bluetooth Device %s %x:%x\n", bthid_driver_names[i], bthiddrivers[i]->idVendor(), bthiddrivers[i]->idProduct()); | |||||
const uint8_t *psz = bthiddrivers[i]->manufacturer(); | |||||
if (psz && *psz) tft.printf(" manufacturer: %s\n", psz); | |||||
psz = bthiddrivers[i]->product(); | |||||
if (psz && *psz) tft.printf(" product: %s\n", psz); | |||||
psz = bthiddrivers[i]->serialNumber(); | |||||
if (psz && *psz) tft.printf(" Serial: %s\n", psz); | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
} | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// ProcessTabletData | |||||
//============================================================================= | |||||
void ProcessTabletData() { | |||||
if (tablet.available()) { | |||||
if (new_device_detected) { | |||||
// Lets display the titles. | |||||
int16_t x; | |||||
tft.getCursor(&x, &y_position_after_device_info); | |||||
tft.setTextColor(ILI9341_YELLOW); | |||||
tft.printf("Buttons:\nX:\nY:\nWheel:\nWheel H:\nAxis:"); | |||||
new_device_detected = false; | |||||
} | |||||
bool something_changed = false; | |||||
if (tablet.getButtons() != buttons_cur) { | |||||
buttons_cur = tablet.getButtons(); | |||||
something_changed = true; | |||||
} | |||||
if (tablet.getMouseX() != x_cur) { | |||||
x_cur = tablet.getMouseX(); | |||||
something_changed = true; | |||||
} | |||||
if (tablet.getMouseY() != y_cur) { | |||||
y_cur = tablet.getMouseY(); | |||||
something_changed = true; | |||||
} | |||||
if (tablet.getWheel() != wheel_cur) { | |||||
wheel_cur = tablet.getWheel(); | |||||
something_changed = true; | |||||
} | |||||
if (tablet.getWheelH() != wheelH_cur) { | |||||
wheelH_cur = tablet.getWheelH(); | |||||
something_changed = true; | |||||
} | |||||
// BUGBUG:: play with some Axis... | |||||
for (uint8_t i = 0; i < 10; i++) { | |||||
int axis = tablet.getAxis(i); | |||||
if (axis != axis_cur[i]) { | |||||
axis_cur[i] = axis; | |||||
something_changed = true; | |||||
} | |||||
} | |||||
if (something_changed) { | |||||
#define TABLET_DATA_X 100 | |||||
int16_t x, y2; | |||||
unsigned char line_space = Arial_12.line_space; | |||||
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); | |||||
//tft.setTextDatum(BR_DATUM); | |||||
int16_t y = y_position_after_device_info; | |||||
tft.setCursor(TABLET_DATA_X, y); | |||||
tft.printf("%d(%x)", buttons_cur, buttons_cur); | |||||
tft.getCursor(&x, &y2); | |||||
tft.fillRect(x, y, 320, line_space, ILI9341_BLACK); | |||||
y += line_space; OutputNumberField(TABLET_DATA_X, y, x_cur, 320); | |||||
y += line_space; OutputNumberField(TABLET_DATA_X, y, y_cur, 320); | |||||
y += line_space; OutputNumberField(TABLET_DATA_X, y, wheel_cur, 320); | |||||
y += line_space; OutputNumberField(TABLET_DATA_X, y, wheelH_cur, 320); | |||||
// Output other Axis data | |||||
for (uint8_t i = 0; i < 9; i += 3) { | |||||
y += line_space; | |||||
OutputNumberField(TABLET_DATA_X, y, axis_cur[i], 75); | |||||
OutputNumberField(TABLET_DATA_X + 75, y, axis_cur[i + 1], 75); | |||||
OutputNumberField(TABLET_DATA_X + 150, y, axis_cur[i + 2], 75); | |||||
} | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
tablet.digitizerDataClear(); | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// OutputNumberField | |||||
//============================================================================= | |||||
void OutputNumberField(int16_t x, int16_t y, int val, int16_t field_width) { | |||||
int16_t x2, y2; | |||||
tft.setCursor(x, y); | |||||
tft.print(val, DEC); tft.getCursor(&x2, &y2); | |||||
tft.fillRect(x2, y, field_width - (x2 - x), Arial_12.line_space, ILI9341_BLACK); | |||||
} | |||||
//============================================================================= | |||||
// ProcessMouseData | |||||
//============================================================================= | |||||
void ProcessMouseData() { | |||||
if (mouse.available()) { | |||||
if (new_device_detected) { | |||||
// Lets display the titles. | |||||
int16_t x; | |||||
tft.getCursor(&x, &y_position_after_device_info); | |||||
tft.setTextColor(ILI9341_YELLOW); | |||||
tft.printf("Buttons:\nX:\nY:\nWheel:\nWheel H:"); | |||||
new_device_detected = false; | |||||
} | |||||
bool something_changed = false; | |||||
if (mouse.getButtons() != buttons_cur) { | |||||
buttons_cur = mouse.getButtons(); | |||||
something_changed = true; | |||||
} | |||||
if (mouse.getMouseX() != x_cur) { | |||||
x_cur = mouse.getMouseX(); | |||||
something_changed = true; | |||||
} | |||||
if (mouse.getMouseY() != y_cur) { | |||||
y_cur = mouse.getMouseY(); | |||||
something_changed = true; | |||||
} | |||||
if (mouse.getWheel() != wheel_cur) { | |||||
wheel_cur = mouse.getWheel(); | |||||
something_changed = true; | |||||
} | |||||
if (mouse.getWheelH() != wheelH_cur) { | |||||
wheelH_cur = mouse.getWheelH(); | |||||
something_changed = true; | |||||
} | |||||
if (something_changed) { | |||||
#define MOUSE_DATA_X 100 | |||||
int16_t x, y2; | |||||
unsigned char line_space = Arial_12.line_space; | |||||
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); | |||||
//tft.setTextDatum(BR_DATUM); | |||||
int16_t y = y_position_after_device_info; | |||||
tft.setCursor(TABLET_DATA_X, y); | |||||
tft.printf("%d(%x)", buttons_cur, buttons_cur); | |||||
tft.getCursor(&x, &y2); | |||||
tft.fillRect(x, y, 320, line_space, ILI9341_BLACK); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, x_cur, 320); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, y_cur, 320); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, wheel_cur, 320); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, wheelH_cur, 320); | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
mouse.mouseDataClear(); | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// ProcessJoystickData | |||||
//============================================================================= | |||||
void ProcessJoystickData() { | |||||
if (joystick.available()) { | |||||
uint64_t axis_mask = joystick.axisMask(); | |||||
uint64_t axis_changed_mask = joystick.axisChangedMask(); | |||||
Serial.print("Joystick: buttons = "); | |||||
buttons = joystick.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, joystick.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, joystick.getAxis(i)); | |||||
} | |||||
} | |||||
} else { | |||||
for (uint8_t i = 0; axis_mask != 0; i++, axis_mask >>= 1) { | |||||
if (axis_mask & 1) { | |||||
Serial.printf(" %d:%d", i, joystick.getAxis(i)); | |||||
} | |||||
} | |||||
} | |||||
for (uint8_t i = 0; i < 64; i++) { | |||||
user_axis[i] = joystick.getAxis(i); | |||||
} | |||||
uint8_t ltv; | |||||
uint8_t rtv; | |||||
switch (joystick.joystickType()) { | |||||
default: | |||||
break; | |||||
case JoystickController::PS4: | |||||
ltv = joystick.getAxis(3); | |||||
rtv = joystick.getAxis(4); | |||||
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | |||||
joystick_left_trigger_value = ltv; | |||||
joystick_right_trigger_value = rtv; | |||||
joystick.setRumble(ltv, rtv); | |||||
} | |||||
break; | |||||
case JoystickController::PS3: | |||||
ltv = joystick.getAxis(18); | |||||
rtv = joystick.getAxis(19); | |||||
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | |||||
joystick_left_trigger_value = ltv; | |||||
joystick_right_trigger_value = rtv; | |||||
joystick.setRumble(ltv, rtv, 50); | |||||
} | |||||
break; | |||||
case JoystickController::XBOXONE: | |||||
case JoystickController::XBOX360: | |||||
ltv = joystick.getAxis(4); | |||||
rtv = joystick.getAxis(5); | |||||
if ((ltv != joystick_left_trigger_value) || (rtv != joystick_right_trigger_value)) { | |||||
joystick_left_trigger_value = ltv; | |||||
joystick_right_trigger_value = rtv; | |||||
joystick.setRumble(ltv, rtv); | |||||
Serial.printf(" Set Rumble %d %d", ltv, rtv); | |||||
} | |||||
break; | |||||
} | |||||
if (buttons != buttons_cur) { | |||||
if (joystick.joystickType() == JoystickController::PS3) { | |||||
joystick.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; | |||||
joystick.setLEDs(lr, lg, lb); | |||||
} | |||||
buttons_cur = buttons; | |||||
} | |||||
Serial.println(); | |||||
tft_JoystickData(); | |||||
joystick.joystickDataClear(); | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// TFT_joystick | |||||
//============================================================================= | |||||
void tft_JoystickData() { | |||||
if (new_device_detected) { | |||||
// Lets display the titles. | |||||
int16_t x; | |||||
tft.getCursor(&x, &y_position_after_device_info); | |||||
tft.setTextColor(ILI9341_YELLOW); | |||||
tft.printf("Buttons:\nX:\nY:\nX2\nY2(Z):\nL1:\nR1:\nHAT:"); | |||||
new_device_detected = false; | |||||
} | |||||
bool something_changed = false; | |||||
if (buttons != buttons_prev) { //buttons | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[0] != x_cur) { //xL | |||||
x_cur = user_axis[0]; | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[1] != y_cur) { //yL | |||||
y_cur = user_axis[1]; | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[9] != wheel_cur) { //Hat | |||||
wheel_cur = user_axis[9]; | |||||
something_changed = true; | |||||
} | |||||
//Second Axis | |||||
if (user_axis[2] != x2_cur) { //xR | |||||
x2_cur = user_axis[2]; | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[5] != y2_cur) { //yR or z-axis | |||||
y2_cur = user_axis[5]; | |||||
something_changed = true; | |||||
} | |||||
//Rumble Axis | |||||
switch (joystick.joystickType()) { | |||||
case JoystickController::XBOXONE: | |||||
case JoystickController::XBOX360: | |||||
case JoystickController::PS4: | |||||
if (user_axis[3] != L1_cur) { //xR | |||||
L1_cur = user_axis[3]; | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[4] != R1_cur) { //yR or z-axis | |||||
R1_cur = user_axis[4]; | |||||
something_changed = true; | |||||
} | |||||
break; | |||||
case JoystickController::PS3: | |||||
if (user_axis[18] != L1_cur) { //xR | |||||
L1_cur = user_axis[18]; | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[19] != R1_cur) { //yR or z-axis | |||||
R1_cur = user_axis[19]; | |||||
something_changed = true; | |||||
} | |||||
break; | |||||
} | |||||
if (something_changed) { | |||||
#define MOUSE_DATA_X 100 | |||||
int16_t x, y2; | |||||
unsigned char line_space = Arial_12.line_space; | |||||
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); | |||||
//tft.setTextDatum(BR_DATUM); | |||||
int16_t y = y_position_after_device_info; | |||||
tft.setCursor(TABLET_DATA_X, y); | |||||
tft.printf("%d(%x)", buttons, buttons); | |||||
tft.getCursor(&x, &y2); | |||||
tft.fillRect(x, y, 320, line_space, ILI9341_BLACK); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, x_cur, 320); //x | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, y_cur, 320); //y | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, x2_cur, 320); //x2(z) | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, y2_cur, 320); //y2 | |||||
switch (joystick.joystickType()) { | |||||
case JoystickController::PS4: | |||||
case JoystickController::PS3: | |||||
case JoystickController::XBOXONE: | |||||
case JoystickController::XBOX360: | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, L1_cur, 320); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, R1_cur, 320); | |||||
break; | |||||
default: | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, 0, 320); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, 0, 320); | |||||
y += line_space; OutputNumberField(MOUSE_DATA_X, y, wheel_cur, 320); //hat | |||||
break; | |||||
} | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
} | |||||
//============================================================================= | |||||
// ProcessMouseData | |||||
//============================================================================= | |||||
bool OnReceiveHidData(uint32_t usage, const uint8_t *data, uint32_t len) { | |||||
// Called for maybe both HIDS for rawhid basic test. One is for the Teensy | |||||
// to output to Serial. while still having Raw Hid... | |||||
if (usage == 0xFF000080 | |||||
) { | |||||
//Serial.print("RawHIDx data: "); | |||||
//Serial.println(usage, HEX); | |||||
for (uint32_t j = 0; j < len; j++) { | |||||
user_axis[j] = data[j]; | |||||
} | |||||
bool something_changed = false; | |||||
if (user_axis[3] != buttons_cur) { | |||||
buttons_cur = user_axis[3]; | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[4] != x_cur) { | |||||
x_cur = user_axis[4]; | |||||
something_changed = true; | |||||
} | |||||
if (user_axis[5] != y_cur) { | |||||
y_cur = user_axis[5]; | |||||
something_changed = true; | |||||
} | |||||
if (tablet.getWheel() != wheel_cur) { | |||||
wheel_cur = 0; | |||||
something_changed = true; | |||||
} | |||||
if (tablet.getWheelH() != wheelH_cur) { | |||||
wheelH_cur = 0; | |||||
something_changed = true; | |||||
} | |||||
if (something_changed) { | |||||
tft.fillRect(45, 197, 240, 20, ILI9341_RED); | |||||
tft.drawNumber(buttons_cur, 50, 200); | |||||
tft.drawNumber(x_cur, 100, 200); | |||||
tft.drawNumber(y_cur, 150, 200); | |||||
tft.drawNumber(wheel_cur, 200, 200); | |||||
tft.drawNumber(wheelH_cur, 250, 200); | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
} else { | |||||
// Lets trim off trailing null characters. | |||||
while ((len > 0) && (data[len - 1] == 0)) { | |||||
len--; | |||||
} | |||||
if (len) { | |||||
//Serial.print("RawHid Serial: "); | |||||
//Serial.write(data, len); | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
void MaybeSetupTextScrollArea() | |||||
{ | |||||
if (new_device_detected) { | |||||
BT = 0; | |||||
new_device_detected = false; | |||||
} | |||||
if (BT == 0) { | |||||
tft.enableScroll(); | |||||
tft.setScrollTextArea(20, 70, 280, 140); | |||||
tft.setScrollBackgroundColor(ILI9341_GREEN); | |||||
tft.setFont(Arial_11); | |||||
tft.setTextColor(ILI9341_BLACK); | |||||
tft.setCursor(20, 70); | |||||
BT = 1; | |||||
} | |||||
} | |||||
void OnPress(int key) | |||||
{ | |||||
MaybeSetupTextScrollArea(); | |||||
tft.print("key: "); | |||||
switch (key) { | |||||
case KEYD_UP : tft.print("UP"); break; | |||||
case KEYD_DOWN : tft.print("DN"); break; | |||||
case KEYD_LEFT : tft.print("LEFT"); break; | |||||
case KEYD_RIGHT : tft.print("RIGHT"); break; | |||||
case KEYD_INSERT : tft.print("Ins"); break; | |||||
case KEYD_DELETE : tft.print("Del"); break; | |||||
case KEYD_PAGE_UP : tft.print("PUP"); break; | |||||
case KEYD_PAGE_DOWN: tft.print("PDN"); break; | |||||
case KEYD_HOME : tft.print("HOME"); break; | |||||
case KEYD_END : tft.print("END"); break; | |||||
case KEYD_F1 : tft.print("F1"); break; | |||||
case KEYD_F2 : tft.print("F2"); break; | |||||
case KEYD_F3 : tft.print("F3"); break; | |||||
case KEYD_F4 : tft.print("F4"); break; | |||||
case KEYD_F5 : tft.print("F5"); break; | |||||
case KEYD_F6 : tft.print("F6"); break; | |||||
case KEYD_F7 : tft.print("F7"); break; | |||||
case KEYD_F8 : tft.print("F8"); break; | |||||
case KEYD_F9 : tft.print("F9"); break; | |||||
case KEYD_F10 : tft.print("F10"); break; | |||||
case KEYD_F11 : tft.print("F11"); break; | |||||
case KEYD_F12 : tft.print("F12"); break; | |||||
default: tft.print((char)key); break; | |||||
} | |||||
tft.print("' "); | |||||
tft.print(key); | |||||
tft.print(" MOD: "); | |||||
if (keyboard1) { | |||||
tft.print(keyboard1.getModifiers(), HEX); | |||||
tft.print(" OEM: "); | |||||
tft.print(keyboard1.getOemKey(), HEX); | |||||
tft.print(" LEDS: "); | |||||
tft.println(keyboard1.LEDS(), HEX); | |||||
} else { | |||||
tft.print(keyboard2.getModifiers(), HEX); | |||||
tft.print(" OEM: "); | |||||
tft.print(keyboard2.getOemKey(), HEX); | |||||
tft.print(" LEDS: "); | |||||
tft.println(keyboard2.LEDS(), HEX); | |||||
} | |||||
//Serial.print("key "); | |||||
//Serial.print((char)keyboard1.getKey()); | |||||
//Serial.print(" "); | |||||
//Serial.print((char)keyboard2.getKey()); | |||||
//Serial.println(); | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
void OnHIDExtrasPress(uint32_t top, uint16_t key) | |||||
{ | |||||
MaybeSetupTextScrollArea(); | |||||
tft.print("HID ("); | |||||
tft.print(top, HEX); | |||||
tft.print(") key press:"); | |||||
tft.print(key, HEX); | |||||
if (top == 0xc0000) { | |||||
switch (key) { | |||||
case 0x20 : tft.print(" - +10"); break; | |||||
case 0x21 : tft.print(" - +100"); break; | |||||
case 0x22 : tft.print(" - AM/PM"); break; | |||||
case 0x30 : tft.print(" - Power"); break; | |||||
case 0x31 : tft.print(" - Reset"); break; | |||||
case 0x32 : tft.print(" - Sleep"); break; | |||||
case 0x33 : tft.print(" - Sleep After"); break; | |||||
case 0x34 : tft.print(" - Sleep Mode"); break; | |||||
case 0x35 : tft.print(" - Illumination"); break; | |||||
case 0x36 : tft.print(" - Function Buttons"); break; | |||||
case 0x40 : tft.print(" - Menu"); break; | |||||
case 0x41 : tft.print(" - Menu Pick"); break; | |||||
case 0x42 : tft.print(" - Menu Up"); break; | |||||
case 0x43 : tft.print(" - Menu Down"); break; | |||||
case 0x44 : tft.print(" - Menu Left"); break; | |||||
case 0x45 : tft.print(" - Menu Right"); break; | |||||
case 0x46 : tft.print(" - Menu Escape"); break; | |||||
case 0x47 : tft.print(" - Menu Value Increase"); break; | |||||
case 0x48 : tft.print(" - Menu Value Decrease"); break; | |||||
case 0x60 : tft.print(" - Data On Screen"); break; | |||||
case 0x61 : tft.print(" - Closed Caption"); break; | |||||
case 0x62 : tft.print(" - Closed Caption Select"); break; | |||||
case 0x63 : tft.print(" - VCR/TV"); break; | |||||
case 0x64 : tft.print(" - Broadcast Mode"); break; | |||||
case 0x65 : tft.print(" - Snapshot"); break; | |||||
case 0x66 : tft.print(" - Still"); break; | |||||
case 0x80 : tft.print(" - Selection"); break; | |||||
case 0x81 : tft.print(" - Assign Selection"); break; | |||||
case 0x82 : tft.print(" - Mode Step"); break; | |||||
case 0x83 : tft.print(" - Recall Last"); break; | |||||
case 0x84 : tft.print(" - Enter Channel"); break; | |||||
case 0x85 : tft.print(" - Order Movie"); break; | |||||
case 0x86 : tft.print(" - Channel"); break; | |||||
case 0x87 : tft.print(" - Media Selection"); break; | |||||
case 0x88 : tft.print(" - Media Select Computer"); break; | |||||
case 0x89 : tft.print(" - Media Select TV"); break; | |||||
case 0x8A : tft.print(" - Media Select WWW"); break; | |||||
case 0x8B : tft.print(" - Media Select DVD"); break; | |||||
case 0x8C : tft.print(" - Media Select Telephone"); break; | |||||
case 0x8D : tft.print(" - Media Select Program Guide"); break; | |||||
case 0x8E : tft.print(" - Media Select Video Phone"); break; | |||||
case 0x8F : tft.print(" - Media Select Games"); break; | |||||
case 0x90 : tft.print(" - Media Select Messages"); break; | |||||
case 0x91 : tft.print(" - Media Select CD"); break; | |||||
case 0x92 : tft.print(" - Media Select VCR"); break; | |||||
case 0x93 : tft.print(" - Media Select Tuner"); break; | |||||
case 0x94 : tft.print(" - Quit"); break; | |||||
case 0x95 : tft.print(" - Help"); break; | |||||
case 0x96 : tft.print(" - Media Select Tape"); break; | |||||
case 0x97 : tft.print(" - Media Select Cable"); break; | |||||
case 0x98 : tft.print(" - Media Select Satellite"); break; | |||||
case 0x99 : tft.print(" - Media Select Security"); break; | |||||
case 0x9A : tft.print(" - Media Select Home"); break; | |||||
case 0x9B : tft.print(" - Media Select Call"); break; | |||||
case 0x9C : tft.print(" - Channel Increment"); break; | |||||
case 0x9D : tft.print(" - Channel Decrement"); break; | |||||
case 0x9E : tft.print(" - Media Select SAP"); break; | |||||
case 0xA0 : tft.print(" - VCR Plus"); break; | |||||
case 0xA1 : tft.print(" - Once"); break; | |||||
case 0xA2 : tft.print(" - Daily"); break; | |||||
case 0xA3 : tft.print(" - Weekly"); break; | |||||
case 0xA4 : tft.print(" - Monthly"); break; | |||||
case 0xB0 : tft.print(" - Play"); break; | |||||
case 0xB1 : tft.print(" - Pause"); break; | |||||
case 0xB2 : tft.print(" - Record"); break; | |||||
case 0xB3 : tft.print(" - Fast Forward"); break; | |||||
case 0xB4 : tft.print(" - Rewind"); break; | |||||
case 0xB5 : tft.print(" - Scan Next Track"); break; | |||||
case 0xB6 : tft.print(" - Scan Previous Track"); break; | |||||
case 0xB7 : tft.print(" - Stop"); break; | |||||
case 0xB8 : tft.print(" - Eject"); break; | |||||
case 0xB9 : tft.print(" - Random Play"); break; | |||||
case 0xBA : tft.print(" - Select DisC"); break; | |||||
case 0xBB : tft.print(" - Enter Disc"); break; | |||||
case 0xBC : tft.print(" - Repeat"); break; | |||||
case 0xBD : tft.print(" - Tracking"); break; | |||||
case 0xBE : tft.print(" - Track Normal"); break; | |||||
case 0xBF : tft.print(" - Slow Tracking"); break; | |||||
case 0xC0 : tft.print(" - Frame Forward"); break; | |||||
case 0xC1 : tft.print(" - Frame Back"); break; | |||||
case 0xC2 : tft.print(" - Mark"); break; | |||||
case 0xC3 : tft.print(" - Clear Mark"); break; | |||||
case 0xC4 : tft.print(" - Repeat From Mark"); break; | |||||
case 0xC5 : tft.print(" - Return To Mark"); break; | |||||
case 0xC6 : tft.print(" - Search Mark Forward"); break; | |||||
case 0xC7 : tft.print(" - Search Mark Backwards"); break; | |||||
case 0xC8 : tft.print(" - Counter Reset"); break; | |||||
case 0xC9 : tft.print(" - Show Counter"); break; | |||||
case 0xCA : tft.print(" - Tracking Increment"); break; | |||||
case 0xCB : tft.print(" - Tracking Decrement"); break; | |||||
case 0xCD : tft.print(" - Pause/Continue"); break; | |||||
case 0xE0 : tft.print(" - Volume"); break; | |||||
case 0xE1 : tft.print(" - Balance"); break; | |||||
case 0xE2 : tft.print(" - Mute"); break; | |||||
case 0xE3 : tft.print(" - Bass"); break; | |||||
case 0xE4 : tft.print(" - Treble"); break; | |||||
case 0xE5 : tft.print(" - Bass Boost"); break; | |||||
case 0xE6 : tft.print(" - Surround Mode"); break; | |||||
case 0xE7 : tft.print(" - Loudness"); break; | |||||
case 0xE8 : tft.print(" - MPX"); break; | |||||
case 0xE9 : tft.print(" - Volume Up"); break; | |||||
case 0xEA : tft.print(" - Volume Down"); break; | |||||
case 0xF0 : tft.print(" - Speed Select"); break; | |||||
case 0xF1 : tft.print(" - Playback Speed"); break; | |||||
case 0xF2 : tft.print(" - Standard Play"); break; | |||||
case 0xF3 : tft.print(" - Long Play"); break; | |||||
case 0xF4 : tft.print(" - Extended Play"); break; | |||||
case 0xF5 : tft.print(" - Slow"); break; | |||||
case 0x100: tft.print(" - Fan Enable"); break; | |||||
case 0x101: tft.print(" - Fan Speed"); break; | |||||
case 0x102: tft.print(" - Light"); break; | |||||
case 0x103: tft.print(" - Light Illumination Level"); break; | |||||
case 0x104: tft.print(" - Climate Control Enable"); break; | |||||
case 0x105: tft.print(" - Room Temperature"); break; | |||||
case 0x106: tft.print(" - Security Enable"); break; | |||||
case 0x107: tft.print(" - Fire Alarm"); break; | |||||
case 0x108: tft.print(" - Police Alarm"); break; | |||||
case 0x150: tft.print(" - Balance Right"); break; | |||||
case 0x151: tft.print(" - Balance Left"); break; | |||||
case 0x152: tft.print(" - Bass Increment"); break; | |||||
case 0x153: tft.print(" - Bass Decrement"); break; | |||||
case 0x154: tft.print(" - Treble Increment"); break; | |||||
case 0x155: tft.print(" - Treble Decrement"); break; | |||||
case 0x160: tft.print(" - Speaker System"); break; | |||||
case 0x161: tft.print(" - Channel Left"); break; | |||||
case 0x162: tft.print(" - Channel Right"); break; | |||||
case 0x163: tft.print(" - Channel Center"); break; | |||||
case 0x164: tft.print(" - Channel Front"); break; | |||||
case 0x165: tft.print(" - Channel Center Front"); break; | |||||
case 0x166: tft.print(" - Channel Side"); break; | |||||
case 0x167: tft.print(" - Channel Surround"); break; | |||||
case 0x168: tft.print(" - Channel Low Frequency Enhancement"); break; | |||||
case 0x169: tft.print(" - Channel Top"); break; | |||||
case 0x16A: tft.print(" - Channel Unknown"); break; | |||||
case 0x170: tft.print(" - Sub-channel"); break; | |||||
case 0x171: tft.print(" - Sub-channel Increment"); break; | |||||
case 0x172: tft.print(" - Sub-channel Decrement"); break; | |||||
case 0x173: tft.print(" - Alternate Audio Increment"); break; | |||||
case 0x174: tft.print(" - Alternate Audio Decrement"); break; | |||||
case 0x180: tft.print(" - Application Launch Buttons"); break; | |||||
case 0x181: tft.print(" - AL Launch Button Configuration Tool"); break; | |||||
case 0x182: tft.print(" - AL Programmable Button Configuration"); break; | |||||
case 0x183: tft.print(" - AL Consumer Control Configuration"); break; | |||||
case 0x184: tft.print(" - AL Word Processor"); break; | |||||
case 0x185: tft.print(" - AL Text Editor"); break; | |||||
case 0x186: tft.print(" - AL Spreadsheet"); break; | |||||
case 0x187: tft.print(" - AL Graphics Editor"); break; | |||||
case 0x188: tft.print(" - AL Presentation App"); break; | |||||
case 0x189: tft.print(" - AL Database App"); break; | |||||
case 0x18A: tft.print(" - AL Email Reader"); break; | |||||
case 0x18B: tft.print(" - AL Newsreader"); break; | |||||
case 0x18C: tft.print(" - AL Voicemail"); break; | |||||
case 0x18D: tft.print(" - AL Contacts/Address Book"); break; | |||||
case 0x18E: tft.print(" - AL Calendar/Schedule"); break; | |||||
case 0x18F: tft.print(" - AL Task/Project Manager"); break; | |||||
case 0x190: tft.print(" - AL Log/Journal/Timecard"); break; | |||||
case 0x191: tft.print(" - AL Checkbook/Finance"); break; | |||||
case 0x192: tft.print(" - AL Calculator"); break; | |||||
case 0x193: tft.print(" - AL A/V Capture/Playback"); break; | |||||
case 0x194: tft.print(" - AL Local Machine Browser"); break; | |||||
case 0x195: tft.print(" - AL LAN/WAN Browser"); break; | |||||
case 0x196: tft.print(" - AL Internet Browser"); break; | |||||
case 0x197: tft.print(" - AL Remote Networking/ISP Connect"); break; | |||||
case 0x198: tft.print(" - AL Network Conference"); break; | |||||
case 0x199: tft.print(" - AL Network Chat"); break; | |||||
case 0x19A: tft.print(" - AL Telephony/Dialer"); break; | |||||
case 0x19B: tft.print(" - AL Logon"); break; | |||||
case 0x19C: tft.print(" - AL Logoff"); break; | |||||
case 0x19D: tft.print(" - AL Logon/Logoff"); break; | |||||
case 0x19E: tft.print(" - AL Terminal Lock/Screensaver"); break; | |||||
case 0x19F: tft.print(" - AL Control Panel"); break; | |||||
case 0x1A0: tft.print(" - AL Command Line Processor/Run"); break; | |||||
case 0x1A1: tft.print(" - AL Process/Task Manager"); break; | |||||
case 0x1A2: tft.print(" - AL Select Tast/Application"); break; | |||||
case 0x1A3: tft.print(" - AL Next Task/Application"); break; | |||||
case 0x1A4: tft.print(" - AL Previous Task/Application"); break; | |||||
case 0x1A5: tft.print(" - AL Preemptive Halt Task/Application"); break; | |||||
case 0x200: tft.print(" - Generic GUI Application Controls"); break; | |||||
case 0x201: tft.print(" - AC New"); break; | |||||
case 0x202: tft.print(" - AC Open"); break; | |||||
case 0x203: tft.print(" - AC Close"); break; | |||||
case 0x204: tft.print(" - AC Exit"); break; | |||||
case 0x205: tft.print(" - AC Maximize"); break; | |||||
case 0x206: tft.print(" - AC Minimize"); break; | |||||
case 0x207: tft.print(" - AC Save"); break; | |||||
case 0x208: tft.print(" - AC Print"); break; | |||||
case 0x209: tft.print(" - AC Properties"); break; | |||||
case 0x21A: tft.print(" - AC Undo"); break; | |||||
case 0x21B: tft.print(" - AC Copy"); break; | |||||
case 0x21C: tft.print(" - AC Cut"); break; | |||||
case 0x21D: tft.print(" - AC Paste"); break; | |||||
case 0x21E: tft.print(" - AC Select All"); break; | |||||
case 0x21F: tft.print(" - AC Find"); break; | |||||
case 0x220: tft.print(" - AC Find and Replace"); break; | |||||
case 0x221: tft.print(" - AC Search"); break; | |||||
case 0x222: tft.print(" - AC Go To"); break; | |||||
case 0x223: tft.print(" - AC Home"); break; | |||||
case 0x224: tft.print(" - AC Back"); break; | |||||
case 0x225: tft.print(" - AC Forward"); break; | |||||
case 0x226: tft.print(" - AC Stop"); break; | |||||
case 0x227: tft.print(" - AC Refresh"); break; | |||||
case 0x228: tft.print(" - AC Previous Link"); break; | |||||
case 0x229: tft.print(" - AC Next Link"); break; | |||||
case 0x22A: tft.print(" - AC Bookmarks"); break; | |||||
case 0x22B: tft.print(" - AC History"); break; | |||||
case 0x22C: tft.print(" - AC Subscriptions"); break; | |||||
case 0x22D: tft.print(" - AC Zoom In"); break; | |||||
case 0x22E: tft.print(" - AC Zoom Out"); break; | |||||
case 0x22F: tft.print(" - AC Zoom"); break; | |||||
case 0x230: tft.print(" - AC Full Screen View"); break; | |||||
case 0x231: tft.print(" - AC Normal View"); break; | |||||
case 0x232: tft.print(" - AC View Toggle"); break; | |||||
case 0x233: tft.print(" - AC Scroll Up"); break; | |||||
case 0x234: tft.print(" - AC Scroll Down"); break; | |||||
case 0x235: tft.print(" - AC Scroll"); break; | |||||
case 0x236: tft.print(" - AC Pan Left"); break; | |||||
case 0x237: tft.print(" - AC Pan Right"); break; | |||||
case 0x238: tft.print(" - AC Pan"); break; | |||||
case 0x239: tft.print(" - AC New Window"); break; | |||||
case 0x23A: tft.print(" - AC Tile Horizontally"); break; | |||||
case 0x23B: tft.print(" - AC Tile Vertically"); break; | |||||
case 0x23C: tft.print(" - AC Format"); break; | |||||
} | |||||
} | |||||
tft.println(); | |||||
tft.updateScreen(); // update the screen now | |||||
} | |||||
void OnHIDExtrasRelease(uint32_t top, uint16_t key) | |||||
{ | |||||
tft.print("HID ("); | |||||
tft.print(top, HEX); | |||||
tft.print(") key release:"); | |||||
tft.println(key, HEX); | |||||
} |
println(" got report descriptor"); | println(" got report descriptor"); | ||||
parse(); | parse(); | ||||
queue_Data_Transfer(in_pipe, report, in_size, this); | queue_Data_Transfer(in_pipe, report, in_size, this); | ||||
if (device->idVendor == 0x054C && device->idProduct == 0x0268) { | |||||
if (device->idVendor == 0x054C && | |||||
((device->idProduct == 0x0268) || (device->idProduct == 0x042F)/* || (device->idProduct == 0x03D5)*/)) { | |||||
println("send special PS3 feature command"); | println("send special PS3 feature command"); | ||||
mk_setup(setup, 0x21, 9, 0x03F4, 0, 4); // ps3 tell to send report 1? | mk_setup(setup, 0x21, 9, 0x03F4, 0, 4); // ps3 tell to send report 1? | ||||
static uint8_t ps3_feature_F4_report[] = {0x42, 0x0c, 0x00, 0x00}; | static uint8_t ps3_feature_F4_report[] = {0x42, 0x0c, 0x00, 0x00}; | ||||
// Called when the HID device sends a report | // Called when the HID device sends a report | ||||
void USBHIDParser::in_data(const Transfer_t *transfer) | void USBHIDParser::in_data(const Transfer_t *transfer) | ||||
{ | { | ||||
/*Serial.printf("HID: "); | |||||
/*USBHDBGSerial.printf("HID: "); | |||||
uint8_t *pb = (uint8_t*)transfer->buffer; | uint8_t *pb = (uint8_t*)transfer->buffer; | ||||
for (uint8_t i = 0; i < transfer->length; i++) { | for (uint8_t i = 0; i < transfer->length; i++) { | ||||
Serial.printf("%x ",pb[i]); | |||||
USBHDBGSerial.printf("%x ",pb[i]); | |||||
} | } | ||||
Serial.printf("\n"); */ | |||||
USBHDBGSerial.printf("\n"); */ | |||||
print("HID: "); | print("HID: "); | ||||
print(use_report_id); | print(use_report_id); | ||||
} | } | ||||
driver = driver->next; | driver = driver->next; | ||||
} | } | ||||
println("No Driver claimed topusage: ", topusage, HEX); | |||||
return NULL; | return NULL; | ||||
} | } | ||||
} | } | ||||
uminmax = true; | 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, | |||||
//USBHDBGSerial.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]); | // report_count, usage_count, uminmax, usage[0], usage[1]); | ||||
for (uint32_t i=0; i < report_count; i++) { | for (uint32_t i=0; i < report_count; i++) { | ||||
uint32_t u; | uint32_t u; |
#define print USBHost::print_ | #define print USBHost::print_ | ||||
#define println USBHost::println_ | #define println USBHost::println_ | ||||
//#define DEBUG_JOYSTICK | |||||
#ifdef DEBUG_JOYSTICK | |||||
#define DBGPrintf USBHDBGSerial.printf | |||||
#else | |||||
#define DBGPrintf(...) | |||||
#endif | |||||
// PID/VID to joystick mapping - Only the XBOXOne is used to claim the USB interface directly, | // 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 | // The others are used after claim-hid code to know which one we have and to use it for | ||||
// doing other features. | // doing other features. | ||||
{ 0x045e, 0x02ea, XBOXONE, false },{ 0x045e, 0x02dd, XBOXONE, false }, | { 0x045e, 0x02ea, XBOXONE, false },{ 0x045e, 0x02dd, XBOXONE, false }, | ||||
{ 0x045e, 0x0719, XBOX360, false}, | { 0x045e, 0x0719, XBOX360, false}, | ||||
{ 0x054C, 0x0268, PS3, true}, | { 0x054C, 0x0268, PS3, true}, | ||||
{ 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true } | |||||
{ 0x054C, 0x042F, PS3, true}, // PS3 Navigation controller | |||||
{ 0x054C, 0x03D5, PS3_MOTION, true}, // PS3 Motion controller | |||||
{ 0x054C, 0x05C4, PS4, true}, {0x054C, 0x09CC, PS4, true }, | |||||
{ 0x046D, 0xC626, SpaceNav, true}, // 3d Connextion Space Navigator, 0x10008 | |||||
{ 0x046D, 0xC628, SpaceNav, true} // 3d Connextion Space Navigator, 0x10008 | |||||
}; | }; | ||||
contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | ||||
driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
USBHIDParser::driver_ready_for_hid_collection(this); | USBHIDParser::driver_ready_for_hid_collection(this); | ||||
BluetoothController::driver_ready_for_bluetooth(this); | |||||
} | } | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
const uint8_t *JoystickController::manufacturer() | const uint8_t *JoystickController::manufacturer() | ||||
{ | { | ||||
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | ||||
//if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | |||||
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
{ | { | ||||
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | ||||
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | ||||
if (btdevice != nullptr) return remote_name_; | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
rumble_rValue_ = rValue; | rumble_rValue_ = rValue; | ||||
rumble_timeout_ = timeout; | rumble_timeout_ = timeout; | ||||
switch (joystickType) { | |||||
switch (joystickType_) { | |||||
default: | default: | ||||
break; | break; | ||||
case PS3: | case PS3: | ||||
return transmitPS3UserFeedbackMsg(); | return transmitPS3UserFeedbackMsg(); | ||||
case PS3_MOTION: | |||||
return transmitPS3MotionUserFeedbackMsg(); | |||||
case PS4: | case PS4: | ||||
return transmitPS4UserFeedbackMsg(); | return transmitPS4UserFeedbackMsg(); | ||||
case XBOXONE: | case XBOXONE: | ||||
return false; | return false; | ||||
} | } | ||||
bool JoystickController::setLEDs(uint8_t lr, uint8_t lg, uint8_t lb) | 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 | // Need to know which joystick we are on. Start off with XBox support - maybe need to add some enum value for the known | ||||
leds_[1] = lg; | leds_[1] = lg; | ||||
leds_[2] = lb; | leds_[2] = lb; | ||||
switch (joystickType) { | |||||
switch (joystickType_) { | |||||
case PS3: | case PS3: | ||||
return transmitPS3UserFeedbackMsg(); | return transmitPS3UserFeedbackMsg(); | ||||
case PS3_MOTION: | |||||
return transmitPS3MotionUserFeedbackMsg(); | |||||
case PS4: | case PS4: | ||||
return transmitPS4UserFeedbackMsg(); | return transmitPS4UserFeedbackMsg(); | ||||
case XBOX360: | case XBOX360: | ||||
} | } | ||||
bool JoystickController::transmitPS4UserFeedbackMsg() { | 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); | |||||
if (driver_) { | |||||
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 second? 2.5 seconds = 255 | |||||
DBGPrintf("Joystick update Rumble/LEDs\n"); | |||||
return driver_->sendPacket(packet, 32); | |||||
} else if (btdriver_) { | |||||
uint8_t packet[79]; | |||||
memset(packet, 0, sizeof(packet)); | |||||
//0xa2, 0x11, 0xc0, 0x20, 0xf0, 0x04, 0x00 | |||||
packet[0] = 0x52; | |||||
packet[1] = 0x11; // Report ID | |||||
packet[2] = 0x80; | |||||
//packet[3] = 0x20; | |||||
packet[4] = 0xFF; | |||||
packet[7] = rumble_lValue_; // Small Rumble | |||||
packet[8] = rumble_rValue_; // Big rumble | |||||
packet[9] = leds_[0]; // RGB value | |||||
packet[10] = leds_[1]; | |||||
packet[11] = leds_[2]; | |||||
// 12, 13 flash ON, OFF times in 100ths of sedond? 2.5 seconds = 255 | |||||
DBGPrintf("Joystick update Rumble/LEDs\n"); | |||||
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | } | ||||
static const uint8_t PS3_USER_FEEDBACK_INIT[] = { | static const uint8_t PS3_USER_FEEDBACK_INIT[] = { | ||||
0x00, 0x00, 0x00 }; | 0x00, 0x00, 0x00 }; | ||||
bool JoystickController::transmitPS3UserFeedbackMsg() { | bool JoystickController::transmitPS3UserFeedbackMsg() { | ||||
if (!driver_) return false; | |||||
memcpy(txbuf_, PS3_USER_FEEDBACK_INIT, 48); | |||||
if (driver_) { | |||||
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_[2] << 1; // RGB value // using third led now... | |||||
//DBGPrintf("\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_); | |||||
} else if (btdriver_) { | |||||
txbuf_[0] = 0x52; | |||||
txbuf_[1] = 0x1; | |||||
memcpy(&txbuf_[2], PS3_USER_FEEDBACK_INIT, 48); | |||||
txbuf_[3] = rumble_lValue_? rumble_timeout_ : 0; | |||||
txbuf_[4] = rumble_lValue_; // Small Rumble | |||||
txbuf_[5] = rumble_rValue_? rumble_timeout_ : 0; | |||||
txbuf_[6] = rumble_rValue_; // Big rumble | |||||
txbuf_[11] = leds_[2] << 1; // RGB value | |||||
DBGPrintf("\nJoystick update Rumble/LEDs %d %d %d %d %d\n", txbuf_[3], txbuf_[4], txbuf_[5], txbuf_[6], txbuf_[11]); | |||||
btdriver_->sendL2CapCommand(txbuf_, 50, BluetoothController::CONTROL_SCID); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
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_); | |||||
#define MOVE_REPORT_BUFFER_SIZE 7 | |||||
#define MOVE_HID_BUFFERSIZE 50 // Size of the buffer for the Playstation Motion Controller | |||||
bool JoystickController::transmitPS3MotionUserFeedbackMsg() { | |||||
if (driver_) { | |||||
txbuf_[0] = 0x02; // Set report ID, this is needed for Move commands to work | |||||
txbuf_[2] = leds_[0]; | |||||
txbuf_[3] = leds_[1]; | |||||
txbuf_[4] = leds_[2]; | |||||
txbuf_[6] = rumble_lValue_; // Set the rumble value into the write buffer | |||||
//return driver_->sendControlPacket(0x21, 9, 0x201, 0, MOVE_REPORT_BUFFER_SIZE, txbuf_); | |||||
return driver_->sendPacket(txbuf_, MOVE_REPORT_BUFFER_SIZE); | |||||
} else if (btdriver_) { | |||||
txbuf_[0] = 0xA2; // HID BT DATA_request (0xA0) | Report Type (Output 0x02) | |||||
txbuf_[1] = 0x02; // Report ID | |||||
txbuf_[3] = leds_[0]; | |||||
txbuf_[4] = leds_[1]; | |||||
txbuf_[5] = leds_[2]; | |||||
txbuf_[7] = rumble_lValue_; | |||||
btdriver_->sendL2CapCommand(txbuf_, MOVE_HID_BUFFERSIZE, BluetoothController::INTERRUPT_SCID); | |||||
return true; | |||||
} | |||||
return false; | |||||
} | } | ||||
//***************************************************************************** | //***************************************************************************** | ||||
hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | hidclaim_t JoystickController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | ||||
{ | { | ||||
// only claim Desktop/Joystick and Desktop/Gamepad | // only claim Desktop/Joystick and Desktop/Gamepad | ||||
if (topusage != 0x10004 && topusage != 0x10005) return CLAIM_NO; | |||||
if (topusage != 0x10004 && topusage != 0x10005 && topusage != 0x10008) 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; | ||||
connected_ = true; // remember that hardware is actually connected... | 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); | |||||
switch (joystickType) { | |||||
joystickType_ = mapVIDPIDtoJoystickType(mydevice->idVendor, mydevice->idProduct, false); | |||||
DBGPrintf("JoystickController::claim_collection joystickType_=%d\n", joystickType_); | |||||
switch (joystickType_) { | |||||
case PS3: | case PS3: | ||||
case PS3_MOTION: // not sure yet | |||||
additional_axis_usage_page_ = 0x1; | additional_axis_usage_page_ = 0x1; | ||||
additional_axis_usage_start_ = 0x100; | additional_axis_usage_start_ = 0x100; | ||||
additional_axis_usage_count_ = 39; | additional_axis_usage_count_ = 39; | ||||
axis_change_notify_mask_ = (uint64_t)0xfffffffffffff3ffl; // Start off assume all bits - 10 and 11 | axis_change_notify_mask_ = (uint64_t)0xfffffffffffff3ffl; // Start off assume all bits - 10 and 11 | ||||
break; | break; | ||||
default: | default: | ||||
additional_axis_usage_page_ = 0; | |||||
additional_axis_usage_start_ = 0; | |||||
additional_axis_usage_count_ = 0; | |||||
additional_axis_usage_page_ = 0x09; | |||||
additional_axis_usage_start_ = 0x21; | |||||
additional_axis_usage_count_ = 5; | |||||
axis_change_notify_mask_ = 0x3ff; // Start off assume only the 10 bits... | 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_); | |||||
DBGPrintf("Claim Additional axis: %x %x %d\n", additional_axis_usage_page_, additional_axis_usage_start_, additional_axis_usage_count_); | |||||
return CLAIM_REPORT; | return CLAIM_REPORT; | ||||
} | } | ||||
void JoystickController::hid_input_data(uint32_t usage, int32_t value) | void JoystickController::hid_input_data(uint32_t usage, int32_t value) | ||||
{ | { | ||||
//Serial.printf("Joystick: usage=%X, value=%d\n", usage, value); | |||||
DBGPrintf("joystickType_=%d\n", joystickType_); | |||||
DBGPrintf("Joystick: usage=%X, value=%d\n", usage, value); | |||||
uint32_t usage_page = usage >> 16; | uint32_t usage_page = usage >> 16; | ||||
usage &= 0xFFFF; | usage &= 0xFFFF; | ||||
if (usage_page == 9 && usage >= 1 && usage <= 32) { | if (usage_page == 9 && usage >= 1 && usage <= 32) { | ||||
} | } | ||||
} else if (usage_page == additional_axis_usage_page_) { | } else if (usage_page == additional_axis_usage_page_) { | ||||
// see if the usage is witin range. | // 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_); | |||||
//DBGPrintf("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_))) { | if ((usage >= additional_axis_usage_start_) && (usage < (additional_axis_usage_start_ + additional_axis_usage_count_))) { | ||||
// We are in the user range. | // We are in the user range. | ||||
uint16_t usage_index = usage - additional_axis_usage_start_ + STANDARD_AXIS_COUNT; | uint16_t usage_index = usage - additional_axis_usage_start_ + STANDARD_AXIS_COUNT; | ||||
} | } | ||||
axis_mask_ |= ((uint64_t)1 << usage_index); // Keep record of which axis we have data on. | 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); | |||||
//DBGPrintf("UB: index=%x value=%x\n", usage_index, value); | |||||
} | } | ||||
} else { | } 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_); | |||||
DBGPrintf("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? | // TODO: hat switch? | ||||
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"); | |||||
//DBGPrintf("JoystickController::hid_process_out_data\n"); | |||||
return true; | return true; | ||||
} | } | ||||
connected_ = 0; // remember that hardware is actually connected... | 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. | |||||
DBGPrintf(" JoystickController::claim joystickType_ %d\n", joystickType_); | |||||
return true; | return true; | ||||
} | } | ||||
// Information came from several places on the web including: | // Information came from several places on the web including: | ||||
// https://github.com/quantus/xbox-one-controller-protocol | // https://github.com/quantus/xbox-one-controller-protocol | ||||
/************************************************************/ | /************************************************************/ | ||||
// 20 00 C5 0E 00 00 00 00 00 00 F0 06 AD FB 7A 0A DD F7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |||||
// 20 00 E0 0E 40 00 00 00 00 00 F0 06 AD FB 7A 0A DD F7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | |||||
typedef struct { | typedef struct { | ||||
uint8_t type; | uint8_t type; | ||||
uint8_t const_0; | uint8_t const_0; | ||||
int16_t axis[4]; | int16_t axis[4]; | ||||
} xbox360data_t; | } xbox360data_t; | ||||
static const uint8_t xbox_axis_order_mapping[] = {4, 5, 0, 1, 2, 3}; | |||||
static const uint8_t xbox_axis_order_mapping[] = {3, 4, 0, 1, 2, 5}; | |||||
void JoystickController::rx_data(const Transfer_t *transfer) | void JoystickController::rx_data(const Transfer_t *transfer) | ||||
{ | { | ||||
print("JoystickController::rx_data: "); | |||||
print("JoystickController::rx_data (", joystickType_, DEC); | |||||
print("): "); | |||||
print_hexbytes((uint8_t*)transfer->buffer, transfer->length); | print_hexbytes((uint8_t*)transfer->buffer, transfer->length); | ||||
if (joystickType == XBOXONE) { | |||||
if (joystickType_ == XBOXONE) { | |||||
// Process XBOX One data | // 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 | ||||
if (xb1d->buttons != buttons) { | if (xb1d->buttons != buttons) { | ||||
buttons = xb1d->buttons; | buttons = xb1d->buttons; | ||||
anychange = true; | anychange = true; | ||||
joystickEvent = true; | |||||
println(" Button Change: ", buttons, HEX); | |||||
} | } | ||||
for (uint8_t i = 0; i < sizeof (xbox_axis_order_mapping); i++) { | for (uint8_t i = 0; i < sizeof (xbox_axis_order_mapping); i++) { | ||||
// The first two values were unsigned. | // The first two values were unsigned. | ||||
joystickEvent = true; | joystickEvent = true; | ||||
} | } | ||||
} else if (joystickType == XBOX360) { | |||||
} else if (joystickType_ == XBOX360) { | |||||
// First byte appears to status - if the byte is 0x8 it is a connect or disconnect of the controller. | // 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; | xbox360data_t *xb360d = (xbox360data_t *)transfer->buffer; | ||||
if (xb360d->state == 0x08) { | if (xb360d->state == 0x08) { | ||||
println("XBox360w - controllerStatus: ", xb360d->controller_status, HEX); | println("XBox360w - controllerStatus: ", xb360d->controller_status, HEX); | ||||
} else if(xb360d->id_or_type == 0x01) { // Lets only process report 1. | } else if(xb360d->id_or_type == 0x01) { // Lets only process report 1. | ||||
//const uint8_t *pbuffer = (uint8_t*)transfer->buffer; | //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"); | |||||
//for (uint8_t i = 0; i < transfer->length; i++) DBGPrintf("%02x ", pbuffer[i]); | |||||
//DBGPrintf("\n"); | |||||
if (buttons != xb360d->buttons) { | if (buttons != xb360d->buttons) { | ||||
buttons = xb360d->buttons; | buttons = xb360d->buttons; | ||||
// TODO: free resources | // TODO: free resources | ||||
} | } | ||||
bool JoystickController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class, uint8_t *remoteName) | |||||
{ | |||||
if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && ((bluetooth_class & 0x3C) == 0x08)) { | |||||
DBGPrintf("JoystickController::claim_bluetooth TRUE\n"); | |||||
btdriver_ = driver; | |||||
btdevice = (Device_t*)driver; // remember this way | |||||
if (remoteName) mapNameToJoystickType(remoteName); | |||||
return true; | |||||
} | |||||
if (remoteName && mapNameToJoystickType(remoteName)) { | |||||
if ((joystickType_ == PS3) || (joystickType_ == PS3_MOTION)) { | |||||
DBGPrintf("JoystickController::claim_bluetooth TRUE PS3 hack...\n"); | |||||
btdriver_ = driver; | |||||
btdevice = (Device_t*)driver; // remember this way | |||||
special_process_required = SP_PS3_IDS; // PS3 maybe needs different IDS. | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
bool JoystickController::process_bluetooth_HID_data(const uint8_t *data, uint16_t length) | |||||
{ | |||||
// Example data from PS4 controller | |||||
//01 7e 7f 82 84 08 00 00 00 00 | |||||
// LX LY RX RY BT BT PS LT RT | |||||
DBGPrintf("JoystickController::process_bluetooth_HID_data: data[0]=%x\n", data[0]); | |||||
// May have to look at this one with other controllers... | |||||
if (data[0] == 1) { | |||||
//print(" Joystick Data: "); | |||||
// print_hexbytes(data, length); | |||||
if (length > TOTAL_AXIS_COUNT) length = TOTAL_AXIS_COUNT; // don't overflow arrays... | |||||
DBGPrintf(" Joystick Data: "); | |||||
for(uint16_t i =0; i < length; i++) DBGPrintf("%02x ", data[i]); | |||||
DBGPrintf("\r\n"); | |||||
if (joystickType_ == PS3) { | |||||
// Quick and dirty hack to match PS3 HID data | |||||
uint32_t cur_buttons = data[2] | ((uint16_t)data[3] << 8) | ((uint32_t)data[4] << 16); | |||||
if (cur_buttons != buttons) { | |||||
buttons = cur_buttons; | |||||
joystickEvent = true; // something changed. | |||||
} | |||||
uint64_t mask = 0x1; | |||||
axis_mask_ = 0x27; // assume bits 0, 1, 2, 5 | |||||
for (uint16_t i = 0; i < 3; i++) { | |||||
if (axis[i] != data[i+6]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = data[i+6]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
} | |||||
if (axis[5] != data[9]) { | |||||
axis_changed_mask_ |= (1<<5); | |||||
axis[5] = data[9]; | |||||
} | |||||
if (axis[3] != data[18]) { | |||||
axis_changed_mask_ |= (1<<3); | |||||
axis[3] = data[18]; | |||||
} | |||||
if (axis[4] != data[19]) { | |||||
axis_changed_mask_ |= (1<<4); | |||||
axis[4] = data[19]; | |||||
} | |||||
// Then rest of data | |||||
mask = 0x1 << 10; // setup for other bits | |||||
for (uint16_t i = 10; i < length; i++ ) { | |||||
axis_mask_ |= mask; | |||||
if(data[i] != axis[i]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = data[i]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
} | |||||
} else if (joystickType_ == PS3_MOTION) { | |||||
// Quick and dirty PS3_Motion data. | |||||
uint32_t cur_buttons = data[1] | ((uint16_t)data[2] << 8) | ((uint32_t)data[3] << 16); | |||||
if (cur_buttons != buttons) { | |||||
buttons = cur_buttons; | |||||
joystickEvent = true; // something changed. | |||||
} | |||||
// Hard to know what is best here. for now just copy raw data over... | |||||
// will do this for now... Format of thought to be data. | |||||
// data[1-3] Buttons (mentioned 4 as well but appears to be counter | |||||
// axis[0-1] data[5] Trigger, Previous trigger value | |||||
// 2-5 Unknown probably place holders for Axis like data for other PS3 | |||||
// 6 - Time stamp | |||||
// 7 - Battery | |||||
// 8-19 - Accel: XL, XH, YL, YH, ZL, ZH, XL2, XH2, YL2, YH2, ZL2, ZH2 | |||||
// 20-31 - Gyro: Xl,Xh,Yl,Yh,Zl,Zh,Xl2,Xh2,Yl2,Yh2,Zl2,Zh2 | |||||
// 32 - Temp High | |||||
// 33 - Temp Low (4 bits) Maybe Magneto x High on other?? | |||||
uint64_t mask = 0x1; | |||||
axis_mask_ = 0; // assume bits 0, 1, 2, 5 | |||||
// Then rest of data | |||||
mask = 0x1 << 10; // setup for other bits | |||||
for (uint16_t i = 5; i < length; i++ ) { | |||||
axis_mask_ |= mask; | |||||
if(data[i] != axis[i-5]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i-5] = data[i]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
} | |||||
} else { | |||||
uint64_t mask = 0x1; | |||||
axis_mask_ = 0; | |||||
for (uint16_t i = 0; i < length; i++ ) { | |||||
axis_mask_ |= mask; | |||||
if(data[i] != axis[i]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = data[i]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
// DBGPrintf("%02x ", axis[i]); | |||||
} | |||||
} | |||||
if (axis_changed_mask_ & axis_change_notify_mask_) | |||||
joystickEvent = true; | |||||
connected_ = true; | |||||
return true; | |||||
} else if(data[0] == 0x11){ | |||||
DBGPrintf("\n Joystick Data: "); | |||||
uint64_t mask = 0x1; | |||||
axis_mask_ = 0; | |||||
axis_changed_mask_ = 0; | |||||
//This moves data to be equivalent to what we see for | |||||
//data[0] = 0x01 | |||||
uint8_t tmp_data[length-2]; | |||||
for (uint16_t i = 0; i < (length-2); i++ ) { | |||||
tmp_data[i] = 0; | |||||
tmp_data[i] = data[i+2]; | |||||
} | |||||
/* | |||||
* [1] LX, [2] = LY, [3] = RX, [4] = RY | |||||
* [5] combo, tri, cir, x, sqr, D-PAD (4bits, 0-3 | |||||
* [6] R3,L3, opt, share, R2, L2, R1, L1 | |||||
* [7] Counter (bit7-2), T-PAD, PS | |||||
* [8] Left Trigger, [9] Right Trigger | |||||
* [10-11] Timestamp | |||||
* [12] Battery (0 to 0xff) | |||||
* [13-14] acceleration x | |||||
* [15-16] acceleration y | |||||
* [17-18] acceleration z | |||||
* [19-20] gyro x | |||||
* [21-22] gyro y | |||||
* [23-24] gyro z | |||||
* [25-29] unknown | |||||
* [30] 0x00,phone,mic, usb, battery level (4bits) | |||||
* rest is trackpad? to do implement? | |||||
*/ | |||||
//PS Bit | |||||
tmp_data[7] = (tmp_data[7] >> 0) & 1; | |||||
//set arrow buttons to axis[0] | |||||
tmp_data[10] = tmp_data[5] & ((1 << 4) - 1); | |||||
//set buttons for last 4bits in the axis[5] | |||||
tmp_data[5] = tmp_data[5] >> 4; | |||||
// Quick and dirty hack to match PS4 HID data | |||||
uint32_t cur_buttons = tmp_data[7] | (tmp_data[10]) | ((tmp_data[6]*10)) | ((uint16_t)tmp_data[5] << 16) ; | |||||
if (cur_buttons != buttons) { | |||||
buttons = cur_buttons; | |||||
joystickEvent = true; // something changed. | |||||
} | |||||
mask = 0x1; | |||||
axis_mask_ = 0x27; // assume bits 0, 1, 2, 5 | |||||
for (uint16_t i = 0; i < 3; i++) { | |||||
if (axis[i] != tmp_data[i+1]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = tmp_data[i+1]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
} | |||||
if (axis[5] != tmp_data[4]) { | |||||
axis_changed_mask_ |= (1<<5); | |||||
axis[5] = tmp_data[4]; | |||||
} | |||||
if (axis[3] != tmp_data[8]) { | |||||
axis_changed_mask_ |= (1<<3); | |||||
axis[3] = tmp_data[8]; | |||||
} | |||||
if (axis[4] != tmp_data[9]) { | |||||
axis_changed_mask_ |= (1<<4); | |||||
axis[4] = tmp_data[9]; | |||||
} | |||||
//limit for masking | |||||
mask = 0x1; | |||||
for (uint16_t i = 6; i < (64); i++ ) { | |||||
axis_mask_ |= mask; | |||||
if(tmp_data[i] != axis[i]) { | |||||
axis_changed_mask_ |= mask; | |||||
axis[i] = tmp_data[i]; | |||||
} | |||||
mask <<= 1; // shift down the mask. | |||||
DBGPrintf("%02x ", axis[i]); | |||||
} | |||||
DBGPrintf("\n"); | |||||
//DBGPrintf("Axis Mask (axis_mask_, axis_changed_mask_; %d, %d\n", axis_mask_,axis_changed_mask_); | |||||
joystickEvent = true; | |||||
connected_ = true; | |||||
} | |||||
return false; | |||||
} | |||||
bool JoystickController::mapNameToJoystickType(const uint8_t *remoteName) | |||||
{ | |||||
// Sort of a hack, but try to map the name given from remote to a type... | |||||
if (strncmp((const char *)remoteName, "Wireless Controller", 19) == 0) { | |||||
DBGPrintf(" JoystickController::mapNameToJoystickType %s - set to PS4\n", remoteName); | |||||
joystickType_ = PS4; | |||||
} else if (strncmp((const char *)remoteName, "PLAYSTATION(R)3", 15) == 0) { | |||||
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3\n", (uint32_t)this, remoteName); | |||||
joystickType_ = PS3; | |||||
} else if (strncmp((const char *)remoteName, "Navigation Controller", 21) == 0) { | |||||
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3\n", (uint32_t)this, remoteName); | |||||
joystickType_ = PS3; | |||||
} else if (strncmp((const char *)remoteName, "Motion Controller", 17) == 0) { | |||||
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to PS3 Motion\n", (uint32_t)this, remoteName); | |||||
joystickType_ = PS3_MOTION; | |||||
} else if (strncmp((const char *)remoteName, "Xbox Wireless", 13) == 0) { | |||||
DBGPrintf(" JoystickController::mapNameToJoystickType %x %s - set to XBOXONE\n", (uint32_t)this, remoteName); | |||||
joystickType_ = XBOXONE; | |||||
} else { | |||||
DBGPrintf(" JoystickController::mapNameToJoystickType %s - Unknown\n", remoteName); | |||||
} | |||||
DBGPrintf(" Joystick Type: %d\n", joystickType_); | |||||
return true; | |||||
} | |||||
bool JoystickController::remoteNameComplete(const uint8_t *remoteName) | |||||
{ | |||||
// Sort of a hack, but try to map the name given from remote to a type... | |||||
if (mapNameToJoystickType(remoteName)) { | |||||
switch (joystickType_) { | |||||
case PS4: special_process_required = SP_NEED_CONNECT; break; | |||||
case PS3: special_process_required = SP_PS3_IDS; break; | |||||
case PS3_MOTION: special_process_required = SP_PS3_IDS; break; | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
void JoystickController::connectionComplete() | |||||
{ | |||||
DBGPrintf(" JoystickController::connectionComplete %x joystick type %d\n", (uint32_t)this, joystickType_); | |||||
switch (joystickType_) { | |||||
case PS4: | |||||
{ | |||||
uint8_t packet[2]; | |||||
packet[0] = 0x43; // HID BT Get_report (0x40) | Report Type (Feature 0x03) | |||||
packet[1] = 0x02; // Report ID | |||||
DBGPrintf("Set PS4 report\n"); | |||||
delay(1); | |||||
btdriver_->sendL2CapCommand(packet, sizeof(packet), 0x40); | |||||
} | |||||
break; | |||||
case PS3: | |||||
{ | |||||
uint8_t packet[6]; | |||||
packet[0] = 0x53; // HID BT Set_report (0x50) | Report Type (Feature 0x03) | |||||
packet[1] = 0xF4; // Report ID | |||||
packet[2] = 0x42; // Special PS3 Controller enable commands | |||||
packet[3] = 0x03; | |||||
packet[4] = 0x00; | |||||
packet[5] = 0x00; | |||||
DBGPrintf("enable six axis\n"); | |||||
delay(1); | |||||
btdriver_->sendL2CapCommand(packet, sizeof(packet), BluetoothController::CONTROL_SCID); | |||||
} | |||||
break; | |||||
case PS3_MOTION: | |||||
setLEDs(0, 0xff, 0); // Maybe try setting to green? | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
void JoystickController::release_bluetooth() | |||||
{ | |||||
btdevice = nullptr; // remember this way | |||||
btdriver_ = nullptr; | |||||
connected_ = false; | |||||
special_process_required = false; | |||||
} | |||||
bool JoystickController::PS3Pair(uint8_t* bdaddr) { | |||||
if (!driver_) return false; | |||||
if (joystickType_ == PS3) { | |||||
/* Set the internal Bluetooth address */ | |||||
txbuf_[0] = 0x01; | |||||
txbuf_[1] = 0x00; | |||||
for(uint8_t i = 0; i < 6; i++) | |||||
txbuf_[i + 2] = bdaddr[5 - i]; // Copy into buffer, has to be written reversed, so it is MSB first | |||||
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data | |||||
return driver_->sendControlPacket(0x21, 9, 0x3f5, 0, 8, txbuf_); | |||||
} else if (joystickType_ == PS3_MOTION) { | |||||
// Slightly different than other PS3 units... | |||||
txbuf_[0] = 0x05; | |||||
for(uint8_t i = 0; i < 6; i++) | |||||
txbuf_[i + 1] = bdaddr[i]; // Order different looks like LSB First? | |||||
txbuf_[7] = 0x10; | |||||
txbuf_[8] = 0x01; | |||||
txbuf_[9] = 0x02; | |||||
txbuf_[10] = 0x12; | |||||
// bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data | |||||
return driver_->sendControlPacket(0x21, 9, 0x305, 0, 11, txbuf_); | |||||
} | |||||
return false; | |||||
} |
#define print USBHost::print_ | #define print USBHost::print_ | ||||
#define println USBHost::println_ | #define println USBHost::println_ | ||||
void KeyboardController::init() | void KeyboardController::init() | ||||
{ | { | ||||
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t)); | ||||
contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | contribute_String_Buffers(mystring_bufs, sizeof(mystring_bufs)/sizeof(strbuf_t)); | ||||
driver_ready_for_device(this); | driver_ready_for_device(this); | ||||
USBHIDParser::driver_ready_for_hid_collection(this); | USBHIDParser::driver_ready_for_hid_collection(this); | ||||
BluetoothController::driver_ready_for_bluetooth(this); | |||||
force_boot_protocol = false; // start off assuming not | force_boot_protocol = false; // start off assuming not | ||||
} | } | ||||
void KeyboardController::updateLEDS() { | void KeyboardController::updateLEDS() { | ||||
// Now lets tell keyboard new state. | // Now lets tell keyboard new state. | ||||
mk_setup(setup, 0x21, 9, 0x200, 0, sizeof(leds_.byte)); // hopefully this sets leds | |||||
queue_Control_Transfer(device, &setup, &leds_.byte, this); | |||||
if (device != nullptr) { | |||||
// Only do it this way if we are a standard USB device | |||||
mk_setup(setup, 0x21, 9, 0x200, 0, sizeof(leds_.byte)); // hopefully this sets leds | |||||
queue_Control_Transfer(device, &setup, &leds_.byte, this); | |||||
} else { | |||||
// Bluetooth, need to setup back channel to Bluetooth controller. | |||||
} | |||||
} | } | ||||
//============================================================================= | //============================================================================= | ||||
hidclaim_t KeyboardController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | hidclaim_t KeyboardController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | ||||
{ | { | ||||
// Lets try to claim a few specific Keyboard related collection/reports | // Lets try to claim a few specific Keyboard related collection/reports | ||||
//Serial.printf("KBH Claim %x\n", topusage); | |||||
//USBHDBGSerial.printf("KBH Claim %x\n", topusage); | |||||
if ((topusage != TOPUSAGE_SYS_CONTROL) | if ((topusage != TOPUSAGE_SYS_CONTROL) | ||||
&& (topusage != TOPUSAGE_CONSUMER_CONTROL) | && (topusage != TOPUSAGE_CONSUMER_CONTROL) | ||||
) return CLAIM_NO; | ) return CLAIM_NO; | ||||
// only claim from one physical device | // only claim from one physical device | ||||
//Serial.println("KeyboardController claim collection"); | |||||
//USBHDBGSerial.println("KeyboardController claim collection"); | |||||
// Lets only claim if this is the same device as claimed Keyboard... | // Lets only claim if this is the same device as claimed Keyboard... | ||||
if (dev != device) return CLAIM_NO; | if (dev != device) return CLAIM_NO; | ||||
if (mydevice != NULL && dev != mydevice) return CLAIM_NO; | if (mydevice != NULL && dev != mydevice) return CLAIM_NO; | ||||
void KeyboardController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) | void KeyboardController::hid_input_begin(uint32_t topusage, uint32_t type, int lgmin, int lgmax) | ||||
{ | { | ||||
//Serial.printf("KPC:hid_input_begin TUSE: %x TYPE: %x Range:%x %x\n", topusage, type, lgmin, lgmax); | |||||
//USBHDBGSerial.printf("KPC:hid_input_begin TUSE: %x TYPE: %x Range:%x %x\n", topusage, type, lgmin, lgmax); | |||||
topusage_ = topusage; // remember which report we are processing. | topusage_ = topusage; // remember which report we are processing. | ||||
hid_input_begin_ = true; | hid_input_begin_ = true; | ||||
hid_input_data_ = false; | hid_input_data_ = false; | ||||
{ | { | ||||
// Hack ignore 0xff00 high words as these are user values... | // Hack ignore 0xff00 high words as these are user values... | ||||
if ((usage & 0xffff0000) == 0xff000000) return; | if ((usage & 0xffff0000) == 0xff000000) return; | ||||
//Serial.printf("KeyboardController: topusage= %x usage=%X, value=%d\n", topusage_, usage, value); | |||||
//USBHDBGSerial.printf("KeyboardController: topusage= %x usage=%X, value=%d\n", topusage_, usage, value); | |||||
// See if the value is in our keys_down list | // See if the value is in our keys_down list | ||||
usage &= 0xffff; // only keep the actual key | usage &= 0xffff; // only keep the actual key | ||||
void KeyboardController::hid_input_end() | void KeyboardController::hid_input_end() | ||||
{ | { | ||||
//Serial.println("KPC:hid_input_end"); | |||||
//USBHDBGSerial.println("KPC:hid_input_end"); | |||||
if (hid_input_begin_) { | if (hid_input_begin_) { | ||||
// See if we received any data from parser if not, assume all keys released... | // See if we received any data from parser if not, assume all keys released... | ||||
} | } | ||||
} | } | ||||
bool KeyboardController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class, uint8_t *remoteName) | |||||
{ | |||||
USBHDBGSerial.printf("Keyboard Controller::claim_bluetooth - Class %x\n", bluetooth_class); | |||||
if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && (bluetooth_class & 0x40)) { | |||||
if (remoteName && (strncmp((const char *)remoteName, "PLAYSTATION(R)3", 15) == 0)) { | |||||
USBHDBGSerial.printf("KeyboardController::claim_bluetooth Reject PS3 hack\n"); | |||||
return false; | |||||
} | |||||
USBHDBGSerial.printf("KeyboardController::claim_bluetooth TRUE\n"); | |||||
//btdevice = driver; | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
bool KeyboardController::remoteNameComplete(const uint8_t *remoteName) | |||||
{ | |||||
// Real Hack some PS3 controllers bluetoot class is keyboard... | |||||
if (strncmp((const char *)remoteName, "PLAYSTATION(R)3", 15) == 0) { | |||||
USBHDBGSerial.printf(" KeyboardController::remoteNameComplete %s - Oops PS3 unclaim\n", remoteName); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
bool KeyboardController::process_bluetooth_HID_data(const uint8_t *data, uint16_t length) | |||||
{ | |||||
// Example DATA from bluetooth keyboard: | |||||
// 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 | |||||
// LEN D | |||||
//BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 0 0 0 0 0 0 | |||||
//BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 4 0 0 0 0 0 | |||||
//BT rx2_data(18): 48 20 e 0 a 0 70 0 a1 1 2 0 0 0 0 0 0 0 | |||||
// So Len=9 passed in data starting at report ID=1... | |||||
USBHDBGSerial.printf("KeyboardController::process_bluetooth_HID_data\n"); | |||||
if (data[0] != 1) return false; | |||||
print(" KB Data: "); | |||||
print_hexbytes(data, length); | |||||
for (int i=2; i < length; i++) { | |||||
uint32_t key = prev_report[i]; | |||||
if (key >= 4 && !contains(key, report)) { | |||||
key_release(prev_report[0], key); | |||||
} | |||||
} | |||||
for (int i=2; i < 8; i++) { | |||||
uint32_t key = data[i]; | |||||
if (key >= 4 && !contains(key, prev_report)) { | |||||
key_press(data[1], key); | |||||
} | |||||
} | |||||
// Save away the data.. But shift down one byte... Don't need the report number | |||||
memcpy(prev_report, &data[1], 8); | |||||
return true; | |||||
} | |||||
void KeyboardController::release_bluetooth() | |||||
{ | |||||
//btdevice = nullptr; | |||||
} | |||||
//***************************************************************************** | //***************************************************************************** | ||||
// Some simple query functions depend on which interface we are using... | // Some simple query functions depend on which interface we are using... | ||||
//***************************************************************************** | //***************************************************************************** | ||||
{ | { | ||||
if (device != nullptr) return device->idVendor; | if (device != nullptr) return device->idVendor; | ||||
if (mydevice != nullptr) return mydevice->idVendor; | if (mydevice != nullptr) return mydevice->idVendor; | ||||
if (btdevice != nullptr) return btdevice->idVendor; | |||||
return 0; | return 0; | ||||
} | } | ||||
{ | { | ||||
if (device != nullptr) return device->idProduct; | if (device != nullptr) return device->idProduct; | ||||
if (mydevice != nullptr) return mydevice->idProduct; | if (mydevice != nullptr) return mydevice->idProduct; | ||||
if (btdevice != nullptr) return btdevice->idProduct; | |||||
return 0; | return 0; | ||||
} | } | ||||
const uint8_t *KeyboardController::manufacturer() | const uint8_t *KeyboardController::manufacturer() | ||||
{ | { | ||||
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | ||||
if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | |||||
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_MAN]]; | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
{ | { | ||||
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | ||||
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | ||||
if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_PROD]]; | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
{ | { | ||||
if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; | if ((device != nullptr) && (device->strbuf != nullptr)) return &device->strbuf->buffer[device->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; | ||||
if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; | if ((mydevice != nullptr) && (mydevice->strbuf != nullptr)) return &mydevice->strbuf->buffer[mydevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; | ||||
if ((btdevice != nullptr) && (btdevice->strbuf != nullptr)) return &btdevice->strbuf->buffer[btdevice->strbuf->iStrings[strbuf_t::STR_ID_SERIAL]]; | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
USBHIDParser KEYWORD1 | USBHIDParser KEYWORD1 | ||||
KeyboardController KEYWORD1 | KeyboardController KEYWORD1 | ||||
MouseController KEYWORD1 | MouseController KEYWORD1 | ||||
DigitizerController KEYWORD1 | |||||
MIDIDevice KEYWORD1 | MIDIDevice KEYWORD1 | ||||
MIDIDevice_BigBuffer KEYWORD1 | MIDIDevice_BigBuffer KEYWORD1 | ||||
USBSerial KEYWORD1 | USBSerial KEYWORD1 | ||||
setLEDs KEYWORD2 | setLEDs KEYWORD2 | ||||
joystickType KEYWORD2 | joystickType KEYWORD2 | ||||
PS3 LITERAL1 | PS3 LITERAL1 | ||||
PS3_MOTION LITERAL1 | |||||
PS4 LITERAL1 | PS4 LITERAL1 | ||||
XBOXONE LITERAL1 | XBOXONE LITERAL1 | ||||
XBOX360 LITERAL1 | XBOX360 LITERAL1 |
#include "USBHost_t36.h" // Read this header first for key info | #include "USBHost_t36.h" // Read this header first for key info | ||||
void MouseController::init() | |||||
{ | |||||
USBHIDParser::driver_ready_for_hid_collection(this); | |||||
BluetoothController::driver_ready_for_bluetooth(this); | |||||
} | |||||
hidclaim_t MouseController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | hidclaim_t MouseController::claim_collection(USBHIDParser *driver, Device_t *dev, uint32_t topusage) | ||||
{ | { | ||||
// only claim Desktop/Mouse | // only claim Desktop/Mouse | ||||
if (topusage != 0x10002) return CLAIM_NO; | |||||
if ((topusage != 0x10002) && (topusage != 0x10001)) 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; | ||||
mydevice = dev; | mydevice = dev; | ||||
void MouseController::hid_input_data(uint32_t usage, int32_t value) | void MouseController::hid_input_data(uint32_t usage, int32_t value) | ||||
{ | { | ||||
//Serial.printf("Mouse: usage=%X, value=%d\n", usage, value); | |||||
//USBHDBGSerial.printf("Mouse: usage=%X, value=%d\n", usage, value); | |||||
uint32_t usage_page = usage >> 16; | uint32_t usage_page = usage >> 16; | ||||
usage &= 0xFFFF; | usage &= 0xFFFF; | ||||
if (usage_page == 9 && usage >= 1 && usage <= 8) { | if (usage_page == 9 && usage >= 1 && usage <= 8) { | ||||
} | } | ||||
bool MouseController::claim_bluetooth(BluetoothController *driver, uint32_t bluetooth_class, uint8_t *remoteName) | |||||
{ | |||||
// How to handle combo devices? | |||||
USBHDBGSerial.printf("MouseController Controller::claim_bluetooth - Class %x\n", bluetooth_class); | |||||
if ((((bluetooth_class & 0xff00) == 0x2500) || (((bluetooth_class & 0xff00) == 0x500))) && (bluetooth_class & 0x80)) { | |||||
USBHDBGSerial.printf("MouseController::claim_bluetooth TRUE\n"); | |||||
btdevice = (Device_t*)driver; // remember this way | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
bool MouseController::process_bluetooth_HID_data(const uint8_t *data, uint16_t length) | |||||
{ | |||||
// Example DATA from bluetooth keyboard: | |||||
// 0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 | |||||
// LEN D | |||||
//BT rx2_data(14): b 20 a 0 6 0 71 0 a1 2 0 9 fe 0 | |||||
//BT rx2_data(14): b 20 a 0 6 0 71 0 a1 2 0 8 fd 0 | |||||
// So Len=9 passed in data starting at report ID=1... | |||||
if (length == 0) return false; | |||||
#ifdef USBHOST_PRINT_DEBUG | |||||
USBHDBGSerial.printf("MouseController::process_bluetooth_HID_data %d\n", length); | |||||
USBHDBGSerial.printf(" Mouse Data: "); | |||||
const uint8_t *p = (const uint8_t *)data; | |||||
uint16_t len = length; | |||||
do { | |||||
if (*p < 16) USBHDBGSerial.print('0'); | |||||
USBHDBGSerial.print(*p++, HEX); | |||||
USBHDBGSerial.print(' '); | |||||
} while (--len); | |||||
USBHDBGSerial.println(); | |||||
#endif | |||||
// Looks like report 2 is for the mouse info. | |||||
if (data[0] != 2) return false; | |||||
buttons = data[1]; | |||||
mouseX = (int8_t)data[2]; | |||||
mouseY = (int8_t)data[3]; | |||||
if (length >= 5) { | |||||
wheel = (int8_t)data[4]; | |||||
if (length >= 6) { | |||||
wheelH = (int8_t)data[5]; | |||||
} | |||||
} | |||||
mouseEvent = true; | |||||
return true; | |||||
} | |||||
void MouseController::release_bluetooth() | |||||
{ | |||||
//btdevice = nullptr; | |||||
} |
void USBHost::print_(const Transfer_t *transfer) | void USBHost::print_(const Transfer_t *transfer) | ||||
{ | { | ||||
if (!((uint32_t)transfer & 0xFFFFFFE0)) return; | if (!((uint32_t)transfer & 0xFFFFFFE0)) return; | ||||
Serial.print("Transfer @ "); | |||||
Serial.println(((uint32_t)transfer & 0xFFFFFFE0), HEX); | |||||
Serial.print(" next: "); | |||||
Serial.println(transfer->qtd.next, HEX); | |||||
Serial.print(" anext: "); | |||||
Serial.println(transfer->qtd.alt_next, HEX); | |||||
Serial.print(" token: "); | |||||
Serial.println(transfer->qtd.token, HEX); | |||||
Serial.print(" bufs: "); | |||||
USBHDBGSerial.print("Transfer @ "); | |||||
USBHDBGSerial.println(((uint32_t)transfer & 0xFFFFFFE0), HEX); | |||||
USBHDBGSerial.print(" next: "); | |||||
USBHDBGSerial.println(transfer->qtd.next, HEX); | |||||
USBHDBGSerial.print(" anext: "); | |||||
USBHDBGSerial.println(transfer->qtd.alt_next, HEX); | |||||
USBHDBGSerial.print(" token: "); | |||||
USBHDBGSerial.println(transfer->qtd.token, HEX); | |||||
USBHDBGSerial.print(" bufs: "); | |||||
for (int i=0; i < 5; i++) { | for (int i=0; i < 5; i++) { | ||||
Serial.print(transfer->qtd.buffer[i], HEX); | |||||
if (i < 4) Serial.print(','); | |||||
USBHDBGSerial.print(transfer->qtd.buffer[i], HEX); | |||||
if (i < 4) USBHDBGSerial.print(','); | |||||
} | } | ||||
Serial.println(); | |||||
USBHDBGSerial.println(); | |||||
} | } | ||||
void USBHost::print_(const Transfer_t *first, const Transfer_t *last) | void USBHost::print_(const Transfer_t *first, const Transfer_t *last) | ||||
{ | { | ||||
Serial.print("Transfer Followup List "); | |||||
Serial.print((uint32_t)first, HEX); | |||||
Serial.print(" to "); | |||||
Serial.println((uint32_t)last, HEX); | |||||
Serial.println(" forward:"); | |||||
USBHDBGSerial.print("Transfer Followup List "); | |||||
USBHDBGSerial.print((uint32_t)first, HEX); | |||||
USBHDBGSerial.print(" to "); | |||||
USBHDBGSerial.println((uint32_t)last, HEX); | |||||
USBHDBGSerial.println(" forward:"); | |||||
while (first) { | while (first) { | ||||
Serial.print(" "); | |||||
Serial.print((uint32_t)first, HEX); | |||||
USBHDBGSerial.print(" "); | |||||
USBHDBGSerial.print((uint32_t)first, HEX); | |||||
print_token(first->qtd.token); | print_token(first->qtd.token); | ||||
first = first->next_followup; | first = first->next_followup; | ||||
} | } | ||||
Serial.println(" backward:"); | |||||
USBHDBGSerial.println(" backward:"); | |||||
while (last) { | while (last) { | ||||
Serial.print(" "); | |||||
Serial.print((uint32_t)last, HEX); | |||||
USBHDBGSerial.print(" "); | |||||
USBHDBGSerial.print((uint32_t)last, HEX); | |||||
print_token(last->qtd.token); | print_token(last->qtd.token); | ||||
last = last->prev_followup; | last = last->prev_followup; | ||||
} | } | ||||
{ | { | ||||
switch ((token >> 8) & 3) { | switch ((token >> 8) & 3) { | ||||
case 0: | case 0: | ||||
Serial.print(" OUT "); | |||||
Serial.println((token >> 16) & 0x7FFF); | |||||
USBHDBGSerial.print(" OUT "); | |||||
USBHDBGSerial.println((token >> 16) & 0x7FFF); | |||||
break; | break; | ||||
case 1: | case 1: | ||||
Serial.print(" IN "); | |||||
Serial.println((token >> 16) & 0x7FFF); | |||||
USBHDBGSerial.print(" IN "); | |||||
USBHDBGSerial.println((token >> 16) & 0x7FFF); | |||||
break; | break; | ||||
case 2: | case 2: | ||||
Serial.println(" SETUP"); | |||||
USBHDBGSerial.println(" SETUP"); | |||||
break; | break; | ||||
default: | default: | ||||
Serial.println(" unknown"); | |||||
USBHDBGSerial.println(" unknown"); | |||||
} | } | ||||
} | } | ||||
void USBHost::print_(const Pipe_t *pipe) | void USBHost::print_(const Pipe_t *pipe) | ||||
{ | { | ||||
if (!((uint32_t)pipe & 0xFFFFFFE0)) return; | if (!((uint32_t)pipe & 0xFFFFFFE0)) return; | ||||
Serial.print("Pipe "); | |||||
if (pipe->type == 0) Serial.print("control"); | |||||
else if (pipe->type == 1) Serial.print("isochronous"); | |||||
else if (pipe->type == 2) Serial.print("bulk"); | |||||
else if (pipe->type == 3) Serial.print("interrupt"); | |||||
Serial.print(pipe->direction ? " IN" : " OUT"); | |||||
Serial.print(" @ "); | |||||
Serial.println((uint32_t)pipe, HEX); | |||||
Serial.print(" horiz link: "); | |||||
Serial.println(pipe->qh.horizontal_link, HEX); | |||||
Serial.print(" capabilities: "); | |||||
Serial.print(pipe->qh.capabilities[0], HEX); | |||||
Serial.print(','); | |||||
Serial.println(pipe->qh.capabilities[1], HEX); | |||||
Serial.println(" overlay:"); | |||||
Serial.print(" cur: "); | |||||
Serial.println(pipe->qh.current, HEX); | |||||
Serial.print(" next: "); | |||||
Serial.println(pipe->qh.next, HEX); | |||||
Serial.print(" anext: "); | |||||
Serial.println(pipe->qh.alt_next, HEX); | |||||
Serial.print(" token: "); | |||||
Serial.println(pipe->qh.token, HEX); | |||||
Serial.print(" bufs: "); | |||||
USBHDBGSerial.print("Pipe "); | |||||
if (pipe->type == 0) USBHDBGSerial.print("control"); | |||||
else if (pipe->type == 1) USBHDBGSerial.print("isochronous"); | |||||
else if (pipe->type == 2) USBHDBGSerial.print("bulk"); | |||||
else if (pipe->type == 3) USBHDBGSerial.print("interrupt"); | |||||
USBHDBGSerial.print(pipe->direction ? " IN" : " OUT"); | |||||
USBHDBGSerial.print(" @ "); | |||||
USBHDBGSerial.println((uint32_t)pipe, HEX); | |||||
USBHDBGSerial.print(" horiz link: "); | |||||
USBHDBGSerial.println(pipe->qh.horizontal_link, HEX); | |||||
USBHDBGSerial.print(" capabilities: "); | |||||
USBHDBGSerial.print(pipe->qh.capabilities[0], HEX); | |||||
USBHDBGSerial.print(','); | |||||
USBHDBGSerial.println(pipe->qh.capabilities[1], HEX); | |||||
USBHDBGSerial.println(" overlay:"); | |||||
USBHDBGSerial.print(" cur: "); | |||||
USBHDBGSerial.println(pipe->qh.current, HEX); | |||||
USBHDBGSerial.print(" next: "); | |||||
USBHDBGSerial.println(pipe->qh.next, HEX); | |||||
USBHDBGSerial.print(" anext: "); | |||||
USBHDBGSerial.println(pipe->qh.alt_next, HEX); | |||||
USBHDBGSerial.print(" token: "); | |||||
USBHDBGSerial.println(pipe->qh.token, HEX); | |||||
USBHDBGSerial.print(" bufs: "); | |||||
for (int i=0; i < 5; i++) { | for (int i=0; i < 5; i++) { | ||||
Serial.print(pipe->qh.buffer[i], HEX); | |||||
if (i < 4) Serial.print(','); | |||||
USBHDBGSerial.print(pipe->qh.buffer[i], HEX); | |||||
if (i < 4) USBHDBGSerial.print(','); | |||||
} | } | ||||
Serial.println(); | |||||
USBHDBGSerial.println(); | |||||
const Transfer_t *t = (Transfer_t *)pipe->qh.next; | const Transfer_t *t = (Transfer_t *)pipe->qh.next; | ||||
while (((uint32_t)t & 0xFFFFFFE0)) { | while (((uint32_t)t & 0xFFFFFFE0)) { | ||||
print_(t); | print_(t); | ||||
t = (Transfer_t *)t->qtd.next; | t = (Transfer_t *)t->qtd.next; | ||||
} | } | ||||
//Serial.print(); | |||||
//USBHDBGSerial.print(); | |||||
} | } | ||||
void USBHost::print_driverlist(const char *name, const USBDriver *driver) | void USBHost::print_driverlist(const char *name, const USBDriver *driver) | ||||
{ | { | ||||
Serial.print("USBDriver ("); | |||||
Serial.print(name); | |||||
Serial.print(") list: "); | |||||
USBHDBGSerial.print("USBDriver ("); | |||||
USBHDBGSerial.print(name); | |||||
USBHDBGSerial.print(") list: "); | |||||
if (driver == NULL) { | if (driver == NULL) { | ||||
Serial.println("(empty"); | |||||
USBHDBGSerial.println("(empty"); | |||||
return; | return; | ||||
} | } | ||||
uint32_t count=0; | uint32_t count=0; | ||||
for (const USBDriver *p = driver; p; p = p->next) { | for (const USBDriver *p = driver; p; p = p->next) { | ||||
Serial.print((uint32_t)p, HEX); | |||||
if (p->next) Serial.print(" -> "); | |||||
USBHDBGSerial.print((uint32_t)p, HEX); | |||||
if (p->next) USBHDBGSerial.print(" -> "); | |||||
if (++count > 30) { | if (++count > 30) { | ||||
Serial.println("abort:list too long"); | |||||
USBHDBGSerial.println("abort:list too long"); | |||||
return; | return; | ||||
} | } | ||||
} | } | ||||
Serial.println(); | |||||
USBHDBGSerial.println(); | |||||
} | } | ||||
void USBHost::print_qh_list(const Pipe_t *list) | void USBHost::print_qh_list(const Pipe_t *list) | ||||
{ | { | ||||
if (!list) { | if (!list) { | ||||
Serial.println("(empty)"); | |||||
USBHDBGSerial.println("(empty)"); | |||||
return; | return; | ||||
} | } | ||||
const Pipe_t *node = list; | const Pipe_t *node = list; | ||||
while (1) { | while (1) { | ||||
Serial.print((uint32_t)node, HEX); | |||||
USBHDBGSerial.print((uint32_t)node, HEX); | |||||
node = (const Pipe_t *)(node->qh.horizontal_link & 0xFFFFFFE0); | node = (const Pipe_t *)(node->qh.horizontal_link & 0xFFFFFFE0); | ||||
if (!node) break; | if (!node) break; | ||||
if (node == list) { | if (node == list) { | ||||
Serial.print(" (loops)"); | |||||
USBHDBGSerial.print(" (loops)"); | |||||
break; | break; | ||||
} | } | ||||
Serial.print(" -> "); | |||||
USBHDBGSerial.print(" -> "); | |||||
} | } | ||||
Serial.println(); | |||||
USBHDBGSerial.println(); | |||||
} | } | ||||
static void print_class_subclass_protocol(uint8_t c, uint8_t s, uint8_t p) | static void print_class_subclass_protocol(uint8_t c, uint8_t s, uint8_t p) | ||||
{ | { | ||||
Serial.print(c); | |||||
if (c == 3) Serial.print("(HID)"); | |||||
if (c == 8) Serial.print("(Mass Storage)"); | |||||
if (c == 9) Serial.print("(Hub)"); | |||||
Serial.print(" / "); | |||||
Serial.print(s); | |||||
if (c == 3 && s == 1) Serial.print("(Boot)"); | |||||
if (c == 8 && s == 6) Serial.print("(SCSI)"); | |||||
Serial.print(" / "); | |||||
Serial.print(p); | |||||
if (c == 3 && s == 1 && p == 1) Serial.print("(Keyboard)"); | |||||
if (c == 3 && s == 1 && p == 2) Serial.print("(Mouse)"); | |||||
if (c == 8 && s == 6 && p == 0x50) Serial.print("(Bulk Only)"); | |||||
if (c == 8 && s == 6 && p == 0x62) Serial.print("(UAS)"); | |||||
if (c == 9 && s == 0 && p == 1) Serial.print("(Single-TT)"); | |||||
if (c == 9 && s == 0 && p == 2) Serial.print("(Multi-TT)"); | |||||
Serial.println(); | |||||
USBHDBGSerial.print(c); | |||||
if (c == 3) USBHDBGSerial.print("(HID)"); | |||||
if (c == 8) USBHDBGSerial.print("(Mass Storage)"); | |||||
if (c == 9) USBHDBGSerial.print("(Hub)"); | |||||
USBHDBGSerial.print(" / "); | |||||
USBHDBGSerial.print(s); | |||||
if (c == 3 && s == 1) USBHDBGSerial.print("(Boot)"); | |||||
if (c == 8 && s == 6) USBHDBGSerial.print("(SCSI)"); | |||||
USBHDBGSerial.print(" / "); | |||||
USBHDBGSerial.print(p); | |||||
if (c == 3 && s == 1 && p == 1) USBHDBGSerial.print("(Keyboard)"); | |||||
if (c == 3 && s == 1 && p == 2) USBHDBGSerial.print("(Mouse)"); | |||||
if (c == 8 && s == 6 && p == 0x50) USBHDBGSerial.print("(Bulk Only)"); | |||||
if (c == 8 && s == 6 && p == 0x62) USBHDBGSerial.print("(UAS)"); | |||||
if (c == 9 && s == 0 && p == 1) USBHDBGSerial.print("(Single-TT)"); | |||||
if (c == 9 && s == 0 && p == 2) USBHDBGSerial.print("(Multi-TT)"); | |||||
USBHDBGSerial.println(); | |||||
} | } | ||||
void USBHost::print_device_descriptor(const uint8_t *p) | void USBHost::print_device_descriptor(const uint8_t *p) | ||||
{ | { | ||||
Serial.println("Device Descriptor:"); | |||||
Serial.print(" "); | |||||
USBHDBGSerial.println("Device Descriptor:"); | |||||
USBHDBGSerial.print(" "); | |||||
print_hexbytes(p, p[0]); | print_hexbytes(p, p[0]); | ||||
if (p[0] != 18) { | if (p[0] != 18) { | ||||
Serial.println("error: device must be 18 bytes"); | |||||
USBHDBGSerial.println("error: device must be 18 bytes"); | |||||
return; | return; | ||||
} | } | ||||
if (p[1] != 1) { | if (p[1] != 1) { | ||||
Serial.println("error: device must type 1"); | |||||
USBHDBGSerial.println("error: device must type 1"); | |||||
return; | return; | ||||
} | } | ||||
Serial.printf(" VendorID = %04X, ProductID = %04X, Version = %04X", | |||||
USBHDBGSerial.printf(" VendorID = %04X, ProductID = %04X, Version = %04X", | |||||
p[8] | (p[9] << 8), p[10] | (p[11] << 8), p[12] | (p[13] << 8)); | p[8] | (p[9] << 8), p[10] | (p[11] << 8), p[12] | (p[13] << 8)); | ||||
Serial.println(); | |||||
Serial.print(" Class/Subclass/Protocol = "); | |||||
USBHDBGSerial.println(); | |||||
USBHDBGSerial.print(" Class/Subclass/Protocol = "); | |||||
print_class_subclass_protocol(p[4], p[5], p[6]); | print_class_subclass_protocol(p[4], p[5], p[6]); | ||||
Serial.print(" Number of Configurations = "); | |||||
Serial.println(p[17]); | |||||
USBHDBGSerial.print(" Number of Configurations = "); | |||||
USBHDBGSerial.println(p[17]); | |||||
} | } | ||||
void USBHost::print_config_descriptor(const uint8_t *p, uint32_t maxlen) | void USBHost::print_config_descriptor(const uint8_t *p, uint32_t maxlen) | ||||
{ | { | ||||
// Descriptor Types: (USB 2.0, page 251) | // Descriptor Types: (USB 2.0, page 251) | ||||
Serial.println("Configuration Descriptor:"); | |||||
Serial.print(" "); | |||||
USBHDBGSerial.println("Configuration Descriptor:"); | |||||
USBHDBGSerial.print(" "); | |||||
print_hexbytes(p, p[0]); | print_hexbytes(p, p[0]); | ||||
if (p[0] != 9) { | if (p[0] != 9) { | ||||
Serial.println("error: config must be 9 bytes"); | |||||
USBHDBGSerial.println("error: config must be 9 bytes"); | |||||
return; | return; | ||||
} | } | ||||
if (p[1] != 2) { | if (p[1] != 2) { | ||||
Serial.println("error: config must type 2"); | |||||
USBHDBGSerial.println("error: config must type 2"); | |||||
return; | return; | ||||
} | } | ||||
Serial.print(" NumInterfaces = "); | |||||
Serial.println(p[4]); | |||||
Serial.print(" ConfigurationValue = "); | |||||
Serial.println(p[5]); | |||||
USBHDBGSerial.print(" NumInterfaces = "); | |||||
USBHDBGSerial.println(p[4]); | |||||
USBHDBGSerial.print(" ConfigurationValue = "); | |||||
USBHDBGSerial.println(p[5]); | |||||
uint32_t len = p[2] | (p[3] << 8); | uint32_t len = p[2] | (p[3] << 8); | ||||
if (len > maxlen) len = maxlen; | if (len > maxlen) len = maxlen; | ||||
while (len > 0) { | while (len > 0) { | ||||
if (p[0] > len) { | if (p[0] > len) { | ||||
Serial.print(" "); | |||||
USBHDBGSerial.print(" "); | |||||
print_hexbytes(p, len); | print_hexbytes(p, len); | ||||
Serial.println(" error: length beyond total data size"); | |||||
USBHDBGSerial.println(" error: length beyond total data size"); | |||||
break; | break; | ||||
} | } | ||||
Serial.print(" "); | |||||
USBHDBGSerial.print(" "); | |||||
print_hexbytes(p, p[0]); | print_hexbytes(p, p[0]); | ||||
if (p[0] == 9 && p[1] == 4) { // Interface Descriptor | if (p[0] == 9 && p[1] == 4) { // Interface Descriptor | ||||
Serial.print(" Interface = "); | |||||
Serial.println(p[2]); | |||||
Serial.print(" Number of endpoints = "); | |||||
Serial.println(p[4]); | |||||
Serial.print(" Class/Subclass/Protocol = "); | |||||
USBHDBGSerial.print(" Interface = "); | |||||
USBHDBGSerial.println(p[2]); | |||||
USBHDBGSerial.print(" Number of endpoints = "); | |||||
USBHDBGSerial.println(p[4]); | |||||
USBHDBGSerial.print(" Class/Subclass/Protocol = "); | |||||
print_class_subclass_protocol(p[5], p[6], p[7]); | print_class_subclass_protocol(p[5], p[6], p[7]); | ||||
} else if (p[0] >= 7 && p[0] <= 9 && p[1] == 5) { // Endpoint Descriptor | } else if (p[0] >= 7 && p[0] <= 9 && p[1] == 5) { // Endpoint Descriptor | ||||
Serial.print(" Endpoint = "); | |||||
Serial.print(p[2] & 15); | |||||
Serial.println((p[2] & 128) ? " IN" : " OUT"); | |||||
Serial.print(" Type = "); | |||||
USBHDBGSerial.print(" Endpoint = "); | |||||
USBHDBGSerial.print(p[2] & 15); | |||||
USBHDBGSerial.println((p[2] & 128) ? " IN" : " OUT"); | |||||
USBHDBGSerial.print(" Type = "); | |||||
switch (p[3] & 3) { | switch (p[3] & 3) { | ||||
case 0: Serial.println("Control"); break; | |||||
case 1: Serial.println("Isochronous"); break; | |||||
case 2: Serial.println("Bulk"); break; | |||||
case 3: Serial.println("Interrupt"); break; | |||||
case 0: USBHDBGSerial.println("Control"); break; | |||||
case 1: USBHDBGSerial.println("Isochronous"); break; | |||||
case 2: USBHDBGSerial.println("Bulk"); break; | |||||
case 3: USBHDBGSerial.println("Interrupt"); break; | |||||
} | } | ||||
Serial.print(" Max Size = "); | |||||
Serial.println(p[4] | (p[5] << 8)); | |||||
Serial.print(" Polling Interval = "); | |||||
Serial.println(p[6]); | |||||
USBHDBGSerial.print(" Max Size = "); | |||||
USBHDBGSerial.println(p[4] | (p[5] << 8)); | |||||
USBHDBGSerial.print(" Polling Interval = "); | |||||
USBHDBGSerial.println(p[6]); | |||||
} else if (p[0] == 8 && p[1] == 11) { // IAD | } else if (p[0] == 8 && p[1] == 11) { // IAD | ||||
Serial.print(" Interface Association = "); | |||||
Serial.print(p[2]); | |||||
Serial.print(" through "); | |||||
Serial.println(p[2] + p[3] - 1); | |||||
Serial.print(" Class / Subclass / Protocol = "); | |||||
USBHDBGSerial.print(" Interface Association = "); | |||||
USBHDBGSerial.print(p[2]); | |||||
USBHDBGSerial.print(" through "); | |||||
USBHDBGSerial.println(p[2] + p[3] - 1); | |||||
USBHDBGSerial.print(" Class / Subclass / Protocol = "); | |||||
print_class_subclass_protocol(p[4], p[5], p[7]); | print_class_subclass_protocol(p[4], p[5], p[7]); | ||||
} else if (p[0] >= 9 && p[1] == 0x21) { // HID | } else if (p[0] >= 9 && p[1] == 0x21) { // HID | ||||
Serial.print(" HID, "); | |||||
Serial.print(p[5]); | |||||
Serial.print(" report descriptor"); | |||||
if (p[5] != 1) Serial.print('s'); | |||||
Serial.println(); | |||||
USBHDBGSerial.print(" HID, "); | |||||
USBHDBGSerial.print(p[5]); | |||||
USBHDBGSerial.print(" report descriptor"); | |||||
if (p[5] != 1) USBHDBGSerial.print('s'); | |||||
USBHDBGSerial.println(); | |||||
} | } | ||||
len -= p[0]; | len -= p[0]; | ||||
p += p[0]; | p += p[0]; | ||||
{ | { | ||||
uint32_t len = p[0]; | uint32_t len = p[0]; | ||||
if (len < 4) return; | if (len < 4) return; | ||||
Serial.print(name); | |||||
USBHDBGSerial.print(name); | |||||
len -= 2; | len -= 2; | ||||
p += 2; | p += 2; | ||||
while (len >= 2) { | while (len >= 2) { | ||||
uint32_t c = p[0] | (p[1] << 8); | uint32_t c = p[0] | (p[1] << 8); | ||||
if (c < 0x80) { | if (c < 0x80) { | ||||
Serial.write(c); | |||||
USBHDBGSerial.write(c); | |||||
} else if (c < 0x800) { | } else if (c < 0x800) { | ||||
Serial.write((c >> 6) | 0xC0); | |||||
Serial.write((c & 0x3F) | 0x80); | |||||
USBHDBGSerial.write((c >> 6) | 0xC0); | |||||
USBHDBGSerial.write((c & 0x3F) | 0x80); | |||||
} else { | } else { | ||||
Serial.write((c >> 12) | 0xE0); | |||||
Serial.write(((c >> 6) & 0x3F) | 0x80); | |||||
Serial.write((c & 0x3F) | 0x80); | |||||
USBHDBGSerial.write((c >> 12) | 0xE0); | |||||
USBHDBGSerial.write(((c >> 6) & 0x3F) | 0x80); | |||||
USBHDBGSerial.write((c & 0x3F) | 0x80); | |||||
} | } | ||||
len -= 2; | len -= 2; | ||||
p += 2; | p += 2; | ||||
} | } | ||||
Serial.println(); | |||||
USBHDBGSerial.println(); | |||||
//print_hexbytes(p, p[0]); | //print_hexbytes(p, p[0]); | ||||
} | } | ||||
if (ptr == NULL || len == 0) return; | if (ptr == NULL || len == 0) return; | ||||
const uint8_t *p = (const uint8_t *)ptr; | const uint8_t *p = (const uint8_t *)ptr; | ||||
do { | do { | ||||
if (*p < 16) Serial.print('0'); | |||||
Serial.print(*p++, HEX); | |||||
Serial.print(' '); | |||||
if (*p < 16) USBHDBGSerial.print('0'); | |||||
USBHDBGSerial.print(*p++, HEX); | |||||
USBHDBGSerial.print(' '); | |||||
} while (--len); | } while (--len); | ||||
Serial.println(); | |||||
USBHDBGSerial.println(); | |||||
} | } | ||||
#endif | #endif |
{ | { | ||||
// only claim RAWHID devices currently: 16c0:0486 | // only claim RAWHID devices currently: 16c0:0486 | ||||
#ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
Serial.printf("Rawhid Claim: %x:%x usage: %x\n", dev->idVendor, dev->idProduct, topusage); | |||||
USBHDBGSerial.printf("Rawhid Claim: %x:%x usage: %x\n", dev->idVendor, dev->idProduct, topusage); | |||||
#endif | #endif | ||||
if ((dev->idVendor != 0x16c0 || (dev->idProduct) != 0x486)) return CLAIM_NO; | if ((dev->idVendor != 0x16c0 || (dev->idProduct) != 0x486)) return CLAIM_NO; | ||||
bool RawHIDController::hid_process_in_data(const Transfer_t *transfer) | bool RawHIDController::hid_process_in_data(const Transfer_t *transfer) | ||||
{ | { | ||||
#ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
Serial.printf("RawHIDController::hid_process_in_data: %x\n", usage_); | |||||
USBHDBGSerial.printf("RawHIDController::hid_process_in_data: %x\n", usage_); | |||||
#endif | #endif | ||||
if (receiveCB) { | if (receiveCB) { | ||||
bool RawHIDController::hid_process_out_data(const Transfer_t *transfer) | bool RawHIDController::hid_process_out_data(const Transfer_t *transfer) | ||||
{ | { | ||||
#ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
Serial.printf("RawHIDController::hid_process_out_data: %x\n", usage_); | |||||
USBHDBGSerial.printf("RawHIDController::hid_process_out_data: %x\n", usage_); | |||||
#endif | #endif | ||||
return true; | return true; | ||||
} | } | ||||
// These should not be called as we are claiming the whole interface and not | // These should not be called as we are claiming the whole interface and not | ||||
// allowing the parse to happen | // allowing the parse to happen | ||||
#ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
Serial.printf("RawHID::hid_input_begin %x %x %x %x\n", topusage, type, lgmin, lgmax); | |||||
USBHDBGSerial.printf("RawHID::hid_input_begin %x %x %x %x\n", topusage, type, lgmin, lgmax); | |||||
#endif | #endif | ||||
//hid_input_begin_ = true; | //hid_input_begin_ = true; | ||||
} | } | ||||
// These should not be called as we are claiming the whole interface and not | // These should not be called as we are claiming the whole interface and not | ||||
// allowing the parse to happen | // allowing the parse to happen | ||||
#ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
Serial.printf("RawHID: usage=%X, value=%d", usage, value); | |||||
if ((value >= ' ') && (value <='~')) Serial.printf("(%c)", value); | |||||
Serial.println(); | |||||
USBHDBGSerial.printf("RawHID: usage=%X, value=%d", usage, value); | |||||
if ((value >= ' ') && (value <='~')) USBHDBGSerial.printf("(%c)", value); | |||||
USBHDBGSerial.println(); | |||||
#endif | #endif | ||||
} | } | ||||
// These should not be called as we are claiming the whole interface and not | // These should not be called as we are claiming the whole interface and not | ||||
// allowing the parse to happen | // allowing the parse to happen | ||||
#ifdef USBHOST_PRINT_DEBUG | #ifdef USBHOST_PRINT_DEBUG | ||||
Serial.println("RawHID::hid_input_end"); | |||||
USBHDBGSerial.println("RawHID::hid_input_end"); | |||||
#endif | #endif | ||||
// if (hid_input_begin_) { | // if (hid_input_begin_) { | ||||
// hid_input_begin_ = false; | // hid_input_begin_ = false; |