Clean up code formatting to industry standards.

This commit is contained in:
Andrew J. Kroll 2013-03-28 04:46:43 -04:00
parent 9b224b9899
commit 904f2ff25a
42 changed files with 5429 additions and 5202 deletions

581
BTD.h
View file

@ -134,17 +134,17 @@
/** All Bluetooth services should include this class. */ /** All Bluetooth services should include this class. */
class BluetoothService { class BluetoothService {
public: public:
/** /**
* Used to pass acldata to the Bluetooth service. * Used to pass acldata to the Bluetooth service.
* @param ACLData Pointer to the incoming acldata. * @param ACLData Pointer to the incoming acldata.
*/ */
virtual void ACLData(uint8_t* ACLData); virtual void ACLData(uint8_t* ACLData);
/** Used to run the different state machines in the Bluetooth service. */ /** Used to run the different state machines in the Bluetooth service. */
virtual void Run(); virtual void Run();
/** Used to reset the Bluetooth service. */ /** Used to reset the Bluetooth service. */
virtual void Reset(); virtual void Reset();
/** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */ /** Used to disconnect both the L2CAP Channel and the HCI Connection for the Bluetooth service. */
virtual void disconnect(); virtual void disconnect();
}; };
/** /**
@ -153,299 +153,312 @@ public:
*/ */
class BTD : public USBDeviceConfig, public UsbConfigXtracter { class BTD : public USBDeviceConfig, public UsbConfigXtracter {
public: public:
/** /**
* Constructor for the BTD class. * Constructor for the BTD class.
* @param p Pointer to USB class instance. * @param p Pointer to USB class instance.
*/ */
BTD(USB *p); BTD(USB *p);
/** @name USBDeviceConfig implementation */ /** @name USBDeviceConfig implementation */
/** /**
* Initialize the Bluetooth dongle. * Initialize the Bluetooth dongle.
* @param parent Hub number. * @param parent Hub number.
* @param port Port number on the hub. * @param port Port number on the hub.
* @param lowspeed Speed of the device. * @param lowspeed Speed of the device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/** /**
* Release the USB device. * Release the USB device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Release(); virtual uint8_t Release();
/** /**
* Poll the USB Input endpoins and run the state machines. * Poll the USB Input endpoins and run the state machines.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Poll(); virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() { return bAddress; };
/**
* Used to check if the dongle has been initialized.
* @return True if it's ready.
*/
virtual bool isReady() { return bPollEnable; };
/**@}*/
/** @name UsbConfigXtracter implementation */ /**
/** * Get the device address.
* UsbConfigXtracter implementation, used to extract endpoint information. * @return The device address.
* @param conf Configuration value. */
* @param iface Interface number. virtual uint8_t GetAddress() {
* @param alt Alternate setting. return bAddress;
* @param proto Interface Protocol. };
* @param ep Endpoint Descriptor.
*/
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
/**@}*/
/** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */ /**
void disconnect() { * Used to check if the dongle has been initialized.
for (uint8_t i=0; i<BTD_NUMSERVICES; i++) * @return True if it's ready.
if (btService[i]) */
btService[i]->disconnect(); virtual bool isReady() {
}; return bPollEnable;
/** };
* Register bluetooth dongle members/services. /**@}*/
* @param pService Pointer to BluetoothService class instance.
* @return The serice ID on succes or -1 on fail.
*/
int8_t registerServiceClass(BluetoothService *pService) {
for (uint8_t i=0; i<BTD_NUMSERVICES; i++) {
if (!btService[i]) {
btService[i] = pService;
return i; // Return ID
}
}
return -1; // ErrorregisterServiceClass
};
/** @name HCI Commands */ /** @name UsbConfigXtracter implementation */
/** /**
* Used to send a HCI Command. * UsbConfigXtracter implementation, used to extract endpoint information.
* @param data Data to send. * @param conf Configuration value.
* @param nbytes Number of bytes to send. * @param iface Interface number.
*/ * @param alt Alternate setting.
void HCI_Command(uint8_t* data, uint16_t nbytes); * @param proto Interface Protocol.
/** Reset the Bluetooth dongle. */ * @param ep Endpoint Descriptor.
void hci_reset(); */
/** Read the Bluetooth address of the dongle. */ virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
void hci_read_bdaddr(); /**@}*/
/** Read the HCI Version of the Bluetooth dongle. */
void hci_read_local_version_information();
/**
* Set the local name of the Bluetooth dongle.
* @param name Desired name.
*/
void hci_set_local_name(const char* name);
/** Enable visibility to other Bluetooth devices. */
void hci_write_scan_enable();
/** Disable visibility to other Bluetooth devices. */
void hci_write_scan_disable();
/** Read the remote devices name. */
void hci_remote_name();
/** Accept the connection with the Bluetooth device. */
void hci_accept_connection();
/**
* Disconnect the HCI connection.
* @param handle The HCI Handle for the connection.
*/
void hci_disconnect(uint16_t handle);
/**
* Respond with the pin for the connection.
* The pin is automatically set for the Wii library,
* but can be customized for the SPP library.
*/
void hci_pin_code_request_reply();
/** Respons when no pin was set. */
void hci_pin_code_negative_request_reply();
/**
* Command is used to reply to a Link Key Request event from the BR/EDR Controller
* if the Host does not have a stored Link Key for the connection.
*/
void hci_link_key_request_negative_reply();
/** Used to try to authenticate with the remote device. */
void hci_authentication_request();
/** Start a HCI inquiry. */
void hci_inquiry();
/** Cancel a HCI inquiry. */
void hci_inquiry_cancel();
/** Connect to a device. */
void hci_connect();
/** Used to a set the class of the device. */
void hci_write_class_of_device();
/**@}*/
/** @name L2CAP Commands */ /** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */
/** void disconnect() {
* Used to send L2CAP Commands. for(uint8_t i = 0; i < BTD_NUMSERVICES; i++)
* @param handle HCI Handle. if(btService[i])
* @param data Data to send. btService[i]->disconnect();
* @param nbytes Number of bytes to send. };
* @param channelLow,channelHigh Low and high byte of channel to send to.
* If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used.
*/
void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00);
/**
* L2CAP Connection Request.
* @param handle HCI handle.
* @param rxid Identifier.
* @param scid Source Channel Identifier.
* @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.
*/
void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);
/**
* L2CAP Connection Response.
* @param handle HCI handle.
* @param rxid Identifier.
* @param dcid Destination Channel Identifier.
* @param scid Source Channel Identifier.
* @param result Result - First send ::PENDING and then ::SUCCESSFUL.
*/
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
/**
* L2CAP Config Request.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Destination Channel Identifier.
*/
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);
/**
* L2CAP Config Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);
/**
* L2CAP Disconnection Request.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Device Channel Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
/**
* L2CAP Disconnection Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Device Channel Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
/**
* L2CAP Information Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param infoTypeLow,infoTypeHigh Infotype.
*/
void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);
/**@}*/
/** Use this to see if it is waiting for a incoming connection. */ /**
bool watingForConnection; * Register bluetooth dongle members/services.
/** This is used by the service to know when to store the device information. */ * @param pService Pointer to BluetoothService class instance.
bool l2capConnectionClaimed; * @return The serice ID on succes or -1 on fail.
/** This is used by the SPP library to claim the current SDP incoming request. */ */
bool sdpConnectionClaimed; int8_t registerServiceClass(BluetoothService *pService) {
/** This is used by the SPP library to claim the current RFCOMM incoming request. */ for(uint8_t i = 0; i < BTD_NUMSERVICES; i++) {
bool rfcommConnectionClaimed; if(!btService[i]) {
btService[i] = pService;
return i; // Return ID
}
}
return -1; // ErrorregisterServiceClass
};
/** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */ /** @name HCI Commands */
const char* btdName; /**
/** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP library. */ * Used to send a HCI Command.
const char* btdPin; * @param data Data to send.
* @param nbytes Number of bytes to send.
*/
void HCI_Command(uint8_t* data, uint16_t nbytes);
/** Reset the Bluetooth dongle. */
void hci_reset();
/** Read the Bluetooth address of the dongle. */
void hci_read_bdaddr();
/** Read the HCI Version of the Bluetooth dongle. */
void hci_read_local_version_information();
/**
* Set the local name of the Bluetooth dongle.
* @param name Desired name.
*/
void hci_set_local_name(const char* name);
/** Enable visibility to other Bluetooth devices. */
void hci_write_scan_enable();
/** Disable visibility to other Bluetooth devices. */
void hci_write_scan_disable();
/** Read the remote devices name. */
void hci_remote_name();
/** Accept the connection with the Bluetooth device. */
void hci_accept_connection();
/**
* Disconnect the HCI connection.
* @param handle The HCI Handle for the connection.
*/
void hci_disconnect(uint16_t handle);
/**
* Respond with the pin for the connection.
* The pin is automatically set for the Wii library,
* but can be customized for the SPP library.
*/
void hci_pin_code_request_reply();
/** Respons when no pin was set. */
void hci_pin_code_negative_request_reply();
/**
* Command is used to reply to a Link Key Request event from the BR/EDR Controller
* if the Host does not have a stored Link Key for the connection.
*/
void hci_link_key_request_negative_reply();
/** Used to try to authenticate with the remote device. */
void hci_authentication_request();
/** Start a HCI inquiry. */
void hci_inquiry();
/** Cancel a HCI inquiry. */
void hci_inquiry_cancel();
/** Connect to a device. */
void hci_connect();
/** Used to a set the class of the device. */
void hci_write_class_of_device();
/**@}*/
/** The bluetooth dongles Bluetooth address. */ /** @name L2CAP Commands */
uint8_t my_bdaddr[6]; /**
/** HCI handle for the last connection. */ * Used to send L2CAP Commands.
uint16_t hci_handle; * @param handle HCI Handle.
/** Last incoming devices Bluetooth address. */ * @param data Data to send.
uint8_t disc_bdaddr[6]; * @param nbytes Number of bytes to send.
/** First 30 chars of last remote name. */ * @param channelLow,channelHigh Low and high byte of channel to send to.
uint8_t remote_name[30]; * If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used.
/** */
* The supported HCI Version read from the Bluetooth dongle. void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00);
* Used by the PS3BT library to check the HCI Version of the Bluetooth dongle, /**
* it should be at least 3 to work properly with the library. * L2CAP Connection Request.
*/ * @param handle HCI handle.
uint8_t hci_version; * @param rxid Identifier.
/** Call this function to pair with a Wiimote */ * @param scid Source Channel Identifier.
void pairWithWiimote() { pairWithWii = true; hci_state = HCI_CHECK_WII_SERVICE; }; * @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.
/** Used to only send the ACL data to the wiimote. */ */
bool connectToWii; void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);
/** True if a Wiimote is connecting. */ /**
bool incomingWii; * L2CAP Connection Response.
/** True when it should pair with the incoming Wiimote. */ * @param handle HCI handle.
bool pairWithWii; * @param rxid Identifier.
/** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */ * @param dcid Destination Channel Identifier.
bool motionPlusInside; * @param scid Source Channel Identifier.
/** True if it's a Wii U Pro Controller. */ * @param result Result - First send ::PENDING and then ::SUCCESSFUL.
bool wiiUProController; */
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
/**
* L2CAP Config Request.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Destination Channel Identifier.
*/
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);
/**
* L2CAP Config Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);
/**
* L2CAP Disconnection Request.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Device Channel Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
/**
* L2CAP Disconnection Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param dcid Device Channel Identifier.
* @param scid Source Channel Identifier.
*/
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
/**
* L2CAP Information Response.
* @param handle HCI Handle.
* @param rxid Identifier.
* @param infoTypeLow,infoTypeHigh Infotype.
*/
void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);
/**@}*/
/** /** Use this to see if it is waiting for a incoming connection. */
* Read the poll interval taken from the endpoint descriptors. bool watingForConnection;
* @return The poll interval in ms. /** This is used by the service to know when to store the device information. */
*/ bool l2capConnectionClaimed;
uint8_t readPollInterval() { return pollInterval; }; /** This is used by the SPP library to claim the current SDP incoming request. */
bool sdpConnectionClaimed;
/** This is used by the SPP library to claim the current RFCOMM incoming request. */
bool rfcommConnectionClaimed;
/** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */
const char* btdName;
/** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP library. */
const char* btdPin;
/** The bluetooth dongles Bluetooth address. */
uint8_t my_bdaddr[6];
/** HCI handle for the last connection. */
uint16_t hci_handle;
/** Last incoming devices Bluetooth address. */
uint8_t disc_bdaddr[6];
/** First 30 chars of last remote name. */
uint8_t remote_name[30];
/**
* The supported HCI Version read from the Bluetooth dongle.
* Used by the PS3BT library to check the HCI Version of the Bluetooth dongle,
* it should be at least 3 to work properly with the library.
*/
uint8_t hci_version;
/** Call this function to pair with a Wiimote */
void pairWithWiimote() {
pairWithWii = true;
hci_state = HCI_CHECK_WII_SERVICE;
};
/** Used to only send the ACL data to the wiimote. */
bool connectToWii;
/** True if a Wiimote is connecting. */
bool incomingWii;
/** True when it should pair with the incoming Wiimote. */
bool pairWithWii;
/** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */
bool motionPlusInside;
/** True if it's a Wii U Pro Controller. */
bool wiiUProController;
/**
* Read the poll interval taken from the endpoint descriptors.
* @return The poll interval in ms.
*/
uint8_t readPollInterval() {
return pollInterval;
};
protected: protected:
/** Pointer to USB class instance. */ /** Pointer to USB class instance. */
USB *pUsb; USB *pUsb;
/** Device address. */ /** Device address. */
uint8_t bAddress; uint8_t bAddress;
/** Endpoint info structure. */ /** Endpoint info structure. */
EpInfo epInfo[BTD_MAX_ENDPOINTS]; EpInfo epInfo[BTD_MAX_ENDPOINTS];
/** Configuration number. */ /** Configuration number. */
uint8_t bConfNum; uint8_t bConfNum;
/** Total number of endpoints in the configuration. */ /** Total number of endpoints in the configuration. */
uint8_t bNumEP; uint8_t bNumEP;
/** Next poll time based on poll interval taken from the USB descriptor. */ /** Next poll time based on poll interval taken from the USB descriptor. */
uint32_t qNextPollTime; uint32_t qNextPollTime;
/** Bluetooth dongle control endpoint. */ /** Bluetooth dongle control endpoint. */
static const uint8_t BTD_CONTROL_PIPE; static const uint8_t BTD_CONTROL_PIPE;
/** HCI event endpoint index. */ /** HCI event endpoint index. */
static const uint8_t BTD_EVENT_PIPE; static const uint8_t BTD_EVENT_PIPE;
/** ACL In endpoint index. */ /** ACL In endpoint index. */
static const uint8_t BTD_DATAIN_PIPE; static const uint8_t BTD_DATAIN_PIPE;
/** ACL Out endpoint index. */ /** ACL Out endpoint index. */
static const uint8_t BTD_DATAOUT_PIPE; static const uint8_t BTD_DATAOUT_PIPE;
/** /**
* Used to print the USB Endpoint Descriptor. * Used to print the USB Endpoint Descriptor.
* @param ep_ptr Pointer to USB Endpoint Descriptor. * @param ep_ptr Pointer to USB Endpoint Descriptor.
*/ */
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr); void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr);
private: private:
BluetoothService* btService[BTD_NUMSERVICES]; BluetoothService* btService[BTD_NUMSERVICES];
bool bPollEnable; bool bPollEnable;
uint8_t pollInterval; uint8_t pollInterval;
/* Variables used by high level HCI task */ /* Variables used by high level HCI task */
uint8_t hci_state; //current state of bluetooth hci connection uint8_t hci_state; //current state of bluetooth hci connection
uint16_t hci_counter; // counter used for bluetooth hci reset loops uint16_t hci_counter; // counter used for bluetooth hci reset loops
uint8_t hci_num_reset_loops; // this value indicate how many times it should read before trying to reset uint8_t hci_num_reset_loops; // this value indicate how many times it should read before trying to reset
uint16_t hci_event_flag; // hci flags of received bluetooth events uint16_t hci_event_flag; // hci flags of received bluetooth events
uint8_t inquiry_counter; uint8_t inquiry_counter;
uint8_t hcibuf[BULK_MAXPKTSIZE];//General purpose buffer for hci data uint8_t hcibuf[BULK_MAXPKTSIZE]; //General purpose buffer for hci data
uint8_t l2capinbuf[BULK_MAXPKTSIZE];//General purpose buffer for l2cap in data uint8_t l2capinbuf[BULK_MAXPKTSIZE]; //General purpose buffer for l2cap in data
uint8_t l2capoutbuf[BULK_MAXPKTSIZE];//General purpose buffer for l2cap out data uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; //General purpose buffer for l2cap out data
/* State machines */ /* State machines */
void HCI_event_task(); // Poll the HCI event pipe void HCI_event_task(); // Poll the HCI event pipe
void HCI_task(); // HCI state machine void HCI_task(); // HCI state machine
void ACL_event_task(); // ACL input pipe void ACL_event_task(); // ACL input pipe
/* Used to set the Bluetooth Address internally to the PS3 Controllers */ /* Used to set the Bluetooth Address internally to the PS3 Controllers */
void setBdaddr(uint8_t* BDADDR); void setBdaddr(uint8_t* BDADDR);
void setMoveBdaddr(uint8_t* BDADDR); void setMoveBdaddr(uint8_t* BDADDR);
}; };
#endif #endif

1013
PS3BT.cpp

File diff suppressed because it is too large Load diff

322
PS3BT.h
View file

@ -65,182 +65,182 @@
*/ */
class PS3BT : public BluetoothService { class PS3BT : public BluetoothService {
public: public:
/** /**
* Constructor for the PS3BT class. * Constructor for the PS3BT class.
* @param pBtd Pointer to BTD class instance. * @param pBtd Pointer to BTD class instance.
* @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0
* Pass your dongles Bluetooth address into the constructor, * Pass your dongles Bluetooth address into the constructor,
* This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller. * This will set BTD#my_bdaddr, so you don't have to plug in the dongle before pairing with your controller.
*/ */
PS3BT(BTD *pBtd, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); PS3BT(BTD *pBtd, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0);
/** @name BluetoothService implementation */ /** @name BluetoothService implementation */
/** /**
* Used to pass acldata to the services. * Used to pass acldata to the services.
* @param ACLData Incoming acldata. * @param ACLData Incoming acldata.
*/ */
virtual void ACLData(uint8_t* ACLData); virtual void ACLData(uint8_t* ACLData);
/** Used to run part of the state maschine. */ /** Used to run part of the state maschine. */
virtual void Run(); virtual void Run();
/** Use this to reset the service. */ /** Use this to reset the service. */
virtual void Reset(); virtual void Reset();
/** Used this to disconnect any of the controllers. */ /** Used this to disconnect any of the controllers. */
virtual void disconnect(); virtual void disconnect();
/**@}*/ /**@}*/
/** @name PS3 Controller functions */ /** @name PS3 Controller functions */
/** /**
* getButtonPress(Button b) will return true as long as the button is held down. * getButtonPress(Button b) will return true as long as the button is held down.
* *
* While getButtonClick(Button b) will only return it once. * While getButtonClick(Button b) will only return it once.
* *
* So you instance if you need to increase a variable once you would use getButtonClick(Button b), * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
* but if you need to drive a robot forward you would use getButtonPress(Button b). * but if you need to drive a robot forward you would use getButtonPress(Button b).
*/ */
bool getButtonPress(Button b); bool getButtonPress(Button b);
bool getButtonClick(Button b); bool getButtonClick(Button b);
/**@}*/ /**@}*/
/** @name PS3 Controller functions */ /** @name PS3 Controller functions */
/** /**
* Used to get the analog value from button presses. * Used to get the analog value from button presses.
* @param a The ::Button to read. * @param a The ::Button to read.
* The supported buttons are: * The supported buttons are:
* ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2, * ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
* ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T. * ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
* @return Analog value in the range of 0-255. * @return Analog value in the range of 0-255.
*/ */
uint8_t getAnalogButton(Button a); uint8_t getAnalogButton(Button a);
/** /**
* Used to read the analog joystick. * Used to read the analog joystick.
* @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY. * @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
* @return Return the analog value in the range of 0-255. * @return Return the analog value in the range of 0-255.
*/ */
uint8_t getAnalogHat(AnalogHat a); uint8_t getAnalogHat(AnalogHat a);
/** /**
* Used to read the sensors inside the Dualshock 3 and Move controller. * Used to read the sensors inside the Dualshock 3 and Move controller.
* @param a * @param a
* The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside. * The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.
* The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer * The Move controller has a 3-axis accelerometer, a 3-axis gyro, a 3-axis magnetometer
* and a temperature sensor inside. * and a temperature sensor inside.
* @return Return the raw sensor value. * @return Return the raw sensor value.
*/ */
int16_t getSensor(Sensor a); int16_t getSensor(Sensor a);
/** /**
* Use this to get ::Pitch and ::Roll calculated using the accelerometer. * Use this to get ::Pitch and ::Roll calculated using the accelerometer.
* @param a Either ::Pitch or ::Roll. * @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360. * @return Return the angle in the range of 0-360.
*/ */
double getAngle(Angle a); double getAngle(Angle a);
/** /**
* Read the sensors inside the Move controller. * Read the sensors inside the Move controller.
* @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove. * @param a ::aXmove, ::aYmove, ::aZmove, ::gXmove, ::gYmove, ::gZmove, ::mXmove, ::mYmove, and ::mXmove.
* @return The value in SI units. * @return The value in SI units.
*/ */
double get9DOFValues(Sensor a); double get9DOFValues(Sensor a);
/** /**
* Get the ::Status from the controller. * Get the ::Status from the controller.
* @param c The ::Status you want to read. * @param c The ::Status you want to read.
* @return True if correct and false if not. * @return True if correct and false if not.
*/ */
bool getStatus(Status c); bool getStatus(Status c);
/** /**
* Read all the available ::Status from the controller. * Read all the available ::Status from the controller.
* @return One large string with all the information. * @return One large string with all the information.
*/ */
String getStatusString(); String getStatusString();
/** /**
* Read the temperature from the Move controller. * Read the temperature from the Move controller.
* @return The temperature in degrees celsius. * @return The temperature in degrees celsius.
*/ */
String getTemperature(); String getTemperature();
/** Used to set all LEDs and ::Rumble off. */ /** Used to set all LEDs and ::Rumble off. */
void setAllOff(); void setAllOff();
/** Turn off ::Rumble. */ /** Turn off ::Rumble. */
void setRumbleOff(); void setRumbleOff();
/** /**
* Turn on ::Rumble. * Turn on ::Rumble.
* @param mode Either ::RumbleHigh or ::RumbleLow. * @param mode Either ::RumbleHigh or ::RumbleLow.
*/ */
void setRumbleOn(Rumble mode); void setRumbleOn(Rumble mode);
/** /**
* Turn the specific ::LED off. * Turn the specific ::LED off.
* @param a The ::LED to turn off. * @param a The ::LED to turn off.
*/ */
void setLedOff(LED a); void setLedOff(LED a);
/** /**
* Turn the specific ::LED on. * Turn the specific ::LED on.
* @param a The ::LED to turn on. * @param a The ::LED to turn on.
*/ */
void setLedOn(LED a); void setLedOn(LED a);
/** /**
* Toggle the specific ::LED. * Toggle the specific ::LED.
* @param a The ::LED to toggle. * @param a The ::LED to toggle.
*/ */
void setLedToggle(LED a); void setLedToggle(LED a);
/** /**
* Use this to set the Color using RGB values. * Use this to set the Color using RGB values.
* @param r,g,b RGB value. * @param r,g,b RGB value.
*/ */
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);
/** /**
* Use this to set the color using the predefined colors in ::Colors. * Use this to set the color using the predefined colors in ::Colors.
* @param color The desired color. * @param color The desired color.
*/ */
void moveSetBulb(Colors color); void moveSetBulb(Colors color);
/** /**
* Set the rumble value inside the Move controller. * Set the rumble value inside the Move controller.
* @param rumble The desired value in the range from 64-255. * @param rumble The desired value in the range from 64-255.
*/ */
void moveSetRumble(uint8_t rumble); void moveSetRumble(uint8_t rumble);
/**@}*/ /**@}*/
/** Variable used to indicate if the normal playstation controller is successfully connected. */ /** Variable used to indicate if the normal playstation controller is successfully connected. */
bool PS3Connected; bool PS3Connected;
/** Variable used to indicate if the move controller is successfully connected. */ /** Variable used to indicate if the move controller is successfully connected. */
bool PS3MoveConnected; bool PS3MoveConnected;
/** Variable used to indicate if the navigation controller is successfully connected. */ /** Variable used to indicate if the navigation controller is successfully connected. */
bool PS3NavigationConnected; bool PS3NavigationConnected;
private: private:
/* mandatory members */ /* mandatory members */
BTD *pBtd; BTD *pBtd;
void L2CAP_task(); // L2CAP state machine void L2CAP_task(); // L2CAP state machine
/* Variables filled from HCI event management */ /* Variables filled from HCI event management */
int16_t hci_handle; int16_t hci_handle;
uint8_t remote_name[30]; // First 30 chars of remote name uint8_t remote_name[30]; // First 30 chars of remote name
bool activeConnection; // Used to indicate if it's already has established a connection bool activeConnection; // Used to indicate if it's already has established a connection
/* variables used by high level L2CAP task */ /* variables used by high level L2CAP task */
uint8_t l2cap_state; uint8_t l2cap_state;
uint16_t l2cap_event_flag; // L2CAP flags of received bluetooth events uint16_t l2cap_event_flag; // L2CAP flags of received bluetooth events
unsigned long timer; unsigned long timer;
uint32_t ButtonState; uint32_t ButtonState;
uint32_t OldButtonState; uint32_t OldButtonState;
uint32_t ButtonClickState; uint32_t ButtonClickState;
uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command uint32_t timerHID; // Timer used see if there has to be a delay before a new HID command
uint32_t timerBulbRumble;// used to continuously set PS3 Move controller Bulb and rumble values uint32_t timerBulbRumble; // used to continuously set PS3 Move controller Bulb and rumble values
uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data uint8_t l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for L2CAP in data
uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands uint8_t HIDBuffer[HID_BUFFERSIZE]; // Used to store HID commands
uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller uint8_t HIDMoveBuffer[HID_BUFFERSIZE]; // Used to store HID commands for the Move controller
/* L2CAP Channels */ /* L2CAP Channels */
uint8_t control_scid[2]; // L2CAP source CID for HID_Control uint8_t control_scid[2]; // L2CAP source CID for HID_Control
uint8_t control_dcid[2]; // 0x0040 uint8_t control_dcid[2]; // 0x0040
uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
uint8_t interrupt_dcid[2]; // 0x0041 uint8_t interrupt_dcid[2]; // 0x0041
uint8_t identifier; // Identifier for connection uint8_t identifier; // Identifier for connection
/* HID Commands */ /* HID Commands */
void HID_Command(uint8_t* data, uint8_t nbytes); void HID_Command(uint8_t* data, uint8_t nbytes);
void HIDMove_Command(uint8_t* data, uint8_t nbytes); void HIDMove_Command(uint8_t* data, uint8_t nbytes);
void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via Bluetooth
}; };
#endif #endif

View file

@ -22,17 +22,17 @@
/** Used to set the LEDs on the controllers */ /** Used to set the LEDs on the controllers */
const uint8_t LEDS[] PROGMEM = { const uint8_t LEDS[] PROGMEM = {
0x01, // LED1 0x01, // LED1
0x02, // LED2 0x02, // LED2
0x04, // LED3 0x04, // LED3
0x08, // LED4 0x08, // LED4
0x09, // LED5 0x09, // LED5
0x0A, // LED6 0x0A, // LED6
0x0C, // LED7 0x0C, // LED7
0x0D, // LED8 0x0D, // LED8
0x0E, // LED9 0x0E, // LED9
0x0F // LED10 0x0F // LED10
}; };
/** /**
@ -41,29 +41,29 @@ const uint8_t LEDS[] PROGMEM = {
* <B>Note:</B> that the location is shiftet 9 when it's connected via USB. * <B>Note:</B> that the location is shiftet 9 when it's connected via USB.
*/ */
const uint32_t BUTTONS[] PROGMEM = { const uint32_t BUTTONS[] PROGMEM = {
0x10, // UP 0x10, // UP
0x20, // RIGHT 0x20, // RIGHT
0x40, // DOWN 0x40, // DOWN
0x80, // LEFT 0x80, // LEFT
0x01, // SELECT 0x01, // SELECT
0x08, // START 0x08, // START
0x02, // L3 0x02, // L3
0x04, // R3 0x04, // R3
0x0100, // L2 0x0100, // L2
0x0200, // R2 0x0200, // R2
0x0400, // L1 0x0400, // L1
0x0800, // R1 0x0800, // R1
0x1000, // TRIANGLE 0x1000, // TRIANGLE
0x2000, // CIRCLE 0x2000, // CIRCLE
0x4000, // CROSS 0x4000, // CROSS
0x8000, // SQUARE 0x8000, // SQUARE
0x010000, // PS 0x010000, // PS
0x080000, // MOVE - covers 12 bits - we only need to read the top 8 0x080000, // MOVE - covers 12 bits - we only need to read the top 8
0x100000 // T - covers 12 bits - we only need to read the top 8 0x100000 // T - covers 12 bits - we only need to read the top 8
}; };
/** /**
@ -72,46 +72,46 @@ const uint32_t BUTTONS[] PROGMEM = {
* <B>Note:</B> that the location is shiftet 9 when it's connected via USB. * <B>Note:</B> that the location is shiftet 9 when it's connected via USB.
*/ */
const uint8_t ANALOGBUTTONS[] PROGMEM = { const uint8_t ANALOGBUTTONS[] PROGMEM = {
23, // UP_ANALOG 23, // UP_ANALOG
24, // RIGHT_ANALOG 24, // RIGHT_ANALOG
25, // DOWN_ANALOG 25, // DOWN_ANALOG
26, // LEFT_ANALOG 26, // LEFT_ANALOG
0,0,0,0, // Skip SELECT, L3, R3 and START 0, 0, 0, 0, // Skip SELECT, L3, R3 and START
27, // L2_ANALOG 27, // L2_ANALOG
28, // R2_ANALOG 28, // R2_ANALOG
29, // L1_ANALOG 29, // L1_ANALOG
30, // R1_ANALOG 30, // R1_ANALOG
31, // TRIANGLE_ANALOG 31, // TRIANGLE_ANALOG
32, // CIRCLE_ANALOG 32, // CIRCLE_ANALOG
33, // CROSS_ANALOG 33, // CROSS_ANALOG
34, // SQUARE_ANALOG 34, // SQUARE_ANALOG
0,0, // Skip PS and MOVE 0, 0, // Skip PS and MOVE
// Playstation Move Controller // Playstation Move Controller
15 // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading) 15 // T_ANALOG - Both at byte 14 (last reading) and byte 15 (current reading)
}; };
/** Used to set the colors of the move controller. */ /** Used to set the colors of the move controller. */
enum Colors { enum Colors {
/** r = 255, g = 0, b = 0 */ /** r = 255, g = 0, b = 0 */
Red = 0xFF0000, Red = 0xFF0000,
/** r = 0, g = 255, b = 0 */ /** r = 0, g = 255, b = 0 */
Green = 0xFF00, Green = 0xFF00,
/** r = 0, g = 0, b = 255 */ /** r = 0, g = 0, b = 255 */
Blue = 0xFF, Blue = 0xFF,
/** r = 255, g = 235, b = 4 */ /** r = 255, g = 235, b = 4 */
Yellow = 0xFFEB04, Yellow = 0xFFEB04,
/** r = 0, g = 255, b = 255 */ /** r = 0, g = 255, b = 255 */
Lightblue = 0xFFFF, Lightblue = 0xFFFF,
/** r = 255, g = 0, b = 255 */ /** r = 255, g = 0, b = 255 */
Purble = 0xFF00FF, Purble = 0xFF00FF,
/** r = 255, g = 255, b = 255 */ /** r = 255, g = 255, b = 255 */
White = 0xFFFFFF, White = 0xFFFFFF,
/** r = 0, g = 0, b = 0 */ /** r = 0, g = 0, b = 0 */
Off = 0x00, Off = 0x00,
}; };
/** /**
@ -120,74 +120,77 @@ enum Colors {
* <B>Note:</B> that the location is shiftet 9 when it's connected via USB. * <B>Note:</B> that the location is shiftet 9 when it's connected via USB.
*/ */
enum Sensor { enum Sensor {
/** Accelerometer x-axis */ /** Accelerometer x-axis */
aX = 50, aX = 50,
/** Accelerometer y-axis */ /** Accelerometer y-axis */
aY = 52, aY = 52,
/** Accelerometer z-axis */ /** Accelerometer z-axis */
aZ = 54, aZ = 54,
/** Gyro z-axis */ /** Gyro z-axis */
gZ = 56, gZ = 56,
/** Accelerometer x-axis */ /** Accelerometer x-axis */
aXmove = 28, aXmove = 28,
/** Accelerometer z-axis */ /** Accelerometer z-axis */
aZmove = 30, aZmove = 30,
/** Accelerometer y-axis */ /** Accelerometer y-axis */
aYmove = 32, aYmove = 32,
/** Gyro x-axis */ /** Gyro x-axis */
gXmove = 40, gXmove = 40,
/** Gyro z-axis */ /** Gyro z-axis */
gZmove = 42, gZmove = 42,
/** Gyro y-axis */ /** Gyro y-axis */
gYmove = 44, gYmove = 44,
/** Temperature sensor */ /** Temperature sensor */
tempMove = 46, tempMove = 46,
/** Magnetometer x-axis */ /** Magnetometer x-axis */
mXmove = 47, mXmove = 47,
/** Magnetometer z-axis */ /** Magnetometer z-axis */
mZmove = 49, mZmove = 49,
/** Magnetometer y-axis */ /** Magnetometer y-axis */
mYmove = 50, mYmove = 50,
}; };
/** Used to get the angle calculated using the accelerometer. */ /** Used to get the angle calculated using the accelerometer. */
enum Angle { enum Angle {
Pitch = 0x01, Pitch = 0x01,
Roll = 0x02, Roll = 0x02,
}; };
enum Status { enum Status {
// Note that the location is shiftet 9 when it's connected via USB // Note that the location is shiftet 9 when it's connected via USB
// Byte location | bit location // Byte location | bit location
Plugged = (38 << 8) | 0x02, Plugged = (38 << 8) | 0x02,
Unplugged = (38 << 8) | 0x03, Unplugged = (38 << 8) | 0x03,
Charging = (39 << 8) | 0xEE, Charging = (39 << 8) | 0xEE,
NotCharging = (39 << 8) | 0xF1, NotCharging = (39 << 8) | 0xF1,
Shutdown = (39 << 8) | 0x01, Shutdown = (39 << 8) | 0x01,
Dying = (39 << 8) | 0x02, Dying = (39 << 8) | 0x02,
Low = (39 << 8) | 0x03, Low = (39 << 8) | 0x03,
High = (39 << 8) | 0x04, High = (39 << 8) | 0x04,
Full = (39 << 8) | 0x05, Full = (39 << 8) | 0x05,
MoveCharging = (21 << 8) | 0xEE, MoveCharging = (21 << 8) | 0xEE,
MoveNotCharging = (21 << 8) | 0xF1, MoveNotCharging = (21 << 8) | 0xF1,
MoveShutdown = (21 << 8) | 0x01, MoveShutdown = (21 << 8) | 0x01,
MoveDying = (21 << 8) | 0x02, MoveDying = (21 << 8) | 0x02,
MoveLow = (21 << 8) | 0x03, MoveLow = (21 << 8) | 0x03,
MoveHigh = (21 << 8) | 0x04, MoveHigh = (21 << 8) | 0x04,
MoveFull = (21 << 8) | 0x05, MoveFull = (21 << 8) | 0x05,
CableRumble = (40 << 8) | 0x10,//Opperating by USB and rumble is turned on CableRumble = (40 << 8) | 0x10, //Opperating by USB and rumble is turned on
Cable = (40 << 8) | 0x12,//Opperating by USB and rumble is turned off Cable = (40 << 8) | 0x12, //Opperating by USB and rumble is turned off
BluetoothRumble = (40 << 8) | 0x14,//Opperating by bluetooth and rumble is turned on BluetoothRumble = (40 << 8) | 0x14, //Opperating by bluetooth and rumble is turned on
Bluetooth = (40 << 8) | 0x16,//Opperating by bluetooth and rumble is turned off Bluetooth = (40 << 8) | 0x16, //Opperating by bluetooth and rumble is turned off
}; };
enum Rumble { enum Rumble {
RumbleHigh = 0x10, RumbleHigh = 0x10,
RumbleLow = 0x20, RumbleLow = 0x20,
}; };
#endif #endif

View file

@ -21,531 +21,547 @@
//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers
const uint8_t PS3_REPORT_BUFFER[] PROGMEM = { const uint8_t PS3_REPORT_BUFFER[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
const uint8_t MOVE_REPORT_BUFFER[] PROGMEM = { const uint8_t MOVE_REPORT_BUFFER[] PROGMEM = {
0x02, 0x00, // Always 0x02, 0x00, 0x02, 0x00, // Always 0x02, 0x00,
0x00, 0x00, 0x00, // r, g, b, 0x00, 0x00, 0x00, // r, g, b,
0x00, // Always 0x00, 0x00, // Always 0x00,
0x00 // Rumble 0x00 // Rumble
}; };
PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0): PS3USB::PS3USB(USB *p, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0) :
pUsb(p), // pointer to USB class instance - mandatory pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory bAddress(0), // device address - mandatory
bPollEnable(false) // don't start polling before dongle is connected bPollEnable(false) // don't start polling before dongle is connected
{ {
for(uint8_t i=0; i<PS3_MAX_ENDPOINTS; i++) { for (uint8_t i = 0; i < PS3_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
if (pUsb) // register in USB subsystem if (pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead my_bdaddr[5] = btadr5; // Change to your dongle's Bluetooth address instead
my_bdaddr[4] = btadr4; my_bdaddr[4] = btadr4;
my_bdaddr[3] = btadr3; my_bdaddr[3] = btadr3;
my_bdaddr[2] = btadr2; my_bdaddr[2] = btadr2;
my_bdaddr[1] = btadr1; my_bdaddr[1] = btadr1;
my_bdaddr[0] = btadr0; my_bdaddr[0] = btadr0;
} }
uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
uint8_t rcode; uint8_t rcode;
UsbDevice *p = NULL; UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL; EpInfo *oldep_ptr = NULL;
uint16_t PID; uint16_t PID;
uint16_t VID; uint16_t VID;
// get memory address of USB device address pool // get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nPS3USB Init"), 0x80); Notify(PSTR("\r\nPS3USB Init"), 0x80);
#endif #endif
// check if address has already been assigned to an instance // check if address has already been assigned to an instance
if (bAddress) { if (bAddress) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
}
// Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0);
if (!p) {
#ifdef DEBUG
Notify(PSTR("\r\nAddress not found"), 0x80);
#endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
}
if (!p->epinfo) {
#ifdef DEBUG
Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif
return USB_ERROR_EPINFO_IS_NULL;
}
// Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo;
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo;
p->lowspeed = lowspeed;
// Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data
// Restore p->epinfo
p->epinfo = oldep_ptr;
if(rcode)
goto FailGetDevDescr;
VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
if(VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID))
goto FailUnknownDevice;
// Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device
rcode = pUsb->setAddr( 0, 0, bAddress );
if (rcode) {
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
#ifdef DEBUG
Notify(PSTR("\r\nsetAddr: "), 0x80);
#endif
PrintHex<uint8_t>(rcode, 0x80);
return rcode;
}
#ifdef EXTRADEBUG
Notify(PSTR("\r\nAddr: "), 0x80);
PrintHex<uint8_t>(bAddress, 0x80);
#endif
p->lowspeed = false;
//get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress);
if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode)
goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data
memory space. After verifying the PID and VID we will use known values for the
configuration values for device, interface, endpoints and HID for the PS3 Controllers */
/* Initialize data structures for endpoints of device */
epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint
epInfo[ PS3_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT;
epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0;
epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0;
epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint
epInfo[ PS3_INPUT_PIPE ].epAttribs = EP_INTERRUPT;
epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ PS3_INPUT_PIPE ].bmSndToggle = bmSNDTOG0;
epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0;
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if( rcode )
goto FailSetDevTblEntry;
delay(200);//Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1);
if( rcode )
goto FailSetConf;
if(PID == PS3_PID || PID == PS3NAVIGATION_PID) {
if(PID == PS3_PID) {
#ifdef DEBUG
Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
#endif
PS3Connected = true;
} else { // must be a navigation controller
#ifdef DEBUG
Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
#endif
PS3NavigationConnected = true;
} }
/* Set internal bluetooth address and request for data */
setBdaddr(my_bdaddr);
enable_sixaxis();
setLedOn(LED1);
// Needed for PS3 Dualshock and Navigation commands to work // Get pointer to pseudo device with address 0 assigned
for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) p = addrPool.GetUsbDevicePtr(0);
writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]);
for (uint8_t i = 6; i < 10; i++) if (!p) {
readBuf[i] = 0x7F; // Set the analog joystick values to center position
}
else { // must be a Motion controller
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nMotion Controller Connected"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
PS3MoveConnected = true; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
setMoveBdaddr(my_bdaddr); // Set internal bluetooth address }
moveSetBulb(Red);
// Needed for Move commands to work if (!p->epinfo) {
for (uint8_t i = 0; i < MOVE_REPORT_BUFFER_SIZE; i++) #ifdef DEBUG
writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]); Notify(PSTR("\r\nepinfo is null"), 0x80);
} #endif
return USB_ERROR_EPINFO_IS_NULL;
}
bPollEnable = true; // Save old pointer to EP_RECORD of address 0
Notify(PSTR("\r\n"), 0x80); oldep_ptr = p->epinfo;
timer = millis();
return 0; // successful configuration
/* diagnostic messages */ // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo;
p->lowspeed = lowspeed;
// Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
// Restore p->epinfo
p->epinfo = oldep_ptr;
if (rcode)
goto FailGetDevDescr;
VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
if (VID != PS3_VID || (PID != PS3_PID && PID != PS3NAVIGATION_PID && PID != PS3MOVE_PID))
goto FailUnknownDevice;
// Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) {
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
#ifdef DEBUG
Notify(PSTR("\r\nsetAddr: "), 0x80);
#endif
PrintHex<uint8_t > (rcode, 0x80);
return rcode;
}
#ifdef EXTRADEBUG
Notify(PSTR("\r\nAddr: "), 0x80);
PrintHex<uint8_t > (bAddress, 0x80);
#endif
p->lowspeed = false;
//get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress);
if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode)
goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data
memory space. After verifying the PID and VID we will use known values for the
configuration values for device, interface, endpoints and HID for the PS3 Controllers */
/* Initialize data structures for endpoints of device */
epInfo[ PS3_OUTPUT_PIPE ].epAddr = 0x02; // PS3 output endpoint
epInfo[ PS3_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT;
epInfo[ PS3_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ PS3_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ PS3_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0;
epInfo[ PS3_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0;
epInfo[ PS3_INPUT_PIPE ].epAddr = 0x01; // PS3 report endpoint
epInfo[ PS3_INPUT_PIPE ].epAttribs = EP_INTERRUPT;
epInfo[ PS3_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ PS3_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ PS3_INPUT_PIPE ].bmSndToggle = bmSNDTOG0;
epInfo[ PS3_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0;
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if (rcode)
goto FailSetDevTblEntry;
delay(200); //Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ PS3_CONTROL_PIPE ].epAddr, 1);
if (rcode)
goto FailSetConf;
if (PID == PS3_PID || PID == PS3NAVIGATION_PID) {
if (PID == PS3_PID) {
#ifdef DEBUG
Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
#endif
PS3Connected = true;
} else { // must be a navigation controller
#ifdef DEBUG
Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
#endif
PS3NavigationConnected = true;
}
/* Set internal bluetooth address and request for data */
setBdaddr(my_bdaddr);
enable_sixaxis();
setLedOn(LED1);
// Needed for PS3 Dualshock and Navigation commands to work
for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]);
for (uint8_t i = 6; i < 10; i++)
readBuf[i] = 0x7F; // Set the analog joystick values to center position
} else { // must be a Motion controller
#ifdef DEBUG
Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
#endif
PS3MoveConnected = true;
setMoveBdaddr(my_bdaddr); // Set internal bluetooth address
moveSetBulb(Red);
// Needed for Move commands to work
for (uint8_t i = 0; i < MOVE_REPORT_BUFFER_SIZE; i++)
writeBuf[i] = pgm_read_byte(&MOVE_REPORT_BUFFER[i]);
}
bPollEnable = true;
Notify(PSTR("\r\n"), 0x80);
timer = millis();
return 0; // successful configuration
/* diagnostic messages */
FailGetDevDescr: FailGetDevDescr:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\ngetDevDescr:"), 0x80); Notify(PSTR("\r\ngetDevDescr:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailSetDevTblEntry: FailSetDevTblEntry:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nsetDevTblEn:"), 0x80); Notify(PSTR("\r\nsetDevTblEn:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailSetConf: FailSetConf:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nsetConf:"), 0x80); Notify(PSTR("\r\nsetConf:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailUnknownDevice: FailUnknownDevice:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80);
PrintHex<uint16_t>(VID, 0x80); PrintHex<uint16_t > (VID, 0x80);
Notify(PSTR(" PID: "), 0x80); Notify(PSTR(" PID: "), 0x80);
PrintHex<uint16_t>(PID, 0x80); PrintHex<uint16_t > (PID, 0x80);
#endif #endif
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
goto Fail; goto Fail;
Fail: Fail:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80); Notify(PSTR("\r\nPS3 Init Failed, error code: "), 0x80);
Serial.print(rcode,HEX); Serial.print(rcode, HEX);
#endif #endif
Release(); Release();
return rcode; return rcode;
} }
/* Performs a cleanup after failed Init() attempt */ /* Performs a cleanup after failed Init() attempt */
uint8_t PS3USB::Release() { uint8_t PS3USB::Release() {
PS3Connected = false; PS3Connected = false;
PS3MoveConnected = false; PS3MoveConnected = false;
PS3NavigationConnected = false; PS3NavigationConnected = false;
pUsb->GetAddressPool().FreeAddress(bAddress); pUsb->GetAddressPool().FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
bPollEnable = false; bPollEnable = false;
return 0; return 0;
} }
uint8_t PS3USB::Poll() {
if (!bPollEnable)
return 0;
if(PS3Connected || PS3NavigationConnected) { uint8_t PS3USB::Poll() {
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; if (!bPollEnable)
pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 return 0;
if(millis() - timer > 100) { // Loop 100ms before processing data
readReport(); if (PS3Connected || PS3NavigationConnected) {
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
pUsb->inTransfer(bAddress, epInfo[ PS3_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
if (millis() - timer > 100) { // Loop 100ms before processing data
readReport();
#ifdef PRINTREPORT #ifdef PRINTREPORT
printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
#endif #endif
}
} else if (PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB
if (millis() - timer > 4000) // Send at least every 4th second
{
Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
timer = millis();
}
} }
} return 0;
else if(PS3MoveConnected) { // One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB
if (millis() - timer > 4000) // Send at least every 4th second
{
Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); // The Bulb and rumble values, has to be written again and again, for it to stay turned on
timer = millis();
}
}
return 0;
} }
void PS3USB::readReport() { void PS3USB::readReport() {
if (readBuf == NULL) if (readBuf == NULL)
return; return;
ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16)); ButtonState = (uint32_t)(readBuf[2] | ((uint16_t)readBuf[3] << 8) | ((uint32_t)readBuf[4] << 16));
//Notify(PSTR("\r\nButtonState", 0x80); //Notify(PSTR("\r\nButtonState", 0x80);
//PrintHex<uint32_t>(ButtonState, 0x80); //PrintHex<uint32_t>(ButtonState, 0x80);
if(ButtonState != OldButtonState) { if (ButtonState != OldButtonState) {
ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable ButtonClickState = ButtonState & ~OldButtonState; // Update click state variable
OldButtonState = ButtonState; OldButtonState = ButtonState;
} }
} }
void PS3USB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers void PS3USB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
#ifdef PRINTREPORT #ifdef PRINTREPORT
if (readBuf == NULL) if (readBuf == NULL)
return; return;
for(uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE;i++) { for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) {
PrintHex<uint8_t>(readBuf[i], 0x80); PrintHex<uint8_t > (readBuf[i], 0x80);
Serial.print(" "); Serial.print(" ");
} }
Serial.println(); Serial.println();
#endif #endif
} }
bool PS3USB::getButtonPress(Button b) { bool PS3USB::getButtonPress(Button b) {
return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b])); return (ButtonState & pgm_read_dword(&BUTTONS[(uint8_t)b]));
} }
bool PS3USB::getButtonClick(Button b) { bool PS3USB::getButtonClick(Button b) {
uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]); uint32_t button = pgm_read_dword(&BUTTONS[(uint8_t)b]);
bool click = (ButtonClickState & button); bool click = (ButtonClickState & button);
ButtonClickState &= ~button; // clear "click" event ButtonClickState &= ~button; // clear "click" event
return click; return click;
} }
uint8_t PS3USB::getAnalogButton(Button a) { uint8_t PS3USB::getAnalogButton(Button a) {
if (readBuf == NULL) if (readBuf == NULL)
return 0; return 0;
return (uint8_t)(readBuf[(pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a]))-9]); return (uint8_t)(readBuf[(pgm_read_byte(&ANALOGBUTTONS[(uint8_t)a])) - 9]);
} }
uint8_t PS3USB::getAnalogHat(AnalogHat a) { uint8_t PS3USB::getAnalogHat(AnalogHat a) {
if (readBuf == NULL) if (readBuf == NULL)
return 0; return 0;
return (uint8_t)(readBuf[((uint8_t)a+6)]); return (uint8_t)(readBuf[((uint8_t)a + 6)]);
} }
uint16_t PS3USB::getSensor(Sensor a) { uint16_t PS3USB::getSensor(Sensor a) {
if (readBuf == NULL) if (readBuf == NULL)
return 0; return 0;
return ((readBuf[((uint16_t)a)-9] << 8) | readBuf[((uint16_t)a + 1)-9]); return ((readBuf[((uint16_t)a) - 9] << 8) | readBuf[((uint16_t)a + 1) - 9]);
} }
double PS3USB::getAngle(Angle a) { double PS3USB::getAngle(Angle a) {
if(PS3Connected) { if (PS3Connected) {
double accXval; double accXval;
double accYval; double accYval;
double accZval; double accZval;
// Data for the Kionix KXPC4 used in the DualShock 3 // Data for the Kionix KXPC4 used in the DualShock 3
const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V) const double zeroG = 511.5; // 1.65/3.3*1023 (1,65V)
accXval = -((double)getSensor(aX)-zeroG); accXval = -((double)getSensor(aX) - zeroG);
accYval = -((double)getSensor(aY)-zeroG); accYval = -((double)getSensor(aY) - zeroG);
accZval = -((double)getSensor(aZ)-zeroG); accZval = -((double)getSensor(aZ) - zeroG);
// Convert to 360 degrees resolution // Convert to 360 degrees resolution
// atan2 outputs the value of -π to π (radians) // atan2 outputs the value of -π to π (radians)
// We are then converting it to 0 to 2π and then to degrees // We are then converting it to 0 to 2π and then to degrees
if (a == Pitch) { if (a == Pitch) {
double angle = (atan2(accYval,accZval)+PI)*RAD_TO_DEG; double angle = (atan2(accYval, accZval) + PI) * RAD_TO_DEG;
return angle; return angle;
} else { } else {
double angle = (atan2(accXval,accZval)+PI)*RAD_TO_DEG; double angle = (atan2(accXval, accZval) + PI) * RAD_TO_DEG;
return angle; return angle;
} }
} else } else
return 0; return 0;
} }
bool PS3USB::getStatus(Status c) { bool PS3USB::getStatus(Status c) {
if (readBuf == NULL) if (readBuf == NULL)
return false;
if (readBuf[((uint16_t)c >> 8) - 9] == ((uint8_t)c & 0xff))
return true;
return false; return false;
if (readBuf[((uint16_t)c >> 8)-9] == ((uint8_t)c & 0xff))
return true;
return false;
} }
String PS3USB::getStatusString() { String PS3USB::getStatusString() {
if (PS3Connected || PS3NavigationConnected) { if (PS3Connected || PS3NavigationConnected) {
char statusOutput[100]; char statusOutput[100];
strcpy(statusOutput,"ConnectionStatus: "); strcpy(statusOutput, "ConnectionStatus: ");
if (getStatus(Plugged)) strcat(statusOutput,"Plugged"); if (getStatus(Plugged)) strcat(statusOutput, "Plugged");
else if (getStatus(Unplugged)) strcat(statusOutput,"Unplugged"); else if (getStatus(Unplugged)) strcat(statusOutput, "Unplugged");
else strcat(statusOutput,"Error"); else strcat(statusOutput, "Error");
strcat(statusOutput," - PowerRating: "); strcat(statusOutput, " - PowerRating: ");
if (getStatus(Charging)) strcat(statusOutput,"Charging"); if (getStatus(Charging)) strcat(statusOutput, "Charging");
else if (getStatus(NotCharging)) strcat(statusOutput,"Not Charging"); else if (getStatus(NotCharging)) strcat(statusOutput, "Not Charging");
else if (getStatus(Shutdown)) strcat(statusOutput,"Shutdown"); else if (getStatus(Shutdown)) strcat(statusOutput, "Shutdown");
else if (getStatus(Dying)) strcat(statusOutput,"Dying"); else if (getStatus(Dying)) strcat(statusOutput, "Dying");
else if (getStatus(Low)) strcat(statusOutput,"Low"); else if (getStatus(Low)) strcat(statusOutput, "Low");
else if (getStatus(High)) strcat(statusOutput,"High"); else if (getStatus(High)) strcat(statusOutput, "High");
else if (getStatus(Full)) strcat(statusOutput,"Full"); else if (getStatus(Full)) strcat(statusOutput, "Full");
else strcat(statusOutput,"Error"); else strcat(statusOutput, "Error");
strcat(statusOutput," - WirelessStatus: "); strcat(statusOutput, " - WirelessStatus: ");
if (getStatus(CableRumble)) strcat(statusOutput,"Cable - Rumble is on"); if (getStatus(CableRumble)) strcat(statusOutput, "Cable - Rumble is on");
else if (getStatus(Cable)) strcat(statusOutput,"Cable - Rumble is off"); else if (getStatus(Cable)) strcat(statusOutput, "Cable - Rumble is off");
else if (getStatus(BluetoothRumble)) strcat(statusOutput,"Bluetooth - Rumble is on"); else if (getStatus(BluetoothRumble)) strcat(statusOutput, "Bluetooth - Rumble is on");
else if (getStatus(Bluetooth)) strcat(statusOutput,"Bluetooth - Rumble is off"); else if (getStatus(Bluetooth)) strcat(statusOutput, "Bluetooth - Rumble is off");
else strcat(statusOutput,"Error"); else strcat(statusOutput, "Error");
return statusOutput; return statusOutput;
} }
} }
/* Playstation Sixaxis Dualshock and Navigation Controller commands */ /* Playstation Sixaxis Dualshock and Navigation Controller commands */
void PS3USB::PS3_Command(uint8_t* data, uint16_t nbytes) { void PS3USB::PS3_Command(uint8_t* data, uint16_t nbytes) {
//bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x01), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL); pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x01, 0x02, 0x00, nbytes, nbytes, data, NULL);
} }
void PS3USB::setAllOff() { void PS3USB::setAllOff() {
for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++) for (uint8_t i = 0; i < PS3_REPORT_BUFFER_SIZE; i++)
writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer writeBuf[i] = pgm_read_byte(&PS3_REPORT_BUFFER[i]); // Reset buffer
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
}
void PS3USB::setRumbleOff() {
writeBuf[1] = 0x00;
writeBuf[2] = 0x00;//low mode off
writeBuf[3] = 0x00;
writeBuf[4] = 0x00;//high mode off
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
}
void PS3USB::setRumbleOn(Rumble mode) {
/* Still not totally sure how it works, maybe something like this instead?
* 3 - duration_right
* 4 - power_right
* 5 - duration_left
* 6 - power_left
*/
if ((mode & 0x30) > 0) {
writeBuf[1] = 0xfe;
writeBuf[3] = 0xfe;
if (mode == RumbleHigh) {
writeBuf[2] = 0;//low mode off
writeBuf[4] = 0xff;//high mode on
}
else {
writeBuf[2] = 0xff;//low mode on
writeBuf[4] = 0;//high mode off
}
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
}
} }
void PS3USB::setRumbleOff() {
writeBuf[1] = 0x00;
writeBuf[2] = 0x00; //low mode off
writeBuf[3] = 0x00;
writeBuf[4] = 0x00; //high mode off
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
}
void PS3USB::setRumbleOn(Rumble mode) {
/* Still not totally sure how it works, maybe something like this instead?
* 3 - duration_right
* 4 - power_right
* 5 - duration_left
* 6 - power_left
*/
if ((mode & 0x30) > 0) {
writeBuf[1] = 0xfe;
writeBuf[3] = 0xfe;
if (mode == RumbleHigh) {
writeBuf[2] = 0; //low mode off
writeBuf[4] = 0xff; //high mode on
} else {
writeBuf[2] = 0xff; //low mode on
writeBuf[4] = 0; //high mode off
}
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
}
}
void PS3USB::setLedOff(LED a) { void PS3USB::setLedOff(LED a) {
writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1)); writeBuf[9] &= ~((uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1));
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
} }
void PS3USB::setLedOn(LED a) { void PS3USB::setLedOn(LED a) {
writeBuf[9] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); writeBuf[9] |= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
} }
void PS3USB::setLedToggle(LED a) { void PS3USB::setLedToggle(LED a) {
writeBuf[9] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1); writeBuf[9] ^= (uint8_t)((pgm_read_byte(&LEDS[(uint8_t)a]) & 0x0f) << 1);
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
} }
void PS3USB::setBdaddr(uint8_t* BDADDR) { void PS3USB::setBdaddr(uint8_t* BDADDR) {
/* Set the internal bluetooth address */ /* Set the internal bluetooth address */
uint8_t buf[8]; uint8_t buf[8];
buf[0] = 0x01; buf[0] = 0x01;
buf[1] = 0x00; buf[1] = 0x00;
for (uint8_t i = 0; i < 6; i++) for (uint8_t i = 0; i < 6; i++)
buf[i+2] = BDADDR[5 - i];//Copy into buffer, has to be written reversed buf[i + 2] = BDADDR[5 - i]; //Copy into buffer, has to be written reversed
//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) //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)
pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL); pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF5, 0x03, 0x00, 8, 8, buf, NULL);
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
for(int8_t i = 5; i > 0; i--) { for (int8_t i = 5; i > 0; i--) {
PrintHex<uint8_t>(my_bdaddr[i], 0x80); PrintHex<uint8_t > (my_bdaddr[i], 0x80);
Serial.print(":"); Serial.print(":");
} }
PrintHex<uint8_t>(my_bdaddr[0], 0x80); PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif #endif
return; return;
} }
void PS3USB::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navigation controller to send data via USB
uint8_t cmd_buf[4];
cmd_buf[0] = 0x42;// Special PS3 Controller enable commands
cmd_buf[1] = 0x0c;
cmd_buf[2] = 0x00;
cmd_buf[3] = 0x00;
//bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) void PS3USB::enable_sixaxis() { //Command used to enable the Dualshock 3 and Navigation controller to send data via USB
pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL); uint8_t cmd_buf[4];
cmd_buf[0] = 0x42; // Special PS3 Controller enable commands
cmd_buf[1] = 0x0c;
cmd_buf[2] = 0x00;
cmd_buf[3] = 0x00;
//bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0xF4), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0xF4, 0x03, 0x00, 4, 4, cmd_buf, NULL);
} }
/* Playstation Move Controller commands */ /* Playstation Move Controller commands */
void PS3USB::Move_Command(uint8_t* data, uint16_t nbytes) { void PS3USB::Move_Command(uint8_t* data, uint16_t nbytes) {
pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data); pUsb->outTransfer(bAddress, epInfo[ PS3_OUTPUT_PIPE ].epAddr, nbytes, data);
} }
void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values void PS3USB::moveSetBulb(uint8_t r, uint8_t g, uint8_t b) { //Use this to set the Color using RGB values
// set the Bulb's values into the write buffer // set the Bulb's values into the write buffer
writeBuf[2] = r; writeBuf[2] = r;
writeBuf[3] = g; writeBuf[3] = g;
writeBuf[4] = b; writeBuf[4] = b;
Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE);
} }
void PS3USB::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in "enums.h" void PS3USB::moveSetBulb(Colors color) { //Use this to set the Color using the predefined colors in "enums.h"
moveSetBulb((uint8_t)(color >> 16),(uint8_t)(color >> 8),(uint8_t)(color)); moveSetBulb((uint8_t)(color >> 16), (uint8_t)(color >> 8), (uint8_t)(color));
} }
void PS3USB::moveSetRumble(uint8_t rumble) { void PS3USB::moveSetRumble(uint8_t rumble) {
#ifdef DEBUG #ifdef DEBUG
if(rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100) if (rumble < 64 && rumble != 0) // The rumble value has to at least 64, or approximately 25% (64/255*100)
Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80); Notify(PSTR("\r\nThe rumble value has to at least 64, or approximately 25%"), 0x80);
#endif #endif
//set the rumble value into the write buffer //set the rumble value into the write buffer
writeBuf[6] = rumble; writeBuf[6] = rumble;
Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE); Move_Command(writeBuf, MOVE_REPORT_BUFFER_SIZE);
} }
void PS3USB::setMoveBdaddr(uint8_t* BDADDR) { void PS3USB::setMoveBdaddr(uint8_t* BDADDR) {
/* Set the internal bluetooth address */ /* Set the internal bluetooth address */
uint8_t buf[11]; uint8_t buf[11];
buf[0] = 0x05; buf[0] = 0x05;
buf[7] = 0x10; buf[7] = 0x10;
buf[8] = 0x01; buf[8] = 0x01;
buf[9] = 0x02; buf[9] = 0x02;
buf[10] = 0x12; buf[10] = 0x12;
for (uint8_t i = 0; i < 6; i++) for (uint8_t i = 0; i < 6; i++)
buf[i + 1] = BDADDR[i]; buf[i + 1] = BDADDR[i];
//bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data) //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x05), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress,epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00,11,11, buf, NULL); pUsb->ctrlReq(bAddress, epInfo[PS3_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x05, 0x03, 0x00, 11, 11, buf, NULL);
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80); Notify(PSTR("\r\nBluetooth Address was set to: "), 0x80);
for(int8_t i = 5; i > 0; i--) { for (int8_t i = 5; i > 0; i--) {
PrintHex<uint8_t>(my_bdaddr[i], 0x80); PrintHex<uint8_t > (my_bdaddr[i], 0x80);
Serial.print(":"); Serial.print(":");
} }
PrintHex<uint8_t>(my_bdaddr[0], 0x80); PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif #endif
return; return;
} }

338
PS3USB.h
View file

@ -63,186 +63,192 @@
*/ */
class PS3USB : public USBDeviceConfig { class PS3USB : public USBDeviceConfig {
public: public:
/** /**
* Constructor for the PS3USB class. * Constructor for the PS3USB class.
* @param pUsb Pointer to USB class instance. * @param pUsb Pointer to USB class instance.
* @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0 * @param btadr5,btadr4,btadr3,btadr2,btadr1,btadr0
* Pass your dongles Bluetooth address into the constructor, * Pass your dongles Bluetooth address into the constructor,
* so you are able to pair the controller with a Bluetooth dongle. * so you are able to pair the controller with a Bluetooth dongle.
*/ */
PS3USB(USB *pUsb, uint8_t btadr5=0, uint8_t btadr4=0, uint8_t btadr3=0, uint8_t btadr2=0, uint8_t btadr1=0, uint8_t btadr0=0); PS3USB(USB *pUsb, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0);
/** @name USBDeviceConfig implementation */ /** @name USBDeviceConfig implementation */
/** /**
* Initialize the PS3 Controller. * Initialize the PS3 Controller.
* @param parent Hub number. * @param parent Hub number.
* @param port Port number on the hub. * @param port Port number on the hub.
* @param lowspeed Speed of the device. * @param lowspeed Speed of the device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/** /**
* Release the USB device. * Release the USB device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Release(); virtual uint8_t Release();
/** /**
* Poll the USB Input endpoins and run the state machines. * Poll the USB Input endpoins and run the state machines.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Poll(); virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() { return bAddress; };
/**
* Used to check if the controller has been initialized.
* @return True if it's ready.
*/
virtual bool isReady() { return bPollEnable; };
/**@}*/
/** /**
* Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller. * Get the device address.
* @param BDADDR Your dongles Bluetooth address. * @return The device address.
*/ */
void setBdaddr(uint8_t* BDADDR); virtual uint8_t GetAddress() {
/** return bAddress;
* Used to set the Bluetooth address inside the Move controller. };
* @param BDADDR Your dongles Bluetooth address.
*/
void setMoveBdaddr(uint8_t* BDADDR);
/** @name PS3 Controller functions */ /**
/** * Used to check if the controller has been initialized.
* getButtonPress(Button b) will return true as long as the button is held down. * @return True if it's ready.
* */
* While getButtonClick(Button b) will only return it once. virtual bool isReady() {
* return bPollEnable;
* So you instance if you need to increase a variable once you would use getButtonClick(Button b), };
* but if you need to drive a robot forward you would use getButtonPress(Button b). /**@}*/
*/
bool getButtonPress(Button b);
bool getButtonClick(Button b);
/**@}*/
/** @name PS3 Controller functions */
/**
* Used to get the analog value from button presses.
* @param a The ::Button to read.
* The supported buttons are:
* ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
* ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
* @return Analog value in the range of 0-255.
*/
uint8_t getAnalogButton(Button a);
/**
* Used to read the analog joystick.
* @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
* @return Return the analog value in the range of 0-255.
*/
uint8_t getAnalogHat(AnalogHat a);
/**
* Used to read the sensors inside the Dualshock 3 controller.
* @param a
* The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.
* @return Return the raw sensor value.
*/
uint16_t getSensor(Sensor a);
/**
* Use this to get ::Pitch and ::Roll calculated using the accelerometer.
* @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360.
*/
double getAngle(Angle a);
/**
* Get the ::Status from the controller.
* @param c The ::Status you want to read.
* @return True if correct and false if not.
*/
bool getStatus(Status c);
/**
* Read all the available ::Status from the controller.
* @return One large string with all the information.
*/
String getStatusString();
/** Used to set all LEDs and ::Rumble off. */ /**
void setAllOff(); * Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller.
/** Turn off ::Rumble. */ * @param BDADDR Your dongles Bluetooth address.
void setRumbleOff(); */
/** void setBdaddr(uint8_t* BDADDR);
* Turn on ::Rumble. /**
* @param mode Either ::RumbleHigh or ::RumbleLow. * Used to set the Bluetooth address inside the Move controller.
*/ * @param BDADDR Your dongles Bluetooth address.
void setRumbleOn(Rumble mode); */
/** void setMoveBdaddr(uint8_t* BDADDR);
* Turn the specific ::LED off.
* @param a The ::LED to turn off.
*/
void setLedOff(LED a);
/**
* Turn the specific ::LED on.
* @param a The ::LED to turn on.
*/
void setLedOn(LED a);
/**
* Toggle the specific ::LED.
* @param a The ::LED to toggle.
*/
void setLedToggle(LED a);
/** /** @name PS3 Controller functions */
* Use this to set the Color using RGB values. /**
* @param r,g,b RGB value. * getButtonPress(Button b) will return true as long as the button is held down.
*/ *
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b); * While getButtonClick(Button b) will only return it once.
/** *
* Use this to set the color using the predefined colors in ::Colors. * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
* @param color The desired color. * but if you need to drive a robot forward you would use getButtonPress(Button b).
*/ */
void moveSetBulb(Colors color); bool getButtonPress(Button b);
/** bool getButtonClick(Button b);
* Set the rumble value inside the Move controller. /**@}*/
* @param rumble The desired value in the range from 64-255. /** @name PS3 Controller functions */
*/ /**
void moveSetRumble(uint8_t rumble); * Used to get the analog value from button presses.
/**@}*/ * @param a The ::Button to read.
* The supported buttons are:
* ::UP, ::RIGHT, ::DOWN, ::LEFT, ::L1, ::L2, ::R1, ::R2,
* ::TRIANGLE, ::CIRCLE, ::CROSS, ::SQUARE, and ::T.
* @return Analog value in the range of 0-255.
*/
uint8_t getAnalogButton(Button a);
/**
* Used to read the analog joystick.
* @param a ::LeftHatX, ::LeftHatY, ::RightHatX, and ::RightHatY.
* @return Return the analog value in the range of 0-255.
*/
uint8_t getAnalogHat(AnalogHat a);
/**
* Used to read the sensors inside the Dualshock 3 controller.
* @param a
* The Dualshock 3 has a 3-axis accelerometer and a 1-axis gyro inside.
* @return Return the raw sensor value.
*/
uint16_t getSensor(Sensor a);
/**
* Use this to get ::Pitch and ::Roll calculated using the accelerometer.
* @param a Either ::Pitch or ::Roll.
* @return Return the angle in the range of 0-360.
*/
double getAngle(Angle a);
/**
* Get the ::Status from the controller.
* @param c The ::Status you want to read.
* @return True if correct and false if not.
*/
bool getStatus(Status c);
/**
* Read all the available ::Status from the controller.
* @return One large string with all the information.
*/
String getStatusString();
/** Variable used to indicate if the normal playstation controller is successfully connected. */ /** Used to set all LEDs and ::Rumble off. */
bool PS3Connected; void setAllOff();
/** Variable used to indicate if the move controller is successfully connected. */ /** Turn off ::Rumble. */
bool PS3MoveConnected; void setRumbleOff();
/** Variable used to indicate if the navigation controller is successfully connected. */ /**
bool PS3NavigationConnected; * Turn on ::Rumble.
* @param mode Either ::RumbleHigh or ::RumbleLow.
*/
void setRumbleOn(Rumble mode);
/**
* Turn the specific ::LED off.
* @param a The ::LED to turn off.
*/
void setLedOff(LED a);
/**
* Turn the specific ::LED on.
* @param a The ::LED to turn on.
*/
void setLedOn(LED a);
/**
* Toggle the specific ::LED.
* @param a The ::LED to toggle.
*/
void setLedToggle(LED a);
/**
* Use this to set the Color using RGB values.
* @param r,g,b RGB value.
*/
void moveSetBulb(uint8_t r, uint8_t g, uint8_t b);
/**
* Use this to set the color using the predefined colors in ::Colors.
* @param color The desired color.
*/
void moveSetBulb(Colors color);
/**
* Set the rumble value inside the Move controller.
* @param rumble The desired value in the range from 64-255.
*/
void moveSetRumble(uint8_t rumble);
/**@}*/
/** Variable used to indicate if the normal playstation controller is successfully connected. */
bool PS3Connected;
/** Variable used to indicate if the move controller is successfully connected. */
bool PS3MoveConnected;
/** Variable used to indicate if the navigation controller is successfully connected. */
bool PS3NavigationConnected;
protected: protected:
/** Pointer to USB class instance. */ /** Pointer to USB class instance. */
USB *pUsb; USB *pUsb;
/** Device address. */ /** Device address. */
uint8_t bAddress; uint8_t bAddress;
/** Endpoint info structure. */ /** Endpoint info structure. */
EpInfo epInfo[PS3_MAX_ENDPOINTS]; EpInfo epInfo[PS3_MAX_ENDPOINTS];
private: private:
bool bPollEnable; bool bPollEnable;
uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values
uint32_t ButtonState; uint32_t ButtonState;
uint32_t OldButtonState; uint32_t OldButtonState;
uint32_t ButtonClickState; uint32_t ButtonClickState;
uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
void readReport(); // read incoming data void readReport(); // read incoming data
void printReport(); // print incoming date - Uncomment for debugging void printReport(); // print incoming date - Uncomment for debugging
/* Private commands */ /* Private commands */
void PS3_Command(uint8_t* data, uint16_t nbytes); void PS3_Command(uint8_t* data, uint16_t nbytes);
void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB
void Move_Command(uint8_t* data, uint16_t nbytes); void Move_Command(uint8_t* data, uint16_t nbytes);
}; };
#endif #endif

1425
SPP.cpp

File diff suppressed because it is too large Load diff

508
SPP.h
View file

@ -87,276 +87,310 @@
#define BT_RFCOMM_RLS_CMD 0x53 #define BT_RFCOMM_RLS_CMD 0x53
#define BT_RFCOMM_RLS_RSP 0x51 #define BT_RFCOMM_RLS_RSP 0x51
#define BT_RFCOMM_NSC_RSP 0x11 #define BT_RFCOMM_NSC_RSP 0x11
*/ */
/** This BluetoothService class implements the Serial Port Protocol (SPP). */ /** This BluetoothService class implements the Serial Port Protocol (SPP). */
class SPP : public BluetoothService { class SPP : public BluetoothService {
public: public:
/** /**
* Constructor for the SPP class. * Constructor for the SPP class.
* @param p Pointer to BTD class instance. * @param p Pointer to BTD class instance.
* @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used. * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used.
* @param pin Write the pin to BTD#btdPin. If argument is omitted, then "1234" will be used. * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "1234" will be used.
*/ */
SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234"); SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234");
/** @name BluetoothService implementation */ /** @name BluetoothService implementation */
/** /**
* Used to pass acldata to the services. * Used to pass acldata to the services.
* @param ACLData Incoming acldata. * @param ACLData Incoming acldata.
*/ */
virtual void ACLData(uint8_t* ACLData); virtual void ACLData(uint8_t* ACLData);
/** Used to establish the connection automatically. */ /** Used to establish the connection automatically. */
virtual void Run(); virtual void Run();
/** Use this to reset the service. */ /** Use this to reset the service. */
virtual void Reset(); virtual void Reset();
/** Used this to disconnect the virtual serial port. */ /** Used this to disconnect the virtual serial port. */
virtual void disconnect(); virtual void disconnect();
/**@}*/ /**@}*/
/** Variable used to indicate if the connection is established. */ /** Variable used to indicate if the connection is established. */
bool connected; bool connected;
/** @name Serial port profile (SPP) Print functions */ /** @name Serial port profile (SPP) Print functions */
/** /**
* Used to send Arduino String data type. * Used to send Arduino String data type.
* @param str String to send. * @param str String to send.
*/ */
void print(const String &str); void print(const String &str);
/** /**
* Same as print(const String &str), but will include newline and carriage return. * Same as print(const String &str), but will include newline and carriage return.
* @param str String to send. * @param str String to send.
*/ */
void println(const String &str); void println(const String &str);
/** /**
* Used to send standard strings. * Used to send standard strings.
* @param str String to send. * @param str String to send.
*/ */
void print(const char* str); void print(const char* str);
/** /**
* Same as print(const char* str), but will include newline and carriage return. * Same as print(const char* str), but will include newline and carriage return.
* @param str String to send. * @param str String to send.
*/ */
void println(const char* str); void println(const char* str);
/** /**
* Used to send single bytes. * Used to send single bytes.
* @param data Data to send. * @param data Data to send.
*/ */
void print(uint8_t data) { print(&data,1); }; void print(uint8_t data) {
/** print(&data, 1);
* Same as print(uint8_t data), but will include newline and carriage return. };
* @param data Data to send. /**
*/ * Same as print(uint8_t data), but will include newline and carriage return.
void println(uint8_t data); * @param data Data to send.
*/
void println(uint8_t data);
/** /**
* Used to send arrays. * Used to send arrays.
* @param array Array to send. * @param array Array to send.
* @param length Number of bytes to send. * @param length Number of bytes to send.
*/ */
void print(uint8_t* array, uint8_t length); void print(uint8_t* array, uint8_t length);
/** /**
* Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return. * Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return.
* @param array Array to send. * @param array Array to send.
* @param length Number of bytes to send. * @param length Number of bytes to send.
*/ */
void println(uint8_t* array, uint8_t length); void println(uint8_t* array, uint8_t length);
/** /**
* Used to print strings stored in flash. * Used to print strings stored in flash.
* Use "SerialBT.print(F("String"));" to print a string stored in flash. * Use "SerialBT.print(F("String"));" to print a string stored in flash.
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory. * @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
*/ */
void print(const __FlashStringHelper *ifsh) { printFlashString(ifsh,false); }; void print(const __FlashStringHelper *ifsh) {
/** printFlashString(ifsh, false);
* Same as print(const __FlashStringHelper *ifsh), but will include newline and carriage return. };
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
*/ /**
void println(const __FlashStringHelper *ifsh) { printFlashString(ifsh,true); }; * Same as print(const __FlashStringHelper *ifsh), but will include newline and carriage return.
/** * @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
* Helper function to print a string stored in flash. */
* @param ifsh String stored in flash you want to print. void println(const __FlashStringHelper *ifsh) {
* @param newline Set this to true to include newline and carriage return. printFlashString(ifsh, true);
*/ };
void printFlashString(const __FlashStringHelper *ifsh, bool newline); /**
* Helper function to print a string stored in flash.
* @param ifsh String stored in flash you want to print.
* @param newline Set this to true to include newline and carriage return.
*/
void printFlashString(const __FlashStringHelper *ifsh, bool newline);
/** Use this to print newline and carriage return. */ /** Use this to print newline and carriage return. */
void println(void); void println(void);
/** /**
* Used to print unsigned integers. * Used to print unsigned integers.
* @param n Unsigned integer to send. * @param n Unsigned integer to send.
*/ */
void printNumber(uint8_t n) { printNumber((uint32_t)n); }; void printNumber(uint8_t n) {
/** printNumber((uint32_t) n);
* Same as printNumber(uint8_t n), but will include newline and carriage return. };
* @param n Unsigned integer to send.
*/
void printNumberln(uint8_t n) { printNumberln((uint32_t)n); };
/**
* Used to print signed integers.
* @param n Signed integer to send.
*/
void printNumber(int8_t n) { printNumber((int32_t)n); };
/**
* Same as printNumber(int8_t n), but will include newline and carriage return.
* @param n Signed integer to send.
*/
void printNumberln(int8_t n) { printNumberln((int32_t)n); };
/** /**
* Used to print unsigned integers. * Same as printNumber(uint8_t n), but will include newline and carriage return.
* @param n Unsigned integer to send. * @param n Unsigned integer to send.
*/ */
void printNumber(uint16_t n) { printNumber((uint32_t)n); }; void printNumberln(uint8_t n) {
/** printNumberln((uint32_t) n);
* Same as printNumber(uint16_t n), but will include newline and carriage return. };
* @param n Unsigned integer to send.
*/
void printNumberln(uint16_t n) { printNumberln((uint32_t)n); };
/**
* Used to print signed integers.
* @param n Signed integer to send.
*/
void printNumber(int16_t n) { printNumber((int32_t)n); };
/**
* Same as printNumber(int16_t n), but will include newline and carriage return.
* @param n Signed integer to send.
*/
void printNumberln(int16_t n) { printNumberln((int32_t)n); };
/** /**
* Used to print unsigned integers. * Used to print signed integers.
* @param n Unsigned integer to send. * @param n Signed integer to send.
*/ */
void printNumber(uint32_t n); void printNumber(int8_t n) {
/** printNumber((int32_t) n);
* Same as printNumber(uint32_t n), but will include newline and carriage return. };
* @param n Unsigned integer to send.
*/
void printNumberln(uint32_t n);
/** /**
* Used to print signed integers. * Same as printNumber(int8_t n), but will include newline and carriage return.
* @param n Signed integer to send. * @param n Signed integer to send.
*/ */
void printNumber(int32_t n); void printNumberln(int8_t n) {
/** printNumberln((int32_t) n);
* Same as printNumber(int32_t n), but will include newline and carriage return. };
* @param n Signed integer to send.
*/
void printNumberln(int32_t n);
/** /**
* Helper function to convert from an unsigned integer to a string. * Used to print unsigned integers.
* @param input Unsigned integer to convert. * @param n Unsigned integer to send.
* @param output Output buffer. */
*/ void printNumber(uint16_t n) {
void intToString(int32_t input, char* output); printNumber((uint32_t) n);
/** };
* Helper function to convert from a signed integer to a string.
* @param input Signed integer to convert.
* @param output Output buffer.
*/
void intToString(uint32_t input, char* output);
/** /**
* Used to print floating-point numbers. * Same as printNumber(uint16_t n), but will include newline and carriage return.
* @param n Floating-point number to print. * @param n Unsigned integer to send.
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used. */
*/ void printNumberln(uint16_t n) {
void printNumber(double n, uint8_t digits = 2); printNumberln((uint32_t) n);
/** };
* Same as printNumber(double n, uint8_t digits), but will include newline and carriage return.
* @param n Floating-point number to print.
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used.
*/
void printNumberln(double n, uint8_t digits = 2);
/**
* Helper function to convert from a double to a string.
* @param input Floating-point number to convert.
* @param output Output buffer.
* @param digits Number of digits to convert. If argument is omitted, then 2 digits will be used.
*/
void doubleToString(double input, char* output, uint8_t digits = 2);
/** /**
* Get number of bytes waiting to be read. * Used to print signed integers.
* @return Return the number of bytes ready to be read. * @param n Signed integer to send.
*/ */
uint8_t available() { return rfcommAvailable; }; void printNumber(int16_t n) {
/** printNumber((int32_t) n);
* Used to read the buffer. };
* @return Return the byte. Will return 0 if no byte is available.
*/ /**
uint8_t read(); * Same as printNumber(int16_t n), but will include newline and carriage return.
/** Discard all the bytes in the buffer. */ * @param n Signed integer to send.
void flush() { rfcommAvailable = 0; }; */
/**@}*/ void printNumberln(int16_t n) {
printNumberln((int32_t) n);
};
/**
* Used to print unsigned integers.
* @param n Unsigned integer to send.
*/
void printNumber(uint32_t n);
/**
* Same as printNumber(uint32_t n), but will include newline and carriage return.
* @param n Unsigned integer to send.
*/
void printNumberln(uint32_t n);
/**
* Used to print signed integers.
* @param n Signed integer to send.
*/
void printNumber(int32_t n);
/**
* Same as printNumber(int32_t n), but will include newline and carriage return.
* @param n Signed integer to send.
*/
void printNumberln(int32_t n);
/**
* Helper function to convert from an unsigned integer to a string.
* @param input Unsigned integer to convert.
* @param output Output buffer.
*/
void intToString(int32_t input, char* output);
/**
* Helper function to convert from a signed integer to a string.
* @param input Signed integer to convert.
* @param output Output buffer.
*/
void intToString(uint32_t input, char* output);
/**
* Used to print floating-point numbers.
* @param n Floating-point number to print.
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used.
*/
void printNumber(double n, uint8_t digits = 2);
/**
* Same as printNumber(double n, uint8_t digits), but will include newline and carriage return.
* @param n Floating-point number to print.
* @param digits Number of digits to send. If argument is omitted, then 2 digits will be used.
*/
void printNumberln(double n, uint8_t digits = 2);
/**
* Helper function to convert from a double to a string.
* @param input Floating-point number to convert.
* @param output Output buffer.
* @param digits Number of digits to convert. If argument is omitted, then 2 digits will be used.
*/
void doubleToString(double input, char* output, uint8_t digits = 2);
/**
* Get number of bytes waiting to be read.
* @return Return the number of bytes ready to be read.
*/
uint8_t available() {
return rfcommAvailable;
};
/**
* Used to read the buffer.
* @return Return the byte. Will return 0 if no byte is available.
*/
uint8_t read();
/** Discard all the bytes in the buffer. */
void flush() {
rfcommAvailable = 0;
};
/**@}*/
private: private:
/* Bluetooth dongle library pointer */ /* Bluetooth dongle library pointer */
BTD *pBtd; BTD *pBtd;
/* Set true when a channel is created */ /* Set true when a channel is created */
bool SDPConnected; bool SDPConnected;
bool RFCOMMConnected; bool RFCOMMConnected;
uint16_t hci_handle; // The HCI Handle for the connection uint16_t hci_handle; // The HCI Handle for the connection
/* Variables used by L2CAP state maschines */ /* Variables used by L2CAP state maschines */
uint8_t l2cap_sdp_state; uint8_t l2cap_sdp_state;
uint8_t l2cap_rfcomm_state; uint8_t l2cap_rfcomm_state;
uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events
uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
/* L2CAP Channels */ /* L2CAP Channels */
uint8_t sdp_scid[2]; // L2CAP source CID for SDP uint8_t sdp_scid[2]; // L2CAP source CID for SDP
uint8_t sdp_dcid[2]; // 0x0050 uint8_t sdp_dcid[2]; // 0x0050
uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM
uint8_t rfcomm_dcid[2]; // 0x0051 uint8_t rfcomm_dcid[2]; // 0x0051
uint8_t identifier; // Identifier for command uint8_t identifier; // Identifier for command
/* RFCOMM Variables */ /* RFCOMM Variables */
uint8_t rfcommChannel; uint8_t rfcommChannel;
uint8_t rfcommChannelConnection; // This is the channel the SPP chanel will be running at uint8_t rfcommChannelConnection; // This is the channel the SPP chanel will be running at
uint8_t rfcommDirection; uint8_t rfcommDirection;
uint8_t rfcommCommandResponse; uint8_t rfcommCommandResponse;
uint8_t rfcommChannelType; uint8_t rfcommChannelType;
uint8_t rfcommPfBit; uint8_t rfcommPfBit;
unsigned long timer; unsigned long timer;
bool waitForLastCommand; bool waitForLastCommand;
bool creditSent; bool creditSent;
uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
uint8_t rfcommAvailable; uint8_t rfcommAvailable;
bool firstMessage; // Used to see if it's the first SDP request received bool firstMessage; // Used to see if it's the first SDP request received
uint8_t bytesRead; // Counter to see when it's time to send more credit uint8_t bytesRead; // Counter to see when it's time to send more credit
/* State machines */ /* State machines */
void SDP_task(); // SDP state machine void SDP_task(); // SDP state machine
void RFCOMM_task(); // RFCOMM state machine void RFCOMM_task(); // RFCOMM state machine
/* SDP Commands */ /* SDP Commands */
void SDP_Command(uint8_t* data, uint8_t nbytes); void SDP_Command(uint8_t* data, uint8_t nbytes);
void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow); void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow); void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow); void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
/* RFCOMM Commands */ /* RFCOMM Commands */
void RFCOMM_Command(uint8_t* data, uint8_t nbytes); void RFCOMM_Command(uint8_t* data, uint8_t nbytes);
void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length); void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length);
void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit); void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit);
uint8_t calcFcs(uint8_t *data); uint8_t calcFcs(uint8_t *data);
uint8_t __crc(uint8_t* data); uint8_t __crc(uint8_t* data);
}; };
#endif #endif

View file

@ -176,7 +176,7 @@ uint8_t USB::ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bReque
// Invoke callback function if inTransfer completed successfuly and callback function pointer is specified // Invoke callback function if inTransfer completed successfuly and callback function pointer is specified
if (!rcode && p) if (!rcode && p)
((USBReadParser*) p)->Parse(read, dataptr, total - left); ((USBReadParser*)p)->Parse(read, dataptr, total - left);
left -= read; left -= read;
@ -236,14 +236,14 @@ uint8_t USB::InTransfer(EpInfo *pep, uint16_t nak_limit, uint16_t *nbytesptr, ui
/* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */ /* the only case when absense of RCVDAVIRQ makes sense is when toggle error occured. Need to add handling for that */
if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) { if ((regRd(rHIRQ) & bmRCVDAVIRQ) == 0) {
//printf("Problem! NO RCVDAVIRQ!\r\n"); //printf("Problem! NO RCVDAVIRQ!\r\n");
rcode = 0xf0; //receive error rcode = 0xf0; //receive error
break; break;
} }
pktsize = regRd(rRCVBC); //number of received bytes pktsize = regRd(rRCVBC); //number of received bytes
//printf("Got %i bytes ", pktsize); //printf("Got %i bytes ", pktsize);
assert(pktsize <= nbytes); assert(pktsize <= nbytes);
int16_t mem_left = (int16_t) nbytes - *((int16_t*) nbytesptr); int16_t mem_left = (int16_t)nbytes - *((int16_t*)nbytesptr);
if (mem_left < 0) if (mem_left < 0)
mem_left = 0; mem_left = 0;
@ -591,7 +591,7 @@ uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint8_t conf, USBReadParser
if (ret) if (ret)
return ret; return ret;
uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength; uint16_t total = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength;
//USBTRACE2("\r\ntotal conf.size:", total); //USBTRACE2("\r\ntotal conf.size:", total);

20
Usb.h
View file

@ -147,7 +147,7 @@ typedef struct {
uint8_t recipient : 5; // Recipient of the request uint8_t recipient : 5; // Recipient of the request
uint8_t type : 2; // Type of request uint8_t type : 2; // Type of request
uint8_t direction : 1; // Direction of data X-fer uint8_t direction : 1; // Direction of data X-fer
}__attribute__((packed)); } __attribute__((packed));
} ReqType_u; } ReqType_u;
uint8_t bRequest; // 1 Request uint8_t bRequest; // 1 Request
@ -157,7 +157,7 @@ typedef struct {
struct { struct {
uint8_t wValueLo; uint8_t wValueLo;
uint8_t wValueHi; uint8_t wValueHi;
}__attribute__((packed)); } __attribute__((packed));
} wVal_u; } wVal_u;
uint16_t wIndex; // 4 Depends on bRequest uint16_t wIndex; // 4 Depends on bRequest
uint16_t wLength; // 6 Depends on bRequest uint16_t wLength; // 6 Depends on bRequest
@ -190,12 +190,12 @@ public:
}; };
AddressPool& GetAddressPool() { AddressPool& GetAddressPool() {
return (AddressPool&) addrPool; return(AddressPool&) addrPool;
}; };
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) { uint8_t RegisterDeviceClass(USBDeviceConfig *pdev) {
for (uint8_t i = 0; i < USB_NUMDEVICES; i++) { for(uint8_t i = 0; i < USB_NUMDEVICES; i++) {
if (!devConfig[i]) { if(!devConfig[i]) {
devConfig[i] = pdev; devConfig[i] = pdev;
return 0; return 0;
} }
@ -250,27 +250,27 @@ private:
//get device descriptor //get device descriptor
inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USB::getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t* dataptr) {
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr)); return( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, 0x00, USB_DESCRIPTOR_DEVICE, 0x0000, nbytes, dataptr));
} }
//get configuration descriptor //get configuration descriptor
inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) { inline uint8_t USB::getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t* dataptr) {
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr)); return( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, conf, USB_DESCRIPTOR_CONFIGURATION, 0x0000, nbytes, dataptr));
} }
//get string descriptor //get string descriptor
inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) { inline uint8_t USB::getStrDescr(uint8_t addr, uint8_t ep, uint16_t nuint8_ts, uint8_t index, uint16_t langid, uint8_t* dataptr) {
return ( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr)); return( ctrlReq(addr, ep, bmREQ_GET_DESCR, USB_REQUEST_GET_DESCRIPTOR, index, USB_DESCRIPTOR_STRING, langid, nuint8_ts, dataptr));
} }
//set address //set address
inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) { inline uint8_t USB::setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr) {
return ( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL)); return( ctrlReq(oldaddr, ep, bmREQ_SET, USB_REQUEST_SET_ADDRESS, newaddr, 0x00, 0x0000, 0x0000, NULL));
} }
//set configuration //set configuration
inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) { inline uint8_t USB::setConf(uint8_t addr, uint8_t ep, uint8_t conf_value) {
return ( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL)); return( ctrlReq(addr, ep, bmREQ_SET, USB_REQUEST_SET_CONFIGURATION, conf_value, 0x00, 0x0000, 0x0000, NULL));
} }
#endif // defined(USB_METHODS_INLINE) #endif // defined(USB_METHODS_INLINE)

1851
Wii.cpp

File diff suppressed because it is too large Load diff

651
Wii.h
View file

@ -82,10 +82,10 @@
/** Enum used to read the joystick on the Nunchuck. */ /** Enum used to read the joystick on the Nunchuck. */
enum Hat { enum Hat {
/** Read the x-axis on the Nunchuck joystick. */ /** Read the x-axis on the Nunchuck joystick. */
HatX = 0, HatX = 0,
/** Read the y-axis on the Nunchuck joystick. */ /** Read the y-axis on the Nunchuck joystick. */
HatY = 1, HatY = 1,
}; };
/** /**
@ -95,347 +95,394 @@ enum Hat {
*/ */
class WII : public BluetoothService { class WII : public BluetoothService {
public: public:
/** /**
* Constructor for the WII class. * Constructor for the WII class.
* @param p Pointer to BTD class instance. * @param p Pointer to BTD class instance.
* @param pair Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it. * @param pair Set this to true in order to pair with the Wiimote. If the argument is omitted then it won't pair with it.
* One can use ::PAIR to set it to true. * One can use ::PAIR to set it to true.
*/ */
WII(BTD *p, bool pair=false); WII(BTD *p, bool pair = false);
/** @name BluetoothService implementation */ /** @name BluetoothService implementation */
/** /**
* Used to pass acldata to the services. * Used to pass acldata to the services.
* @param ACLData Incoming acldata. * @param ACLData Incoming acldata.
*/ */
virtual void ACLData(uint8_t* ACLData); virtual void ACLData(uint8_t* ACLData);
/** Used to run part of the state maschine. */ /** Used to run part of the state maschine. */
virtual void Run(); virtual void Run();
/** Use this to reset the service. */ /** Use this to reset the service. */
virtual void Reset(); virtual void Reset();
/** Used this to disconnect any of the controllers. */ /** Used this to disconnect any of the controllers. */
virtual void disconnect(); virtual void disconnect();
/**@}*/ /**@}*/
/** @name Wii Controller functions */ /** @name Wii Controller functions */
/** /**
* getButtonPress(Button b) will return true as long as the button is held down. * getButtonPress(Button b) will return true as long as the button is held down.
* *
* While getButtonClick(Button b) will only return it once. * While getButtonClick(Button b) will only return it once.
* *
* So you instance if you need to increase a variable once you would use getButtonClick(Button b), * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
* but if you need to drive a robot forward you would use getButtonPress(Button b). * but if you need to drive a robot forward you would use getButtonPress(Button b).
*/ */
bool getButtonPress(Button b); bool getButtonPress(Button b);
bool getButtonClick(Button b); bool getButtonClick(Button b);
/**@}*/ /**@}*/
/** @name Wii Controller functions */ /** @name Wii Controller functions */
/** /**
* Used to read the joystick of the Nunchuck. * Used to read the joystick of the Nunchuck.
* @param a Either ::HatX or ::HatY. * @param a Either ::HatX or ::HatY.
* @return Return the analog value in the range from approximately 25-230. * @return Return the analog value in the range from approximately 25-230.
*/ */
uint8_t getAnalogHat(Hat a); uint8_t getAnalogHat(Hat a);
/** /**
* Used to read the joystick of the Wii U Pro Controller. * Used to read the joystick of the Wii U Pro Controller.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
* @return Return the analog value in the range from approximately 800-3200. * @return Return the analog value in the range from approximately 800-3200.
*/ */
uint16_t getAnalogHat(AnalogHat a); uint16_t getAnalogHat(AnalogHat a);
/** /**
* Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. * Pitch calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
* @return Pitch in the range from 0-360. * @return Pitch in the range from 0-360.
*/ */
double getPitch() { return pitch; }; double getPitch() {
/** return pitch;
* Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected. };
* @return Roll in the range from 0-360.
*/
double getRoll() { return roll; };
/**
* This is the yaw calculated by the gyro.
*
* <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.
* @return The angle calculated using the gyro.
*/
double getYaw() { return gyroYaw; };
/** Used to set all LEDs and rumble off. */ /**
void setAllOff(); * Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
/** Turn off rumble. */ * @return Roll in the range from 0-360.
void setRumbleOff(); */
/** Turn on rumble. */ double getRoll() {
void setRumbleOn(); return roll;
/** Toggle rumble. */ };
void setRumbleToggle();
/**
* Turn the specific ::LED off.
* @param a The ::LED to turn off.
*/
void setLedOff(LED a);
/**
* Turn the specific ::LED on.
* @param a The ::LED to turn on.
*/
void setLedOn(LED a);
/**
* Toggle the specific ::LED.
* @param a The ::LED to toggle.
*/
void setLedToggle(LED a);
/**
* This will set the LEDs, so the user can see which connections are active.
*
* The first ::LED indicate that the Wiimote is connected,
*
* the second ::LED indicate indicate that a Motion Plus is also connected
*
* the third ::LED will indicate that a Nunchuck controller is also connected.
*/
void setLedStatus();
/** /**
* Return the battery level of the Wiimote. * This is the yaw calculated by the gyro.
* @return The battery level in the range 0-255. *
*/ * <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.
uint8_t getBatteryLevel() { return batteryLevel; }; * @return The angle calculated using the gyro.
/** */
* Return the Wiimote state. double getYaw() {
* @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status. return gyroYaw;
*/ };
uint8_t getWiiState() { return wiiState; };
/**@}*/
/**@{*/ /** Used to set all LEDs and rumble off. */
/** Variable used to indicate if a Wiimote is connected. */ void setAllOff();
bool wiimoteConnected; /** Turn off rumble. */
/** Variable used to indicate if a Nunchuck controller is connected. */ void setRumbleOff();
bool nunchuckConnected; /** Turn on rumble. */
/** Variable used to indicate if a Nunchuck controller is connected. */ void setRumbleOn();
bool motionPlusConnected; /** Toggle rumble. */
/** Variable used to indicate if a Wii U Pro controller is connected. */ void setRumbleToggle();
bool wiiUProControllerConnected; /**
/**@}*/ * Turn the specific ::LED off.
* @param a The ::LED to turn off.
*/
void setLedOff(LED a);
/**
* Turn the specific ::LED on.
* @param a The ::LED to turn on.
*/
void setLedOn(LED a);
/**
* Toggle the specific ::LED.
* @param a The ::LED to toggle.
*/
void setLedToggle(LED a);
/**
* This will set the LEDs, so the user can see which connections are active.
*
* The first ::LED indicate that the Wiimote is connected,
*
* the second ::LED indicate indicate that a Motion Plus is also connected
*
* the third ::LED will indicate that a Nunchuck controller is also connected.
*/
void setLedStatus();
/* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */ /**
* Return the battery level of the Wiimote.
* @return The battery level in the range 0-255.
*/
uint8_t getBatteryLevel() {
return batteryLevel;
};
/**@{*/ /**
/** Pitch and roll calculated from the accelerometer inside the Wiimote. */ * Return the Wiimote state.
double wiimotePitch; * @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.
double wiimoteRoll; */
/**@}*/ uint8_t getWiiState() {
return wiiState;
};
/**@}*/
/**@{*/ /**@{*/
/** Pitch and roll calculated from the accelerometer inside the Nunchuck. */ /** Variable used to indicate if a Wiimote is connected. */
double nunchuckPitch; bool wiimoteConnected;
double nunchuckRoll; /** Variable used to indicate if a Nunchuck controller is connected. */
/**@}*/ bool nunchuckConnected;
/** Variable used to indicate if a Nunchuck controller is connected. */
bool motionPlusConnected;
/** Variable used to indicate if a Wii U Pro controller is connected. */
bool wiiUProControllerConnected;
/**@}*/
/**@{*/ /* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
/** Accelerometer values used to calculate pitch and roll. */
int16_t accX;
int16_t accY;
int16_t accZ;
/**@}*/
/* Variables for the gyro inside the Motion Plus */ /**@{*/
/** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */ /** Pitch and roll calculated from the accelerometer inside the Wiimote. */
double gyroPitch; double wiimotePitch;
/** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */ double wiimoteRoll;
double gyroRoll; /**@}*/
/** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
double gyroYaw;
/**@{*/ /**@{*/
/** The speed in deg/s from the gyro. */ /** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
double pitchGyroSpeed; double nunchuckPitch;
double rollGyroSpeed; double nunchuckRoll;
double yawGyroSpeed; /**@}*/
/**@}*/
/**@{*/ /**@{*/
/** You might need to fine-tune these values. */ /** Accelerometer values used to calculate pitch and roll. */
uint16_t pitchGyroScale; int16_t accX;
uint16_t rollGyroScale; int16_t accY;
uint16_t yawGyroScale; int16_t accZ;
/**@}*/ /**@}*/
/**@{*/ /* Variables for the gyro inside the Motion Plus */
/** Raw value read directly from the Motion Plus. */ /** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */
int16_t gyroYawRaw; double gyroPitch;
int16_t gyroRollRaw; /** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
int16_t gyroPitchRaw; double gyroRoll;
/**@}*/ /** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
double gyroYaw;
/**@{*/ /**@{*/
/** These values are set when the controller is first initialized. */ /** The speed in deg/s from the gyro. */
int16_t gyroYawZero; double pitchGyroSpeed;
int16_t gyroRollZero; double rollGyroSpeed;
int16_t gyroPitchZero; double yawGyroSpeed;
/**@}*/ /**@}*/
/**@{*/
/** You might need to fine-tune these values. */
uint16_t pitchGyroScale;
uint16_t rollGyroScale;
uint16_t yawGyroScale;
/**@}*/
/**@{*/
/** Raw value read directly from the Motion Plus. */
int16_t gyroYawRaw;
int16_t gyroRollRaw;
int16_t gyroPitchRaw;
/**@}*/
/**@{*/
/** These values are set when the controller is first initialized. */
int16_t gyroYawZero;
int16_t gyroRollZero;
int16_t gyroPitchZero;
/**@}*/
#ifdef WIICAMERA #ifdef WIICAMERA
/** @name Wiimote IR camera functions /** @name Wiimote IR camera functions
* You will have to uncomment #WIICAMERA in Wii.h to use the IR camera. * You will have to uncomment #WIICAMERA in Wii.h to use the IR camera.
*/ */
/** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */ /** Initialises the camera as per the steps from: http://wiibrew.org/wiki/Wiimote#IR_Camera */
void IRinitialize(); void IRinitialize();
/** /**
* IR object 1 x-position read from the Wii IR camera. * IR object 1 x-position read from the Wii IR camera.
* @return The x-position of the object in the range 0-1023. * @return The x-position of the object in the range 0-1023.
*/ */
uint16_t getIRx1() { return IR_object_x1; }; uint16_t getIRx1() {
/** return IR_object_x1;
* IR object 1 y-position read from the Wii IR camera. };
* @return The y-position of the object in the range 0-767.
*/
uint16_t getIRy1() { return IR_object_y1; };
/**
* IR object 1 size read from the Wii IR camera.
* @return The size of the object in the range 0-15.
*/
uint8_t getIRs1() { return IR_object_s1; };
/** /**
* IR object 2 x-position read from the Wii IR camera. * IR object 1 y-position read from the Wii IR camera.
* @return The x-position of the object in the range 0-1023. * @return The y-position of the object in the range 0-767.
*/ */
uint16_t getIRx2() { return IR_object_x2; }; uint16_t getIRy1() {
/** return IR_object_y1;
* IR object 2 y-position read from the Wii IR camera. };
* @return The y-position of the object in the range 0-767.
*/
uint16_t getIRy2() { return IR_object_y2; };
/**
* IR object 2 size read from the Wii IR camera.
* @return The size of the object in the range 0-15.
*/
uint8_t getIRs2() { return IR_object_s2; };
/** /**
* IR object 3 x-position read from the Wii IR camera. * IR object 1 size read from the Wii IR camera.
* @return The x-position of the object in the range 0-1023. * @return The size of the object in the range 0-15.
*/ */
uint16_t getIRx3() { return IR_object_x3; }; uint8_t getIRs1() {
/** return IR_object_s1;
* IR object 3 y-position read from the Wii IR camera. };
* @return The y-position of the object in the range 0-767.
*/
uint16_t getIRy3() { return IR_object_y3; };
/**
* IR object 3 size read from the Wii IR camera.
* @return The size of the object in the range 0-15.
*/
uint8_t getIRs3() { return IR_object_s3; };
/** /**
* IR object 4 x-position read from the Wii IR camera. * IR object 2 x-position read from the Wii IR camera.
* @return The x-position of the object in the range 0-1023. * @return The x-position of the object in the range 0-1023.
*/ */
uint16_t getIRx4() { return IR_object_x4; }; uint16_t getIRx2() {
/** return IR_object_x2;
* IR object 4 y-position read from the Wii IR camera. };
* @return The y-position of the object in the range 0-767.
*/
uint16_t getIRy4() { return IR_object_y4; };
/**
* IR object 4 size read from the Wii IR camera.
* @return The size of the object in the range 0-15.
*/
uint8_t getIRs4() { return IR_object_s4; };
/** /**
* Use this to check if the camera is enabled or not. * IR object 2 y-position read from the Wii IR camera.
* If not call WII#IRinitialize to initialize the IR camera. * @return The y-position of the object in the range 0-767.
* @return True if it's enabled, false if not. */
*/ uint16_t getIRy2() {
bool isIRCameraEnabled() { return (wiiState & 0x08); }; return IR_object_y2;
/**@}*/ };
/**
* IR object 2 size read from the Wii IR camera.
* @return The size of the object in the range 0-15.
*/
uint8_t getIRs2() {
return IR_object_s2;
};
/**
* IR object 3 x-position read from the Wii IR camera.
* @return The x-position of the object in the range 0-1023.
*/
uint16_t getIRx3() {
return IR_object_x3;
};
/**
* IR object 3 y-position read from the Wii IR camera.
* @return The y-position of the object in the range 0-767.
*/
uint16_t getIRy3() {
return IR_object_y3;
};
/**
* IR object 3 size read from the Wii IR camera.
* @return The size of the object in the range 0-15.
*/
uint8_t getIRs3() {
return IR_object_s3;
};
/**
* IR object 4 x-position read from the Wii IR camera.
* @return The x-position of the object in the range 0-1023.
*/
uint16_t getIRx4() {
return IR_object_x4;
};
/**
* IR object 4 y-position read from the Wii IR camera.
* @return The y-position of the object in the range 0-767.
*/
uint16_t getIRy4() {
return IR_object_y4;
};
/**
* IR object 4 size read from the Wii IR camera.
* @return The size of the object in the range 0-15.
*/
uint8_t getIRs4() {
return IR_object_s4;
};
/**
* Use this to check if the camera is enabled or not.
* If not call WII#IRinitialize to initialize the IR camera.
* @return True if it's enabled, false if not.
*/
bool isIRCameraEnabled() {
return(wiiState & 0x08);
};
/**@}*/
#endif #endif
private: private:
/* Mandatory members */ /* Mandatory members */
BTD *pBtd; BTD *pBtd;
void L2CAP_task(); // L2CAP state machine void L2CAP_task(); // L2CAP state machine
/* Variables filled from HCI event management */ /* Variables filled from HCI event management */
uint16_t hci_handle; uint16_t hci_handle;
bool activeConnection; // Used to indicate if it's already has established a connection bool activeConnection; // Used to indicate if it's already has established a connection
/* variables used by high level L2CAP task */ /* variables used by high level L2CAP task */
uint8_t l2cap_state; uint8_t l2cap_state;
uint16_t l2cap_event_flag;// l2cap flags of received bluetooth events uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events
uint32_t ButtonState; uint32_t ButtonState;
uint32_t OldButtonState; uint32_t OldButtonState;
uint32_t ButtonClickState; uint32_t ButtonClickState;
uint16_t hatValues[4]; uint16_t hatValues[4];
uint8_t HIDBuffer[3];// Used to store HID commands uint8_t HIDBuffer[3]; // Used to store HID commands
uint16_t stateCounter; uint16_t stateCounter;
bool unknownExtensionConnected; bool unknownExtensionConnected;
bool extensionConnected; bool extensionConnected;
/* L2CAP Channels */ /* L2CAP Channels */
uint8_t control_scid[2]; // L2CAP source CID for HID_Control uint8_t control_scid[2]; // L2CAP source CID for HID_Control
uint8_t control_dcid[2]; // 0x0060 uint8_t control_dcid[2]; // 0x0060
uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
uint8_t interrupt_dcid[2]; // 0x0061 uint8_t interrupt_dcid[2]; // 0x0061
uint8_t identifier; // Identifier for connection uint8_t identifier; // Identifier for connection
/* HID Commands */ /* HID Commands */
void HID_Command(uint8_t* data, uint8_t nbytes); void HID_Command(uint8_t* data, uint8_t nbytes);
void setReportMode(bool continuous, uint8_t mode); void setReportMode(bool continuous, uint8_t mode);
void statusRequest(); void statusRequest();
void writeData(uint32_t offset, uint8_t size, uint8_t* data); void writeData(uint32_t offset, uint8_t size, uint8_t* data);
void initExtension1(); void initExtension1();
void initExtension2(); void initExtension2();
void readData(uint32_t offset, uint16_t size, bool EEPROM); void readData(uint32_t offset, uint16_t size, bool EEPROM);
void readExtensionType(); void readExtensionType();
void readCalData(); void readCalData();
void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote
void initMotionPlus(); void initMotionPlus();
void activateMotionPlus(); void activateMotionPlus();
double pitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected double pitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected
double roll; // Fusioned angle using a complimentary filter if the Motion Plus is connected double roll; // Fusioned angle using a complimentary filter if the Motion Plus is connected
bool activateNunchuck; bool activateNunchuck;
bool motionValuesReset; // This bool is true when the gyro values has been reset bool motionValuesReset; // This bool is true when the gyro values has been reset
unsigned long timer; unsigned long timer;
uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4) uint8_t wiiState; // Stores the value in l2capinbuf[12] - (0x01: Battery is nearly empty), (0x02: An Extension Controller is connected), (0x04: Speaker enabled), (0x08: IR enabled), (0x10: LED1, 0x20: LED2, 0x40: LED3, 0x80: LED4)
uint8_t batteryLevel; uint8_t batteryLevel;
#ifdef WIICAMERA #ifdef WIICAMERA
/* Private function and variables for the readings from teh IR Camera */ /* Private function and variables for the readings from teh IR Camera */
void enableIRCamera1(); // Sets bit 2 of output report 13 void enableIRCamera1(); // Sets bit 2 of output report 13
void enableIRCamera2(); // Sets bit 2 of output report 1A void enableIRCamera2(); // Sets bit 2 of output report 1A
void writeSensitivityBlock1(); void writeSensitivityBlock1();
void writeSensitivityBlock2(); void writeSensitivityBlock2();
void write0x08Value(); void write0x08Value();
void setWiiModeNumber(uint8_t mode_number); void setWiiModeNumber(uint8_t mode_number);
uint16_t IR_object_x1; // IR x position 10 bits uint16_t IR_object_x1; // IR x position 10 bits
uint16_t IR_object_y1; // IR y position 10 bits uint16_t IR_object_y1; // IR y position 10 bits
uint8_t IR_object_s1; // IR size value uint8_t IR_object_s1; // IR size value
uint16_t IR_object_x2; uint16_t IR_object_x2;
uint16_t IR_object_y2; uint16_t IR_object_y2;
uint8_t IR_object_s2; uint8_t IR_object_s2;
uint16_t IR_object_x3; // IR x position 10 bits uint16_t IR_object_x3; // IR x position 10 bits
uint16_t IR_object_y3; // IR y position 10 bits uint16_t IR_object_y3; // IR y position 10 bits
uint8_t IR_object_s3; // IR size value uint8_t IR_object_s3; // IR size value
uint16_t IR_object_x4; uint16_t IR_object_x4;
uint16_t IR_object_y4; uint16_t IR_object_y4;
uint8_t IR_object_s4; uint8_t IR_object_s4;
#endif #endif
}; };
#endif #endif

View file

@ -22,395 +22,411 @@
//#define EXTRADEBUG // Uncomment to get even more debugging data //#define EXTRADEBUG // Uncomment to get even more debugging data
//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller
XBOXRECV::XBOXRECV(USB *p): XBOXRECV::XBOXRECV(USB *p) :
pUsb(p), // pointer to USB class instance - mandatory pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory bAddress(0), // device address - mandatory
bPollEnable(false) { // don't start polling before dongle is connected bPollEnable(false) { // don't start polling before dongle is connected
for(uint8_t i=0; i<XBOX_MAX_ENDPOINTS; i++) { for (uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
if (pUsb) // register in USB subsystem if (pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
} }
uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t XBOXRECV::Init(uint8_t parent, uint8_t port, bool lowspeed) {
uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
uint8_t rcode; uint8_t rcode;
UsbDevice *p = NULL; UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL; EpInfo *oldep_ptr = NULL;
uint16_t PID; uint16_t PID;
uint16_t VID; uint16_t VID;
// get memory address of USB device address pool // get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nXBOXRECV Init"), 0x80); Notify(PSTR("\r\nXBOXRECV Init"), 0x80);
#endif #endif
// check if address has already been assigned to an instance // check if address has already been assigned to an instance
if (bAddress) { if (bAddress) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
} }
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if (!p) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if (!p->epinfo) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nepinfo is null"), 0x80); Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif #endif
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
// Save old pointer to EP_RECORD of address 0 // Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo; oldep_ptr = p->epinfo;
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo; p->epinfo = epInfo;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if(rcode) if (rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
if(VID != XBOX_VID && VID != MADCATZ_VID) // We just check if it's a xbox receiver using the Vendor ID if (VID != XBOX_VID && VID != MADCATZ_VID) // We just check if it's a xbox receiver using the Vendor ID
goto FailUnknownDevice; goto FailUnknownDevice;
else if(PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) { else if (PID != XBOX_WIRELESS_RECEIVER_PID && PID != XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80); Notify(PSTR("\r\nYou'll need a wireless receiver for this libary to work"), 0x80);
#endif #endif
goto FailUnknownDevice; goto FailUnknownDevice;
} }
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if (!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor // Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr( 0, 0, bAddress ); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if (rcode) {
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
#ifdef DEBUG
Notify(PSTR("\r\nsetAddr: "), 0x80);
#endif
PrintHex<uint8_t > (rcode, 0x80);
return rcode;
}
#ifdef EXTRADEBUG
Notify(PSTR("\r\nAddr: "), 0x80);
PrintHex<uint8_t > (bAddress, 0x80);
#endif
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
#ifdef DEBUG
Notify(PSTR("\r\nsetAddr: "), 0x80);
#endif
PrintHex<uint8_t>(rcode, 0x80);
return rcode;
}
#ifdef EXTRADEBUG
Notify(PSTR("\r\nAddr: "), 0x80);
PrintHex<uint8_t>(bAddress, 0x80);
#endif
p->lowspeed = false;
//get pointer to assigned address record //get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known // Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if (rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data /* The application will work in reduced host mode, so we can save program and data
memory space. After verifying the VID we will use known values for the memory space. After verifying the VID we will use known values for the
configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */ configuration values for device, interface, endpoints and HID for the XBOX360 Wireless receiver */
/* Initialize data structures for endpoints of device */ /* Initialize data structures for endpoints of device */
epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 report endpoint - poll interval 1ms
epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE_1 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_INPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_INPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_INPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_INPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms epInfo[ XBOX_OUTPUT_PIPE_1 ].epAddr = 0x01; // XBOX 360 output endpoint - poll interval 8ms
epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_OUTPUT_PIPE_1 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_OUTPUT_PIPE_1 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_1 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_1 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_OUTPUT_PIPE_1 ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 report endpoint - poll interval 1ms
epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE_2 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_INPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_INPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_INPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_INPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms epInfo[ XBOX_OUTPUT_PIPE_2 ].epAddr = 0x03; // XBOX 360 output endpoint - poll interval 8ms
epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_OUTPUT_PIPE_2 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_OUTPUT_PIPE_2 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_2 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_2 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_OUTPUT_PIPE_2 ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 report endpoint - poll interval 1ms
epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE_3 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_INPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_INPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_INPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_INPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms epInfo[ XBOX_OUTPUT_PIPE_3 ].epAddr = 0x05; // XBOX 360 output endpoint - poll interval 8ms
epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_OUTPUT_PIPE_3 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_OUTPUT_PIPE_3 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_3 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_3 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_OUTPUT_PIPE_3 ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms epInfo[ XBOX_INPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 report endpoint - poll interval 1ms
epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE_4 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_INPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_INPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_INPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_INPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms epInfo[ XBOX_OUTPUT_PIPE_4 ].epAddr = 0x07; // XBOX 360 output endpoint - poll interval 8ms
epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_OUTPUT_PIPE_4 ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_OUTPUT_PIPE_4 ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE_4 ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE_4 ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_OUTPUT_PIPE_4 ].bmRcvToggle = bmRCVTOG0;
rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 9, epInfo);
if( rcode ) if (rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
delay(200);//Give time for address change delay(200); //Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
if( rcode ) if (rcode)
goto FailSetConf; goto FailSetConf;
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80); Notify(PSTR("\r\nXbox Wireless Receiver Connected\r\n"), 0x80);
#endif #endif
XboxReceiverConnected = true; XboxReceiverConnected = true;
bPollEnable = true; bPollEnable = true;
return 0; // successful configuration return 0; // successful configuration
/* diagnostic messages */ /* diagnostic messages */
FailGetDevDescr: FailGetDevDescr:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\ngetDevDescr:"), 0x80); Notify(PSTR("\r\ngetDevDescr:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailSetDevTblEntry: FailSetDevTblEntry:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nsetDevTblEn:"), 0x80); Notify(PSTR("\r\nsetDevTblEn:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailSetConf: FailSetConf:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nsetConf:"), 0x80); Notify(PSTR("\r\nsetConf:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailUnknownDevice: FailUnknownDevice:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80);
PrintHex<uint16_t>(VID, 0x80); PrintHex<uint16_t > (VID, 0x80);
Notify(PSTR(" PID: "), 0x80); Notify(PSTR(" PID: "), 0x80);
PrintHex<uint16_t>(PID, 0x80); PrintHex<uint16_t > (PID, 0x80);
#endif #endif
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
goto Fail; goto Fail;
Fail: Fail:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80);
Serial.print(rcode,HEX); Serial.print(rcode, HEX);
#endif #endif
Release(); Release();
return rcode; return rcode;
} }
/* Performs a cleanup after failed Init() attempt */ /* Performs a cleanup after failed Init() attempt */
uint8_t XBOXRECV::Release() { uint8_t XBOXRECV::Release() {
XboxReceiverConnected = false; XboxReceiverConnected = false;
for(uint8_t i=0;i<4;i++) for (uint8_t i = 0; i < 4; i++)
Xbox360Connected[i] = 0x00; Xbox360Connected[i] = 0x00;
pUsb->GetAddressPool().FreeAddress(bAddress); pUsb->GetAddressPool().FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
bPollEnable = false; bPollEnable = false;
return 0; return 0;
} }
uint8_t XBOXRECV::Poll() { uint8_t XBOXRECV::Poll() {
if (!bPollEnable) if (!bPollEnable)
return 0; return 0;
if(!timer || ((millis() - timer) > 3000)) { // Run checkStatus every 3 seconds if (!timer || ((millis() - timer) > 3000)) { // Run checkStatus every 3 seconds
timer = millis(); timer = millis();
checkStatus(); checkStatus();
}
uint8_t inputPipe;
uint16_t bufferSize;
for(uint8_t i=0;i<4;i++) {
switch (i) {
case 0: inputPipe = XBOX_INPUT_PIPE_1; break;
case 1: inputPipe = XBOX_INPUT_PIPE_2; break;
case 2: inputPipe = XBOX_INPUT_PIPE_3; break;
case 3: inputPipe = XBOX_INPUT_PIPE_4; break;
} }
bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive uint8_t inputPipe;
pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf); uint16_t bufferSize;
if(bufferSize > 0) { // The number of received bytes for (uint8_t i = 0; i < 4; i++) {
switch (i) {
case 0: inputPipe = XBOX_INPUT_PIPE_1;
break;
case 1: inputPipe = XBOX_INPUT_PIPE_2;
break;
case 2: inputPipe = XBOX_INPUT_PIPE_3;
break;
case 3: inputPipe = XBOX_INPUT_PIPE_4;
break;
}
bufferSize = EP_MAXPKTSIZE; // This is the maximum number of bytes we want to receive
pUsb->inTransfer(bAddress, epInfo[ inputPipe ].epAddr, &bufferSize, readBuf);
if (bufferSize > 0) { // The number of received bytes
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("Bytes Received: "), 0x80); Notify(PSTR("Bytes Received: "), 0x80);
Serial.print(bufferSize); Serial.print(bufferSize);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
#endif #endif
readReport(i); readReport(i);
#ifdef PRINTREPORT #ifdef PRINTREPORT
printReport(i,bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller printReport(i, bufferSize); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
#endif #endif
}
} }
} return 0;
return 0;
} }
void XBOXRECV::readReport(uint8_t controller) { void XBOXRECV::readReport(uint8_t controller) {
if (readBuf == NULL) if (readBuf == NULL)
return; return;
// This report is send when a controller is connected and disconnected // This report is send when a controller is connected and disconnected
if(readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) { if (readBuf[0] == 0x08 && readBuf[1] != Xbox360Connected[controller]) {
Xbox360Connected[controller] = readBuf[1]; Xbox360Connected[controller] = readBuf[1];
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("Controller "), 0x80); Notify(PSTR("Controller "), 0x80);
Serial.print(controller); Serial.print(controller);
#endif #endif
if(Xbox360Connected[controller]) { if (Xbox360Connected[controller]) {
#ifdef DEBUG #ifdef DEBUG
char* str = 0; char* str = 0;
switch(readBuf[1]) { switch (readBuf[1]) {
case 0x80: str = PSTR(" as controller\r\n"); break; case 0x80: str = PSTR(" as controller\r\n");
case 0x40: str = PSTR(" as headset\r\n"); break; break;
case 0xC0: str = PSTR(" as controller+headset\r\n"); break; case 0x40: str = PSTR(" as headset\r\n");
} break;
Notify(PSTR(": connected"), 0x80); case 0xC0: str = PSTR(" as controller+headset\r\n");
Notify(str, 0x80); break;
}
Notify(PSTR(": connected"), 0x80);
Notify(str, 0x80);
#endif #endif
LED led; LED led;
switch (controller) { switch (controller) {
case 0: led = LED1; break; case 0: led = LED1;
case 1: led = LED2; break; break;
case 2: led = LED3; break; case 1: led = LED2;
case 3: led = LED4; break; break;
} case 2: led = LED3;
setLedOn(controller,led); break;
case 3: led = LED4;
break;
}
setLedOn(controller, led);
}
#ifdef DEBUG
else
Notify(PSTR(": disconnected\r\n"), 0x80);
#endif
return;
} }
#ifdef DEBUG // Controller status report
else if (readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) {
Notify(PSTR(": disconnected\r\n"), 0x80); controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4];
#endif return;
return; }
} if (readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports
// Controller status report return;
if(readBuf[1] == 0x00 && readBuf[3] & 0x13 && readBuf[4] >= 0x22) {
controllerStatus[controller] = ((uint16_t)readBuf[3] << 8) | readBuf[4];
return;
}
if(readBuf[1] != 0x01) // Check if it's the correct report - the receiver also sends different status reports
return;
// A controller must be connected if it's sending data // A controller must be connected if it's sending data
if(!Xbox360Connected[controller]) if (!Xbox360Connected[controller])
Xbox360Connected[controller] |= 0x80; Xbox360Connected[controller] |= 0x80;
ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24)); ButtonState[controller] = (uint32_t)(readBuf[9] | ((uint16_t)readBuf[8] << 8) | ((uint32_t)readBuf[7] << 16) | ((uint32_t)readBuf[6] << 24));
hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); hatValue[controller][LeftHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); hatValue[controller][LeftHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]); hatValue[controller][RightHatX] = (int16_t)(((uint16_t)readBuf[15] << 8) | readBuf[14]);
hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]); hatValue[controller][RightHatY] = (int16_t)(((uint16_t)readBuf[17] << 8) | readBuf[16]);
//Notify(PSTR("\r\nButtonState: "), 0x80); //Notify(PSTR("\r\nButtonState: "), 0x80);
//PrintHex<uint32_t>(ButtonState[controller], 0x80); //PrintHex<uint32_t>(ButtonState[controller], 0x80);
if(ButtonState[controller] != OldButtonState[controller]) { if (ButtonState[controller] != OldButtonState[controller]) {
buttonStateChanged[controller] = true; buttonStateChanged[controller] = true;
ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 ButtonClickState[controller] = (ButtonState[controller] >> 16) & ((~OldButtonState[controller]) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2
if(((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons if (((uint8_t)OldButtonState[controller]) == 0 && ((uint8_t)ButtonState[controller]) != 0) // The L2 and R2 buttons are special as they are analog buttons
R2Clicked[controller] = true; R2Clicked[controller] = true;
if((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0) if ((uint8_t)(OldButtonState[controller] >> 8) == 0 && (uint8_t)(ButtonState[controller] >> 8) != 0)
L2Clicked[controller] = true; L2Clicked[controller] = true;
OldButtonState[controller] = ButtonState[controller]; OldButtonState[controller] = ButtonState[controller];
} }
} }
void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
#ifdef PRINTREPORT #ifdef PRINTREPORT
if (readBuf == NULL) if (readBuf == NULL)
return; return;
Notify(PSTR("Controller "), 0x80); Notify(PSTR("Controller "), 0x80);
Serial.print(controller); Serial.print(controller);
Notify(PSTR(": "), 0x80); Notify(PSTR(": "), 0x80);
for(uint8_t i = 0; i < nBytes;i++) { for (uint8_t i = 0; i < nBytes; i++) {
PrintHex<uint8_t>(readBuf[i], 0x80); PrintHex<uint8_t > (readBuf[i], 0x80);
Serial.print(" "); Serial.print(" ");
} }
Serial.println(); Serial.println();
#endif #endif
} }
uint8_t XBOXRECV::getButtonPress(uint8_t controller, Button b) { uint8_t XBOXRECV::getButtonPress(uint8_t controller, Button b) {
if(b == L2) // These are analog buttons if (b == L2) // These are analog buttons
return (uint8_t)(ButtonState[controller] >> 8); return (uint8_t)(ButtonState[controller] >> 8);
else if(b == R2) else if (b == R2)
return (uint8_t)ButtonState[controller]; return (uint8_t)ButtonState[controller];
return (ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); return (ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16));
} }
bool XBOXRECV::getButtonClick(uint8_t controller, Button b) { bool XBOXRECV::getButtonClick(uint8_t controller, Button b) {
if(b == L2) { if (b == L2) {
if(L2Clicked[controller]) { if (L2Clicked[controller]) {
L2Clicked[controller] = false; L2Clicked[controller] = false;
return true; return true;
}
return false;
} else if (b == R2) {
if (R2Clicked[controller]) {
R2Clicked[controller] = false;
return true;
}
return false;
} }
return false; uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]);
} bool click = (ButtonClickState[controller] & button);
else if(b == R2) { ButtonClickState[controller] &= ~button; // clear "click" event
if(R2Clicked[controller]) { return click;
R2Clicked[controller] = false;
return true;
}
return false;
}
uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]);
bool click = (ButtonClickState[controller] & button);
ButtonClickState[controller] &= ~button; // clear "click" event
return click;
} }
int16_t XBOXRECV::getAnalogHat(uint8_t controller, AnalogHat a) { int16_t XBOXRECV::getAnalogHat(uint8_t controller, AnalogHat a) {
return hatValue[controller][a]; return hatValue[controller][a];
} }
bool XBOXRECV::buttonChanged(uint8_t controller) { bool XBOXRECV::buttonChanged(uint8_t controller) {
bool state = buttonStateChanged[controller]; bool state = buttonStateChanged[controller];
buttonStateChanged[controller] = false; buttonStateChanged[controller] = false;
return state; return state;
} }
/* /*
ControllerStatus Breakdown ControllerStatus Breakdown
ControllerStatus[controller] & 0x0001 // 0 ControllerStatus[controller] & 0x0001 // 0
@ -429,81 +445,90 @@ ControllerStatus Breakdown
ControllerStatus[controller] & 0x2000 // 0 ControllerStatus[controller] & 0x2000 // 0
ControllerStatus[controller] & 0x4000 // 0 ControllerStatus[controller] & 0x4000 // 0
ControllerStatus[controller] & 0x8000 // 0 ControllerStatus[controller] & 0x8000 // 0
*/ */
uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) { uint8_t XBOXRECV::getBatteryLevel(uint8_t controller) {
uint8_t batteryLevel = ((controllerStatus[controller] & 0x00C0) >> 6) * 33; uint8_t batteryLevel = ((controllerStatus[controller] & 0x00C0) >> 6) * 33;
if(batteryLevel == 99) if (batteryLevel == 99)
batteryLevel = 100; batteryLevel = 100;
return batteryLevel; return batteryLevel;
} }
void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) { void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) {
uint8_t rcode; uint8_t rcode;
uint8_t outputPipe; uint8_t outputPipe;
switch (controller) { switch (controller) {
case 0: outputPipe = XBOX_OUTPUT_PIPE_1; break; case 0: outputPipe = XBOX_OUTPUT_PIPE_1;
case 1: outputPipe = XBOX_OUTPUT_PIPE_2; break; break;
case 2: outputPipe = XBOX_OUTPUT_PIPE_3; break; case 1: outputPipe = XBOX_OUTPUT_PIPE_2;
case 3: outputPipe = XBOX_OUTPUT_PIPE_4; break; break;
} case 2: outputPipe = XBOX_OUTPUT_PIPE_3;
rcode = pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data); break;
case 3: outputPipe = XBOX_OUTPUT_PIPE_4;
break;
}
rcode = pUsb->outTransfer(bAddress, epInfo[ outputPipe ].epAddr, nbytes, data);
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
if(rcode) if (rcode)
Notify(PSTR("Error sending Xbox message\r\n"), 0x80); Notify(PSTR("Error sending Xbox message\r\n"), 0x80);
#endif #endif
} }
void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) {
writeBuf[0] = 0x00;
writeBuf[1] = 0x00;
writeBuf[2] = 0x08;
writeBuf[3] = value | 0x40;
XboxCommand(controller, writeBuf, 4); void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) {
writeBuf[0] = 0x00;
writeBuf[1] = 0x00;
writeBuf[2] = 0x08;
writeBuf[3] = value | 0x40;
XboxCommand(controller, writeBuf, 4);
} }
void XBOXRECV::setLedOn(uint8_t controller, LED led) { void XBOXRECV::setLedOn(uint8_t controller, LED led) {
if(led != ALL) // All LEDs can't be on a the same time if (led != ALL) // All LEDs can't be on a the same time
setLedRaw(controller,(pgm_read_byte(&XBOXLEDS[(uint8_t)led]))+4); setLedRaw(controller, (pgm_read_byte(&XBOXLEDS[(uint8_t)led])) + 4);
} }
void XBOXRECV::setLedBlink(uint8_t controller, LED led) { void XBOXRECV::setLedBlink(uint8_t controller, LED led) {
setLedRaw(controller,pgm_read_byte(&XBOXLEDS[(uint8_t)led])); setLedRaw(controller, pgm_read_byte(&XBOXLEDS[(uint8_t)led]));
} }
void XBOXRECV::setLedMode(uint8_t controller, LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports void XBOXRECV::setLedMode(uint8_t controller, LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports
setLedRaw(controller,(uint8_t)ledMode); setLedRaw(controller, (uint8_t)ledMode);
} }
/* PC runs this at interval of approx 2 seconds /* PC runs this at interval of approx 2 seconds
Thanks to BusHound from Perisoft.net for the Windows USB Analysis output Thanks to BusHound from Perisoft.net for the Windows USB Analysis output
Found by timstamp.co.uk Found by timstamp.co.uk
*/ */
void XBOXRECV::checkStatus() { void XBOXRECV::checkStatus() {
if(!bPollEnable) if (!bPollEnable)
return; return;
// Get controller info // Get controller info
writeBuf[0] = 0x08; writeBuf[0] = 0x08;
writeBuf[1] = 0x00; writeBuf[1] = 0x00;
writeBuf[2] = 0x0f; writeBuf[2] = 0x0f;
writeBuf[3] = 0xc0; writeBuf[3] = 0xc0;
for(uint8_t i=0; i<4; i++) { for (uint8_t i = 0; i < 4; i++) {
XboxCommand(i, writeBuf, 4); XboxCommand(i, writeBuf, 4);
} }
// Get battery status // Get battery status
writeBuf[0] = 0x00; writeBuf[0] = 0x00;
writeBuf[1] = 0x00; writeBuf[1] = 0x00;
writeBuf[2] = 0x00; writeBuf[2] = 0x00;
writeBuf[3] = 0x40; writeBuf[3] = 0x40;
for(uint8_t i=0; i<4; i++) { for (uint8_t i = 0; i < 4; i++) {
if(Xbox360Connected[i]) if (Xbox360Connected[i])
XboxCommand(i, writeBuf, 4); XboxCommand(i, writeBuf, 4);
} }
} }
void XBOXRECV::setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue) { void XBOXRECV::setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue) {
writeBuf[0] = 0x00; writeBuf[0] = 0x00;
writeBuf[1] = 0x01; writeBuf[1] = 0x01;
writeBuf[2] = 0x0f; writeBuf[2] = 0x0f;
writeBuf[3] = 0xc0; writeBuf[3] = 0xc0;
writeBuf[4] = 0x00; writeBuf[4] = 0x00;
writeBuf[5] = lValue; // big weight writeBuf[5] = lValue; // big weight
writeBuf[6] = rValue; // small weight writeBuf[6] = rValue; // small weight
XboxCommand(controller, writeBuf, 7); XboxCommand(controller, writeBuf, 7);
} }

View file

@ -62,167 +62,183 @@
*/ */
class XBOXRECV : public USBDeviceConfig { class XBOXRECV : public USBDeviceConfig {
public: public:
/** /**
* Constructor for the XBOXRECV class. * Constructor for the XBOXRECV class.
* @param pUsb Pointer to USB class instance. * @param pUsb Pointer to USB class instance.
*/ */
XBOXRECV(USB *pUsb); XBOXRECV(USB *pUsb);
/** @name USBDeviceConfig implementation */ /** @name USBDeviceConfig implementation */
/** /**
* Initialize the Xbox wireless receiver. * Initialize the Xbox wireless receiver.
* @param parent Hub number. * @param parent Hub number.
* @param port Port number on the hub. * @param port Port number on the hub.
* @param lowspeed Speed of the device. * @param lowspeed Speed of the device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/** /**
* Release the USB device. * Release the USB device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Release(); virtual uint8_t Release();
/** /**
* Poll the USB Input endpoins and run the state machines. * Poll the USB Input endpoins and run the state machines.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Poll(); virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() { return bAddress; };
/**
* Used to check if the controller has been initialized.
* @return True if it's ready.
*/
virtual bool isReady() { return bPollEnable; };
/**@}*/
/** @name Xbox Controller functions */ /**
/** * Get the device address.
* getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down. * @return The device address.
* */
* While getButtonClick(uint8_t controller, Button b) will only return it once. virtual uint8_t GetAddress() {
* return bAddress;
* So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b), };
* but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, Button b).
* @param controller The controller to read from.
* @param b ::Button to read.
* @return getButtonClick(uint8_t controller, Button b) will return a bool, but getButtonPress(uint8_t controller, Button b)
* will return a byte if reading ::L2 or ::R2.
*/
uint8_t getButtonPress(uint8_t controller, Button b);
bool getButtonClick(uint8_t controller, Button b);
/**@}*/
/** @name Xbox Controller functions */ /**
/** * Used to check if the controller has been initialized.
* Return the analog value from the joysticks on the controller. * @return True if it's ready.
* @param controller The controller to read from. */
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. virtual bool isReady() {
* @return Returns a signed 16-bit integer. return bPollEnable;
*/ };
int16_t getAnalogHat(uint8_t controller, AnalogHat a); /**@}*/
/**
* Turn rumble off and all the LEDs on the specific controller.
* @param controller The controller to write to.
*/
void setAllOff(uint8_t controller) { setRumbleOn(controller,0,0); setLedOff(controller); };
/**
* Turn rumble off the specific controller.
* @param controller The controller to write to.
*/
void setRumbleOff(uint8_t controller) { setRumbleOn(controller,0,0); };
/**
* Turn rumble on.
* @param controller The controller to write to.
* @param lValue Left motor (big weight) inside the controller.
* @param rValue Right motor (small weight) inside the controller.
*/
void setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue);
/**
* Set LED value. Without using the ::LED or ::LEDMode enum.
* @param controller The controller to write to.
* @param value See:
* setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l),
* setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm).
*/
void setLedRaw(uint8_t controller, uint8_t value);
/**
* Turn all LEDs off the specific controller.
* @param controller The controller to write to.
*/
void setLedOff(uint8_t controller) { setLedRaw(controller,0); };
/**
* Turn on a LED by using the ::LED enum.
* @param controller The controller to write to.
* @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedOn(uint8_t controller, LED l);
/**
* Turn on a LED by using the ::LED enum.
* @param controller The controller to write to.
* @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedBlink(uint8_t controller, LED l);
/**
* Used to set special LED modes supported by the Xbox controller.
* @param controller The controller to write to.
* @param lm See ::LEDMode.
*/
void setLedMode(uint8_t controller, LEDMode lm);
/**
* Used to get the battery level from the controller.
* @param controller The controller to read from.
* @return Returns the battery level in percentage in 33% steps.
*/
uint8_t getBatteryLevel(uint8_t controller);
/**
* Used to check if a button has changed.
* @param controller The controller to read from.
* @return True if a button has changed.
*/
bool buttonChanged(uint8_t controller);
/**@}*/
/** True if a wireless receiver is connected. */ /** @name Xbox Controller functions */
bool XboxReceiverConnected; /**
/** Variable used to indicate if the XBOX 360 controller is successfully connected. */ * getButtonPress(uint8_t controller, Button b) will return true as long as the button is held down.
uint8_t Xbox360Connected[4]; *
* While getButtonClick(uint8_t controller, Button b) will only return it once.
*
* So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b),
* but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, Button b).
* @param controller The controller to read from.
* @param b ::Button to read.
* @return getButtonClick(uint8_t controller, Button b) will return a bool, but getButtonPress(uint8_t controller, Button b)
* will return a byte if reading ::L2 or ::R2.
*/
uint8_t getButtonPress(uint8_t controller, Button b);
bool getButtonClick(uint8_t controller, Button b);
/**@}*/
/** @name Xbox Controller functions */
/**
* Return the analog value from the joysticks on the controller.
* @param controller The controller to read from.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
* @return Returns a signed 16-bit integer.
*/
int16_t getAnalogHat(uint8_t controller, AnalogHat a);
/**
* Turn rumble off and all the LEDs on the specific controller.
* @param controller The controller to write to.
*/
void setAllOff(uint8_t controller) {
setRumbleOn(controller, 0, 0);
setLedOff(controller);
};
/**
* Turn rumble off the specific controller.
* @param controller The controller to write to.
*/
void setRumbleOff(uint8_t controller) {
setRumbleOn(controller, 0, 0);
};
/**
* Turn rumble on.
* @param controller The controller to write to.
* @param lValue Left motor (big weight) inside the controller.
* @param rValue Right motor (small weight) inside the controller.
*/
void setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue);
/**
* Set LED value. Without using the ::LED or ::LEDMode enum.
* @param controller The controller to write to.
* @param value See:
* setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l),
* setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm).
*/
void setLedRaw(uint8_t controller, uint8_t value);
/**
* Turn all LEDs off the specific controller.
* @param controller The controller to write to.
*/
void setLedOff(uint8_t controller) {
setLedRaw(controller, 0);
};
/**
* Turn on a LED by using the ::LED enum.
* @param controller The controller to write to.
* @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedOn(uint8_t controller, LED l);
/**
* Turn on a LED by using the ::LED enum.
* @param controller The controller to write to.
* @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedBlink(uint8_t controller, LED l);
/**
* Used to set special LED modes supported by the Xbox controller.
* @param controller The controller to write to.
* @param lm See ::LEDMode.
*/
void setLedMode(uint8_t controller, LEDMode lm);
/**
* Used to get the battery level from the controller.
* @param controller The controller to read from.
* @return Returns the battery level in percentage in 33% steps.
*/
uint8_t getBatteryLevel(uint8_t controller);
/**
* Used to check if a button has changed.
* @param controller The controller to read from.
* @return True if a button has changed.
*/
bool buttonChanged(uint8_t controller);
/**@}*/
/** True if a wireless receiver is connected. */
bool XboxReceiverConnected;
/** Variable used to indicate if the XBOX 360 controller is successfully connected. */
uint8_t Xbox360Connected[4];
protected: protected:
/** Pointer to USB class instance. */ /** Pointer to USB class instance. */
USB *pUsb; USB *pUsb;
/** Device address. */ /** Device address. */
uint8_t bAddress; uint8_t bAddress;
/** Endpoint info structure. */ /** Endpoint info structure. */
EpInfo epInfo[XBOX_MAX_ENDPOINTS]; EpInfo epInfo[XBOX_MAX_ENDPOINTS];
private: private:
bool bPollEnable; bool bPollEnable;
/* Variables to store the buttons */ /* Variables to store the buttons */
uint32_t ButtonState[4]; uint32_t ButtonState[4];
uint32_t OldButtonState[4]; uint32_t OldButtonState[4];
uint16_t ButtonClickState[4]; uint16_t ButtonClickState[4];
int16_t hatValue[4][4]; int16_t hatValue[4][4];
uint16_t controllerStatus[4]; uint16_t controllerStatus[4];
bool buttonStateChanged[4]; // True if a button has changed bool buttonStateChanged[4]; // True if a button has changed
bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not bool L2Clicked[4]; // These buttons are analog, so we use we use these bools to check if they where clicked or not
bool R2Clicked[4]; bool R2Clicked[4];
unsigned long timer; // Timing for checkStatus() signals unsigned long timer; // Timing for checkStatus() signals
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
void readReport(uint8_t controller); // read incoming data void readReport(uint8_t controller); // read incoming data
void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging
/* Private commands */ /* Private commands */
void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes); void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes);
void checkStatus(); void checkStatus();
}; };
#endif #endif

View file

@ -20,323 +20,329 @@
//#define EXTRADEBUG // Uncomment to get even more debugging data //#define EXTRADEBUG // Uncomment to get even more debugging data
//#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller //#define PRINTREPORT // Uncomment to print the report send by the Xbox 360 Controller
XBOXUSB::XBOXUSB(USB *p): XBOXUSB::XBOXUSB(USB *p) :
pUsb(p), // pointer to USB class instance - mandatory pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory bAddress(0), // device address - mandatory
bPollEnable(false) { // don't start polling before dongle is connected bPollEnable(false) { // don't start polling before dongle is connected
for(uint8_t i=0; i<XBOX_MAX_ENDPOINTS; i++) { for (uint8_t i = 0; i < XBOX_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER; epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
} }
if (pUsb) // register in USB subsystem if (pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry pUsb->RegisterDeviceClass(this); //set devConfig[] entry
} }
uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t XBOXUSB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
uint8_t buf[sizeof(USB_DEVICE_DESCRIPTOR)]; uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
uint8_t rcode; uint8_t rcode;
UsbDevice *p = NULL; UsbDevice *p = NULL;
EpInfo *oldep_ptr = NULL; EpInfo *oldep_ptr = NULL;
uint16_t PID; uint16_t PID;
uint16_t VID; uint16_t VID;
// get memory address of USB device address pool // get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool(); AddressPool &addrPool = pUsb->GetAddressPool();
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nXBOXUSB Init"), 0x80); Notify(PSTR("\r\nXBOXUSB Init"), 0x80);
#endif #endif
// check if address has already been assigned to an instance // check if address has already been assigned to an instance
if (bAddress) { if (bAddress) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nAddress in use"), 0x80); Notify(PSTR("\r\nAddress in use"), 0x80);
#endif #endif
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
} }
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) { if (!p) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nAddress not found"), 0x80); Notify(PSTR("\r\nAddress not found"), 0x80);
#endif #endif
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
} }
if (!p->epinfo) { if (!p->epinfo) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nepinfo is null"), 0x80); Notify(PSTR("\r\nepinfo is null"), 0x80);
#endif #endif
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
// Save old pointer to EP_RECORD of address 0 // Save old pointer to EP_RECORD of address 0
oldep_ptr = p->epinfo; oldep_ptr = p->epinfo;
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p->epinfo = epInfo; p->epinfo = epInfo;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof(USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);// Get device descriptor - addr, ep, nbytes, data rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf); // Get device descriptor - addr, ep, nbytes, data
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if(rcode) if (rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor; VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct; PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
if(VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) // We just check if it's a xbox controller using the Vendor ID if (VID != XBOX_VID && VID != MADCATZ_VID && VID != JOYTECH_VID) // We just check if it's a xbox controller using the Vendor ID
goto FailUnknownDevice; goto FailUnknownDevice;
if(PID == XBOX_WIRELESS_PID) { if (PID == XBOX_WIRELESS_PID) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80); Notify(PSTR("\r\nYou have plugged in a wireless Xbox 360 controller - it doesn't support USB communication"), 0x80);
#endif #endif
goto FailUnknownDevice; goto FailUnknownDevice;
} } else if (PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) {
else if(PID == XBOX_WIRELESS_RECEIVER_PID || PID == XBOX_WIRELESS_RECEIVER_THIRD_PARTY_PID) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80); Notify(PSTR("\r\nThis library only supports Xbox 360 controllers via USB"), 0x80);
#endif #endif
goto FailUnknownDevice; goto FailUnknownDevice;
} }
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if (!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from device descriptor // Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr( 0, 0, bAddress ); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if (rcode) {
p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
#ifdef DEBUG
Notify(PSTR("\r\nsetAddr: "), 0x80);
#endif
PrintHex<uint8_t > (rcode, 0x80);
return rcode;
}
#ifdef EXTRADEBUG
Notify(PSTR("\r\nAddr: "), 0x80);
PrintHex<uint8_t > (bAddress, 0x80);
#endif
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress);
bAddress = 0;
#ifdef DEBUG
Notify(PSTR("\r\nsetAddr: "), 0x80);
#endif
PrintHex<uint8_t>(rcode, 0x80);
return rcode;
}
#ifdef EXTRADEBUG
Notify(PSTR("\r\nAddr: "), 0x80);
PrintHex<uint8_t>(bAddress, 0x80);
#endif
p->lowspeed = false;
//get pointer to assigned address record //get pointer to assigned address record
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if (!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Assign epInfo to epinfo pointer - only EP0 is known // Assign epInfo to epinfo pointer - only EP0 is known
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if (rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
/* The application will work in reduced host mode, so we can save program and data /* The application will work in reduced host mode, so we can save program and data
memory space. After verifying the VID we will use known values for the memory space. After verifying the VID we will use known values for the
configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */ configuration values for device, interface, endpoints and HID for the XBOX360 Controllers */
/* Initialize data structures for endpoints of device */ /* Initialize data structures for endpoints of device */
epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint epInfo[ XBOX_INPUT_PIPE ].epAddr = 0x01; // XBOX 360 report endpoint
epInfo[ XBOX_INPUT_PIPE ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_INPUT_PIPE ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_INPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_INPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_INPUT_PIPE ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_INPUT_PIPE ].bmRcvToggle = bmRCVTOG0;
epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint epInfo[ XBOX_OUTPUT_PIPE ].epAddr = 0x02; // XBOX 360 output endpoint
epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT; epInfo[ XBOX_OUTPUT_PIPE ].epAttribs = EP_INTERRUPT;
epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints epInfo[ XBOX_OUTPUT_PIPE ].bmNakPower = USB_NAK_NOWAIT; // Only poll once for interrupt endpoints
epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE; epInfo[ XBOX_OUTPUT_PIPE ].maxPktSize = EP_MAXPKTSIZE;
epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0; epInfo[ XBOX_OUTPUT_PIPE ].bmSndToggle = bmSNDTOG0;
epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0; epInfo[ XBOX_OUTPUT_PIPE ].bmRcvToggle = bmRCVTOG0;
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
if( rcode ) if (rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
delay(200);//Give time for address change delay(200); //Give time for address change
rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1); rcode = pUsb->setConf(bAddress, epInfo[ XBOX_CONTROL_PIPE ].epAddr, 1);
if( rcode ) if (rcode)
goto FailSetConf; goto FailSetConf;
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80); Notify(PSTR("\r\nXbox 360 Controller Connected\r\n"), 0x80);
#endif #endif
setLedOn(LED1); setLedOn(LED1);
Xbox360Connected = true; Xbox360Connected = true;
bPollEnable = true; bPollEnable = true;
return 0; // successful configuration return 0; // successful configuration
/* diagnostic messages */ /* diagnostic messages */
FailGetDevDescr: FailGetDevDescr:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\ngetDevDescr:"), 0x80); Notify(PSTR("\r\ngetDevDescr:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailSetDevTblEntry: FailSetDevTblEntry:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nsetDevTblEn:"), 0x80); Notify(PSTR("\r\nsetDevTblEn:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailSetConf: FailSetConf:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nsetConf:"), 0x80); Notify(PSTR("\r\nsetConf:"), 0x80);
#endif #endif
goto Fail; goto Fail;
FailUnknownDevice: FailUnknownDevice:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80); Notify(PSTR("\r\nUnknown Device Connected - VID: "), 0x80);
PrintHex<uint16_t>(VID, 0x80); PrintHex<uint16_t > (VID, 0x80);
Notify(PSTR(" PID: "), 0x80); Notify(PSTR(" PID: "), 0x80);
PrintHex<uint16_t>(PID, 0x80); PrintHex<uint16_t > (PID, 0x80);
#endif #endif
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
goto Fail; goto Fail;
Fail: Fail:
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80); Notify(PSTR("\r\nXbox 360 Init Failed, error code: "), 0x80);
Serial.print(rcode,HEX); Serial.print(rcode, HEX);
#endif #endif
Release(); Release();
return rcode; return rcode;
} }
/* Performs a cleanup after failed Init() attempt */ /* Performs a cleanup after failed Init() attempt */
uint8_t XBOXUSB::Release() { uint8_t XBOXUSB::Release() {
Xbox360Connected = false; Xbox360Connected = false;
pUsb->GetAddressPool().FreeAddress(bAddress); pUsb->GetAddressPool().FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
bPollEnable = false; bPollEnable = false;
return 0; return 0;
} }
uint8_t XBOXUSB::Poll() { uint8_t XBOXUSB::Poll() {
if (!bPollEnable) if (!bPollEnable)
return 0; return 0;
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE; uint16_t BUFFER_SIZE = EP_MAXPKTSIZE;
pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1 pUsb->inTransfer(bAddress, epInfo[ XBOX_INPUT_PIPE ].epAddr, &BUFFER_SIZE, readBuf); // input on endpoint 1
readReport(); readReport();
#ifdef PRINTREPORT #ifdef PRINTREPORT
printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller printReport(); // Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
#endif #endif
return 0; return 0;
} }
void XBOXUSB::readReport() { void XBOXUSB::readReport() {
if (readBuf == NULL) if (readBuf == NULL)
return; return;
if(readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports if (readBuf[0] != 0x00 || readBuf[1] != 0x14) { // Check if it's the correct report - the controller also sends different status reports
return; return;
} }
ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24)); ButtonState = (uint32_t)(readBuf[5] | ((uint16_t)readBuf[4] << 8) | ((uint32_t)readBuf[3] << 16) | ((uint32_t)readBuf[2] << 24));
hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]); hatValue[LeftHatX] = (int16_t)(((uint16_t)readBuf[7] << 8) | readBuf[6]);
hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]); hatValue[LeftHatY] = (int16_t)(((uint16_t)readBuf[9] << 8) | readBuf[8]);
hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]); hatValue[RightHatX] = (int16_t)(((uint16_t)readBuf[11] << 8) | readBuf[10]);
hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]); hatValue[RightHatY] = (int16_t)(((uint16_t)readBuf[13] << 8) | readBuf[12]);
//Notify(PSTR("\r\nButtonState"), 0x80); //Notify(PSTR("\r\nButtonState"), 0x80);
//PrintHex<uint32_t>(ButtonState, 0x80); //PrintHex<uint32_t>(ButtonState, 0x80);
if(ButtonState != OldButtonState) { if (ButtonState != OldButtonState) {
ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2 ButtonClickState = (ButtonState >> 16) & ((~OldButtonState) >> 16); // Update click state variable, but don't include the two trigger buttons L2 and R2
if(((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons if (((uint8_t)OldButtonState) == 0 && ((uint8_t)ButtonState) != 0) // The L2 and R2 buttons are special as they are analog buttons
R2Clicked = true; R2Clicked = true;
if((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0) if ((uint8_t)(OldButtonState >> 8) == 0 && (uint8_t)(ButtonState >> 8) != 0)
L2Clicked = true; L2Clicked = true;
OldButtonState = ButtonState; OldButtonState = ButtonState;
} }
} }
void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the report send by the Xbox 360 Controller
#ifdef PRINTREPORT #ifdef PRINTREPORT
if (readBuf == NULL) if (readBuf == NULL)
return; return;
for(uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE;i++) { for (uint8_t i = 0; i < XBOX_REPORT_BUFFER_SIZE; i++) {
PrintHex<uint8_t>(readBuf[i], 0x80); PrintHex<uint8_t > (readBuf[i], 0x80);
Serial.print(" "); Serial.print(" ");
} }
Serial.println(); Serial.println();
#endif #endif
} }
uint8_t XBOXUSB::getButtonPress(Button b) { uint8_t XBOXUSB::getButtonPress(Button b) {
if(b == L2) // These are analog buttons if (b == L2) // These are analog buttons
return (uint8_t)(ButtonState >> 8); return (uint8_t)(ButtonState >> 8);
else if(b == R2) else if (b == R2)
return (uint8_t)ButtonState; return (uint8_t)ButtonState;
return (ButtonState & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16)); return (ButtonState & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16));
} }
bool XBOXUSB::getButtonClick(Button b) { bool XBOXUSB::getButtonClick(Button b) {
if(b == L2) { if (b == L2) {
if(L2Clicked) { if (L2Clicked) {
L2Clicked = false; L2Clicked = false;
return true; return true;
}
return false;
} else if (b == R2) {
if (R2Clicked) {
R2Clicked = false;
return true;
}
return false;
} }
return false; uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]);
} bool click = (ButtonClickState & button);
else if(b == R2) { ButtonClickState &= ~button; // clear "click" event
if(R2Clicked) { return click;
R2Clicked = false;
return true;
}
return false;
}
uint16_t button = pgm_read_word(&XBOXBUTTONS[(uint8_t)b]);
bool click = (ButtonClickState & button);
ButtonClickState &= ~button; // clear "click" event
return click;
} }
int16_t XBOXUSB::getAnalogHat(AnalogHat a) { int16_t XBOXUSB::getAnalogHat(AnalogHat a) {
return hatValue[a]; return hatValue[a];
} }
/* Xbox Controller commands */ /* Xbox Controller commands */
void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) { void XBOXUSB::XboxCommand(uint8_t* data, uint16_t nbytes) {
//bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data) //bmRequest = Host to device (0x00) | Class (0x20) | Interface (0x01) = 0x21, bRequest = Set Report (0x09), Report ID (0x00), Report Type (Output 0x02), interface (0x00), datalength, datalength, data)
pUsb->ctrlReq(bAddress,epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL); pUsb->ctrlReq(bAddress, epInfo[XBOX_CONTROL_PIPE].epAddr, bmREQ_HID_OUT, HID_REQUEST_SET_REPORT, 0x00, 0x02, 0x00, nbytes, nbytes, data, NULL);
} }
void XBOXUSB::setLedRaw(uint8_t value) { void XBOXUSB::setLedRaw(uint8_t value) {
writeBuf[0] = 0x01; writeBuf[0] = 0x01;
writeBuf[1] = 0x03; writeBuf[1] = 0x03;
writeBuf[2] = value; writeBuf[2] = value;
XboxCommand(writeBuf, 3); XboxCommand(writeBuf, 3);
} }
void XBOXUSB::setLedOn(LED led) { void XBOXUSB::setLedOn(LED led) {
if(led != ALL) // All LEDs can't be on a the same time if (led != ALL) // All LEDs can't be on a the same time
setLedRaw((pgm_read_byte(&XBOXLEDS[(uint8_t)led]))+4); setLedRaw((pgm_read_byte(&XBOXLEDS[(uint8_t)led])) + 4);
} }
void XBOXUSB::setLedBlink(LED led) {
setLedRaw(pgm_read_byte(&XBOXLEDS[(uint8_t)led]));
}
void XBOXUSB::setLedMode(LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports
setLedRaw((uint8_t)ledMode);
}
void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) {
writeBuf[0] = 0x00;
writeBuf[1] = 0x08;
writeBuf[2] = 0x00;
writeBuf[3] = lValue; // big weight
writeBuf[4] = rValue; // small weight
writeBuf[5] = 0x00;
writeBuf[6] = 0x00;
writeBuf[7] = 0x00;
XboxCommand(writeBuf, 8); void XBOXUSB::setLedBlink(LED led) {
setLedRaw(pgm_read_byte(&XBOXLEDS[(uint8_t)led]));
}
void XBOXUSB::setLedMode(LEDMode ledMode) { // This function is used to do some speciel LED stuff the controller supports
setLedRaw((uint8_t)ledMode);
}
void XBOXUSB::setRumbleOn(uint8_t lValue, uint8_t rValue) {
writeBuf[0] = 0x00;
writeBuf[1] = 0x08;
writeBuf[2] = 0x00;
writeBuf[3] = lValue; // big weight
writeBuf[4] = rValue; // small weight
writeBuf[5] = 0x00;
writeBuf[6] = 0x00;
writeBuf[7] = 0x00;
XboxCommand(writeBuf, 8);
} }

247
XBOXUSB.h
View file

@ -58,135 +58,150 @@
/** This class implements support for a Xbox wired controller via USB. */ /** This class implements support for a Xbox wired controller via USB. */
class XBOXUSB : public USBDeviceConfig { class XBOXUSB : public USBDeviceConfig {
public: public:
/** /**
* Constructor for the XBOXUSB class. * Constructor for the XBOXUSB class.
* @param pUsb Pointer to USB class instance. * @param pUsb Pointer to USB class instance.
*/ */
XBOXUSB(USB *pUsb); XBOXUSB(USB *pUsb);
/** @name USBDeviceConfig implementation */ /** @name USBDeviceConfig implementation */
/** /**
* Initialize the Xbox Controller. * Initialize the Xbox Controller.
* @param parent Hub number. * @param parent Hub number.
* @param port Port number on the hub. * @param port Port number on the hub.
* @param lowspeed Speed of the device. * @param lowspeed Speed of the device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed); virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
/** /**
* Release the USB device. * Release the USB device.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Release(); virtual uint8_t Release();
/** /**
* Poll the USB Input endpoins and run the state machines. * Poll the USB Input endpoins and run the state machines.
* @return 0 on success. * @return 0 on success.
*/ */
virtual uint8_t Poll(); virtual uint8_t Poll();
/**
* Get the device address.
* @return The device address.
*/
virtual uint8_t GetAddress() { return bAddress; };
/**
* Used to check if the controller has been initialized.
* @return True if it's ready.
*/
virtual bool isReady() { return bPollEnable; };
/**@}*/
/** @name Xbox Controller functions */ /**
/** * Get the device address.
* getButtonPress(Button b) will return true as long as the button is held down. * @return The device address.
* */
* While getButtonClick(Button b) will only return it once. virtual uint8_t GetAddress() {
* return bAddress;
* So you instance if you need to increase a variable once you would use getButtonClick(Button b), };
* but if you need to drive a robot forward you would use getButtonPress(Button b).
* @param b ::Button to read.
* @return getButtonClick(Button b) will return a bool, but getButtonPress(Button b)
* will return a byte if reading ::L2 or ::R2.
*/
uint8_t getButtonPress(Button b);
bool getButtonClick(Button b);
/**@}*/
/** @name Xbox Controller functions */ /**
/** * Used to check if the controller has been initialized.
* Return the analog value from the joysticks on the controller. * @return True if it's ready.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. */
* @return Returns a signed 16-bit integer. virtual bool isReady() {
*/ return bPollEnable;
int16_t getAnalogHat(AnalogHat a); };
/**@}*/
/** Turn rumble off and all the LEDs on the controller. */ /** @name Xbox Controller functions */
void setAllOff() { setRumbleOn(0,0); setLedRaw(0); }; /**
/** Turn rumble off the controller. */ * getButtonPress(Button b) will return true as long as the button is held down.
void setRumbleOff() { setRumbleOn(0,0); }; *
/** * While getButtonClick(Button b) will only return it once.
* Turn rumble on. *
* @param lValue Left motor (big weight) inside the controller. * So you instance if you need to increase a variable once you would use getButtonClick(Button b),
* @param rValue Right motor (small weight) inside the controller. * but if you need to drive a robot forward you would use getButtonPress(Button b).
*/ * @param b ::Button to read.
void setRumbleOn(uint8_t lValue, uint8_t rValue); * @return getButtonClick(Button b) will return a bool, but getButtonPress(Button b)
/** * will return a byte if reading ::L2 or ::R2.
* Set LED value. Without using the ::LED or ::LEDMode enum. */
* @param value See: uint8_t getButtonPress(Button b);
* setLedOff(), setLedOn(LED l), bool getButtonClick(Button b);
* setLedBlink(LED l), and setLedMode(LEDMode lm). /**@}*/
*/
void setLedRaw(uint8_t value);
/** Turn all LEDs off the controller. */
void setLedOff() { setLedRaw(0); };
/**
* Turn on a LED by using the ::LED enum.
* @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedOn(LED l);
/**
* Turn on a LED by using the ::LED enum.
* @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedBlink(LED l);
/**
* Used to set special LED modes supported by the Xbox controller.
* @param controller The controller to write to.
* @param lm See ::LEDMode.
*/
void setLedMode(LEDMode lm);
/**@}*/
/** True if a Xbox 360 controller is connected. */ /** @name Xbox Controller functions */
bool Xbox360Connected; /**
* Return the analog value from the joysticks on the controller.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
* @return Returns a signed 16-bit integer.
*/
int16_t getAnalogHat(AnalogHat a);
/** Turn rumble off and all the LEDs on the controller. */
void setAllOff() {
setRumbleOn(0, 0);
setLedRaw(0);
};
/** Turn rumble off the controller. */
void setRumbleOff() {
setRumbleOn(0, 0);
};
/**
* Turn rumble on.
* @param lValue Left motor (big weight) inside the controller.
* @param rValue Right motor (small weight) inside the controller.
*/
void setRumbleOn(uint8_t lValue, uint8_t rValue);
/**
* Set LED value. Without using the ::LED or ::LEDMode enum.
* @param value See:
* setLedOff(), setLedOn(LED l),
* setLedBlink(LED l), and setLedMode(LEDMode lm).
*/
void setLedRaw(uint8_t value);
/** Turn all LEDs off the controller. */
void setLedOff() {
setLedRaw(0);
};
/**
* Turn on a LED by using the ::LED enum.
* @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedOn(LED l);
/**
* Turn on a LED by using the ::LED enum.
* @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
*/
void setLedBlink(LED l);
/**
* Used to set special LED modes supported by the Xbox controller.
* @param controller The controller to write to.
* @param lm See ::LEDMode.
*/
void setLedMode(LEDMode lm);
/**@}*/
/** True if a Xbox 360 controller is connected. */
bool Xbox360Connected;
protected: protected:
/** Pointer to USB class instance. */ /** Pointer to USB class instance. */
USB *pUsb; USB *pUsb;
/** Device address. */ /** Device address. */
uint8_t bAddress; uint8_t bAddress;
/** Endpoint info structure. */ /** Endpoint info structure. */
EpInfo epInfo[XBOX_MAX_ENDPOINTS]; EpInfo epInfo[XBOX_MAX_ENDPOINTS];
private: private:
bool bPollEnable; bool bPollEnable;
/* Variables to store the buttons */ /* Variables to store the buttons */
uint32_t ButtonState; uint32_t ButtonState;
uint32_t OldButtonState; uint32_t OldButtonState;
uint16_t ButtonClickState; uint16_t ButtonClickState;
int16_t hatValue[4]; int16_t hatValue[4];
uint16_t controllerStatus; uint16_t controllerStatus;
bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not
bool R2Clicked; bool R2Clicked;
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
void readReport(); // read incoming data void readReport(); // read incoming data
void printReport(); // print incoming date - Uncomment for debugging void printReport(); // print incoming date - Uncomment for debugging
/* Private commands */ /* Private commands */
void XboxCommand(uint8_t* data, uint16_t nbytes); void XboxCommand(uint8_t* data, uint16_t nbytes);
}; };
#endif #endif

View file

@ -40,9 +40,9 @@ struct EpInfo {
uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
}__attribute__((packed)); } __attribute__((packed));
}; };
}__attribute__((packed)); } __attribute__((packed));
// 7 6 5 4 3 2 1 0 // 7 6 5 4 3 2 1 0
// --------------------------------- // ---------------------------------
@ -63,10 +63,10 @@ struct UsbDeviceAddress {
uint8_t bmParent : 3; // parent hub address uint8_t bmParent : 3; // parent hub address
uint8_t bmHub : 1; // hub flag uint8_t bmHub : 1; // hub flag
uint8_t bmReserved : 1; // reserved, must be zerro uint8_t bmReserved : 1; // reserved, must be zerro
}__attribute__((packed)); } __attribute__((packed));
uint8_t devAddress; uint8_t devAddress;
}; };
}__attribute__((packed)); } __attribute__((packed));
#define bmUSB_DEV_ADDR_ADDRESS 0x07 #define bmUSB_DEV_ADDR_ADDRESS 0x07
#define bmUSB_DEV_ADDR_PARENT 0x38 #define bmUSB_DEV_ADDR_PARENT 0x38
@ -78,7 +78,7 @@ struct UsbDevice {
uint8_t epcount; // number of endpoints uint8_t epcount; // number of endpoints
bool lowspeed; // indicates if a device is the low speed one bool lowspeed; // indicates if a device is the low speed one
// uint8_t devclass; // device class // uint8_t devclass; // device class
}__attribute__((packed)); } __attribute__((packed));
class AddressPool { class AddressPool {
public: public:
@ -112,8 +112,8 @@ class AddressPoolImpl : public AddressPool {
// Returns thePool index for a given address // Returns thePool index for a given address
uint8_t FindAddressIndex(uint8_t address = 0) { uint8_t FindAddressIndex(uint8_t address = 0) {
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) { for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) {
if (thePool[i].address == address) if(thePool[i].address == address)
return i; return i;
} }
return 0; return 0;
@ -121,8 +121,8 @@ class AddressPoolImpl : public AddressPool {
// Returns thePool child index for a given parent // Returns thePool child index for a given parent
uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) { uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {
for (uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) { for(uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
if (((UsbDeviceAddress*) & thePool[i].address)->bmParent == addr.bmAddress) if(((UsbDeviceAddress*) & thePool[i].address)->bmParent == addr.bmAddress)
return i; return i;
} }
return 0; return 0;
@ -131,16 +131,16 @@ class AddressPoolImpl : public AddressPool {
void FreeAddressByIndex(uint8_t index) { void FreeAddressByIndex(uint8_t index) {
// Zerro field is reserved and should not be affected // Zerro field is reserved and should not be affected
if (index == 0) if(index == 0)
return; return;
// If a hub was switched off all port addresses should be freed // If a hub was switched off all port addresses should be freed
if (((UsbDeviceAddress*) & thePool[index].address)->bmHub == 1) { if(((UsbDeviceAddress*) & thePool[index].address)->bmHub == 1) {
for (uint8_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*) & thePool[index].address), i));) for(uint8_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*) & thePool[index].address), i));)
FreeAddressByIndex(i); FreeAddressByIndex(i);
// If the hub had the last allocated address, hubCounter should be decremented // If the hub had the last allocated address, hubCounter should be decremented
if (hubCounter == ((UsbDeviceAddress*) & thePool[index].address)->bmAddress) if(hubCounter == ((UsbDeviceAddress*) & thePool[index].address)->bmAddress)
hubCounter--; hubCounter--;
} }
InitEntry(index); InitEntry(index);
@ -148,7 +148,7 @@ class AddressPoolImpl : public AddressPool {
// Initializes the whole address pool at once // Initializes the whole address pool at once
void InitAllAddresses() { void InitAllAddresses() {
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
InitEntry(i); InitEntry(i);
hubCounter = 0; hubCounter = 0;
@ -172,22 +172,22 @@ public:
// Returns a pointer to a specified address entry // Returns a pointer to a specified address entry
virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) { virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) {
if (!addr) if(!addr)
return thePool; return thePool;
uint8_t index = FindAddressIndex(addr); uint8_t index = FindAddressIndex(addr);
return (!index) ? NULL : thePool + index; return(!index) ? NULL : thePool + index;
}; };
// Performs an operation specified by pfunc for each addressed device // Performs an operation specified by pfunc for each addressed device
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) { void ForEachUsbDevice(UsbDeviceHandleFunc pfunc) {
if (!pfunc) if(!pfunc)
return; return;
for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++) for(uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
if (thePool[i].address) if(thePool[i].address)
pfunc(thePool + i); pfunc(thePool + i);
}; };
// Allocates new address // Allocates new address
@ -196,20 +196,20 @@ public:
/* if (parent != 0 && port == 0) /* if (parent != 0 && port == 0)
Serial.println("PRT:0"); */ Serial.println("PRT:0"); */
if (parent > 127 || port > 7) if(parent > 127 || port > 7)
return 0; return 0;
if (is_hub && hubCounter == 7) if(is_hub && hubCounter == 7)
return 0; return 0;
// finds first empty address entry starting from one // finds first empty address entry starting from one
uint8_t index = FindAddressIndex(0); uint8_t index = FindAddressIndex(0);
if (!index) // if empty entry is not found if(!index) // if empty entry is not found
return 0; return 0;
if (parent == 0) { if(parent == 0) {
if (is_hub) { if(is_hub) {
thePool[index].address = 0x41; thePool[index].address = 0x41;
hubCounter++; hubCounter++;
} else } else
@ -222,7 +222,7 @@ public:
addr.bmParent = ((UsbDeviceAddress*) & parent)->bmAddress; addr.bmParent = ((UsbDeviceAddress*) & parent)->bmAddress;
if (is_hub) { if(is_hub) {
addr.bmHub = 1; addr.bmHub = 1;
addr.bmAddress = ++hubCounter; addr.bmAddress = ++hubCounter;
} else { } else {
@ -244,7 +244,7 @@ public:
virtual void FreeAddress(uint8_t addr) { virtual void FreeAddress(uint8_t addr) {
// if the root hub is disconnected all the addresses should be initialized // if the root hub is disconnected all the addresses should be initialized
if (addr == 0x41) { if(addr == 0x41) {
InitAllAddresses(); InitAllAddresses();
return; return;
} }

15
adk.cpp
View file

@ -41,8 +41,7 @@ pUsb(p), //pointer to USB class instance - mandatory
bAddress(0), //device address - mandatory bAddress(0), //device address - mandatory
bConfNum(0), //configuration number bConfNum(0), //configuration number
bNumEP(1), //if config descriptor needs to be parsed bNumEP(1), //if config descriptor needs to be parsed
ready(false) ready(false) {
{
// initialize endpoint data structures // initialize endpoint data structures
for (uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) { for (uint8_t i = 0; i < ADK_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
@ -101,7 +100,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -114,7 +113,7 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
// Extract Max Packet Size from device descriptor // Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
@ -145,11 +144,11 @@ uint8_t ADK::Init(uint8_t parent, uint8_t port, bool lowspeed) {
} }
//check if ADK device is already in accessory mode; if yes, configure and exit //check if ADK device is already in accessory mode; if yes, configure and exit
if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor == ADK_VID && if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor == ADK_VID &&
(((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct == ADB_PID)) { (((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADK_PID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct == ADB_PID)) {
USBTRACE("\r\nAcc.mode device detected"); USBTRACE("\r\nAcc.mode device detected");
/* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */ /* go through configurations, find first bulk-IN, bulk-OUT EP, fill epInfo and quit */
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
//USBTRACE2("\r\nNC:",num_of_conf); //USBTRACE2("\r\nNC:",num_of_conf);
@ -286,7 +285,7 @@ void ADK::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
bNumEP++; bNumEP++;

6
adk.h
View file

@ -133,17 +133,17 @@ public:
/* returns 2 bytes in *adkproto */ /* returns 2 bytes in *adkproto */
inline uint8_t ADK::getProto(uint8_t* adkproto) { inline uint8_t ADK::getProto(uint8_t* adkproto) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_GET, ADK_GETPROTO, 0, 0, 0, 2, 2, adkproto, NULL));
} }
/* send ADK string */ /* send ADK string */
inline uint8_t ADK::sendStr(uint8_t index, const char* str) { inline uint8_t ADK::sendStr(uint8_t index, const char* str) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*) str, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_SENDSTR, 0, 0, index, strlen(str) + 1, strlen(str) + 1, (uint8_t*) str, NULL));
} }
/* switch to accessory mode */ /* switch to accessory mode */
inline uint8_t ADK::switchAcc(void) { inline uint8_t ADK::switchAcc(void) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_ADK_SEND, ADK_ACCSTART, 0, 0, 0, 0, 0, NULL, NULL));
} }
#endif // _ADK_H_ #endif // _ADK_H_

View file

@ -178,13 +178,13 @@ public:
} }
static void Set(uint8_t val) { static void Set(uint8_t val) {
if (val) if(val)
Set(); Set();
else Clear(); else Clear();
} }
static void SetDir(uint8_t val) { static void SetDir(uint8_t val) {
if (val) if(val)
SetDirWrite(); SetDirWrite();
else SetDirRead(); else SetDirRead();
} }
@ -210,12 +210,12 @@ public:
} }
static void WaiteForSet() { static void WaiteForSet() {
while (IsSet() == 0) { while(IsSet() == 0) {
} }
} }
static void WaiteForClear() { static void WaiteForClear() {
while (IsSet()) { while(IsSet()) {
} }
} }
}; //class TPin... }; //class TPin...
@ -411,7 +411,7 @@ class Tp_Tc {
public: public:
static void SetDir(uint8_t val) { static void SetDir(uint8_t val) {
if (val) if(val)
SetDirWrite(); SetDirWrite();
else SetDirRead(); else SetDirRead();
} }

View file

@ -79,7 +79,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -94,7 +94,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
@ -118,7 +118,7 @@ uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
@ -226,7 +226,7 @@ void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0; epInfo[index].epAttribs = 0;
bNumEP++; bNumEP++;
@ -304,11 +304,11 @@ uint8_t ACM::ClearCommFeature(uint16_t fid) {
} }
uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) { uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*) dataptr, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
} }
uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) { uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*) dataptr, NULL)); return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
} }
uint8_t ACM::SetControlLineState(uint8_t state) { uint8_t ACM::SetControlLineState(uint8_t state) {

View file

@ -78,7 +78,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -86,11 +86,11 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
if (rcode) if (rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct != FTDI_PID) if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != FTDI_VID || ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != FTDI_PID)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Save type of FTDI chip // Save type of FTDI chip
wFTDIType = ((USB_DEVICE_DESCRIPTOR*) buf)->bcdDevice; wFTDIType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
@ -99,7 +99,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
@ -123,7 +123,7 @@ uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
@ -224,7 +224,7 @@ void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t prot
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0; epInfo[index].epAttribs = 0;
bNumEP++; bNumEP++;

View file

@ -57,7 +57,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), (uint8_t*)buf);
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -65,11 +65,11 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
if (rcode) if (rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
if (((USB_DEVICE_DESCRIPTOR*) buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*) buf)->idProduct != PL_PID) if (((USB_DEVICE_DESCRIPTOR*)buf)->idVendor != PL_VID && ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct != PL_PID)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Save type of PL chip // Save type of PL chip
wPLType = ((USB_DEVICE_DESCRIPTOR*) buf)->bcdDevice; wPLType = ((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
@ -78,7 +78,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
@ -102,7 +102,7 @@ uint8_t PL2303::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);

View file

@ -85,8 +85,8 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uin
uint16_t cntdn = (uint16_t) len; uint16_t cntdn = (uint16_t) len;
uint8_t *p = (uint8_t*) pbuf; uint8_t *p = (uint8_t*) pbuf;
while (cntdn) while(cntdn)
if (!ParseDescriptor(&p, &cntdn)) if(!ParseDescriptor(&p, &cntdn))
return; return;
} }
@ -94,13 +94,13 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uin
compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK> template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) { bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint16_t *pcntdn) {
switch (stateParseDescr) { switch(stateParseDescr) {
case 0: case 0:
theBuffer.valueSize = 2; theBuffer.valueSize = 2;
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
stateParseDescr = 1; stateParseDescr = 1;
case 1: case 1:
if (!valParser.Parse(pp, pcntdn)) if(!valParser.Parse(pp, pcntdn))
return false; return false;
dscrLen = *((uint8_t*) theBuffer.pValue); dscrLen = *((uint8_t*) theBuffer.pValue);
dscrType = *((uint8_t*) theBuffer.pValue + 1); dscrType = *((uint8_t*) theBuffer.pValue + 1);
@ -114,14 +114,14 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
theBuffer.pValue = varBuffer + 2; theBuffer.pValue = varBuffer + 2;
stateParseDescr = 3; stateParseDescr = 3;
case 3: case 3:
switch (dscrType) { switch(dscrType) {
case USB_DESCRIPTOR_INTERFACE: case USB_DESCRIPTOR_INTERFACE:
isGoodInterface = false; isGoodInterface = false;
case USB_DESCRIPTOR_CONFIGURATION: case USB_DESCRIPTOR_CONFIGURATION:
theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2; theBuffer.valueSize = sizeof(USB_CONFIGURATION_DESCRIPTOR) - 2;
break; break;
case USB_DESCRIPTOR_ENDPOINT: case USB_DESCRIPTOR_ENDPOINT:
theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2; theBuffer.valueSize = sizeof(USB_ENDPOINT_DESCRIPTOR) - 2;
break; break;
case HID_DESCRIPTOR_HID: case HID_DESCRIPTOR_HID:
theBuffer.valueSize = dscrLen - 2; theBuffer.valueSize = dscrLen - 2;
@ -130,20 +130,20 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
valParser.Initialize(&theBuffer); valParser.Initialize(&theBuffer);
stateParseDescr = 4; stateParseDescr = 4;
case 4: case 4:
switch (dscrType) { switch(dscrType) {
case USB_DESCRIPTOR_CONFIGURATION: case USB_DESCRIPTOR_CONFIGURATION:
if (!valParser.Parse(pp, pcntdn)) if(!valParser.Parse(pp, pcntdn))
return false; return false;
confValue = ((USB_CONFIGURATION_DESCRIPTOR*) varBuffer)->bConfigurationValue; confValue = ((USB_CONFIGURATION_DESCRIPTOR*) varBuffer)->bConfigurationValue;
break; break;
case USB_DESCRIPTOR_INTERFACE: case USB_DESCRIPTOR_INTERFACE:
if (!valParser.Parse(pp, pcntdn)) if(!valParser.Parse(pp, pcntdn))
return false; return false;
if ((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceClass != CLASS_ID) if((MASK & CP_MASK_COMPARE_CLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceClass != CLASS_ID)
break; break;
if ((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceSubClass != SUBCLASS_ID) if((MASK & CP_MASK_COMPARE_SUBCLASS) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceSubClass != SUBCLASS_ID)
break; break;
if ((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol != PROTOCOL_ID) if((MASK & CP_MASK_COMPARE_PROTOCOL) && ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol != PROTOCOL_ID)
break; break;
isGoodInterface = true; isGoodInterface = true;
@ -152,10 +152,10 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
protoValue = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol; protoValue = ((USB_INTERFACE_DESCRIPTOR*) varBuffer)->bInterfaceProtocol;
break; break;
case USB_DESCRIPTOR_ENDPOINT: case USB_DESCRIPTOR_ENDPOINT:
if (!valParser.Parse(pp, pcntdn)) if(!valParser.Parse(pp, pcntdn))
return false; return false;
if (isGoodInterface) if(isGoodInterface)
if (theXtractor) if(theXtractor)
theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*) varBuffer); theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*) varBuffer);
break; break;
//case HID_DESCRIPTOR_HID: //case HID_DESCRIPTOR_HID:
@ -164,7 +164,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
// PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer); // PrintHidDescriptor((const USB_HID_DESCRIPTOR*)varBuffer);
// break; // break;
default: default:
if (!theSkipper.Skip(pp, pcntdn, dscrLen - 2)) if(!theSkipper.Skip(pp, pcntdn, dscrLen - 2))
return false; return false;
} }
theBuffer.pValue = varBuffer; theBuffer.pValue = varBuffer;
@ -197,7 +197,7 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescrip
//Notify(PSTR("\r\nwDescriptorLength:\t")); //Notify(PSTR("\r\nwDescriptorLength:\t"));
//PrintHex<uint16_t>(pDesc->wDescriptorLength); //PrintHex<uint16_t>(pDesc->wDescriptorLength);
for (uint8_t i = 0; i < pDesc->bNumDescriptors; i++) { for(uint8_t i = 0; i < pDesc->bNumDescriptors; i++) {
HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType); HID_CLASS_DESCRIPTOR_LEN_AND_TYPE *pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);

View file

@ -21,96 +21,98 @@
/* /*
This header file is used to store different enums for the controllers, This header file is used to store different enums for the controllers,
This is necessary so all the different libraries can be used at once This is necessary so all the different libraries can be used at once
*/ */
/** Enum used to turn on the LEDs on the different controllers. */ /** Enum used to turn on the LEDs on the different controllers. */
enum LED { enum LED {
LED1 = 0, LED1 = 0,
LED2 = 1, LED2 = 1,
LED3 = 2, LED3 = 2,
LED4 = 3, LED4 = 3,
LED5 = 4, LED5 = 4,
LED6 = 5, LED6 = 5,
LED7 = 6, LED7 = 6,
LED8 = 7, LED8 = 7,
LED9 = 8, LED9 = 8,
LED10 = 9, LED10 = 9,
/** Used to blink all LEDs on the Xbox controller */ /** Used to blink all LEDs on the Xbox controller */
ALL = 4, ALL = 4,
}; };
/** This enum is used to read all the different buttons on the different controllers */ /** This enum is used to read all the different buttons on the different controllers */
enum Button { enum Button {
/**@{*/ /**@{*/
/** These buttons are available on all the the controllers */ /** These buttons are available on all the the controllers */
UP = 0, UP = 0,
RIGHT = 1, RIGHT = 1,
DOWN = 2, DOWN = 2,
LEFT = 3, LEFT = 3,
/**@}*/ /**@}*/
/**@{*/ /**@{*/
/** Wii buttons */ /** Wii buttons */
PLUS = 5, PLUS = 5,
TWO = 6, TWO = 6,
ONE = 7, ONE = 7,
MINUS = 8, MINUS = 8,
HOME = 9, HOME = 9,
Z = 10, Z = 10,
C = 11, C = 11,
B = 12, B = 12,
A = 13, A = 13,
/**@}*/ /**@}*/
/**@{*/ /**@{*/
/** These are only available on the Wii U Pro Controller */ /** These are only available on the Wii U Pro Controller */
L = 16, L = 16,
R = 17, R = 17,
ZL = 18, ZL = 18,
ZR = 19, ZR = 19,
/**@}*/ /**@}*/
/**@{*/ /**@{*/
/** PS3 controllers buttons */ /** PS3 controllers buttons */
SELECT = 4, SELECT = 4,
START = 5, START = 5,
L3 = 6, L3 = 6,
R3 = 7, R3 = 7,
L2 = 8, L2 = 8,
R2 = 9, R2 = 9,
L1 = 10, L1 = 10,
R1 = 11, R1 = 11,
TRIANGLE = 12, TRIANGLE = 12,
CIRCLE = 13, CIRCLE = 13,
CROSS = 14, CROSS = 14,
SQUARE = 15, SQUARE = 15,
PS = 16, PS = 16,
MOVE = 17, // Covers 12 bits - we only need to read the top 8 MOVE = 17, // Covers 12 bits - we only need to read the top 8
T = 18, // Covers 12 bits - we only need to read the top 8 T = 18, // Covers 12 bits - we only need to read the top 8
/**@}*/ /**@}*/
/**@{*/ /**@{*/
/** Xbox buttons */ /** Xbox buttons */
BACK = 4, BACK = 4,
X = 14, X = 14,
Y = 15, Y = 15,
XBOX = 16, XBOX = 16,
SYNC = 17, SYNC = 17,
/**@}*/ /**@}*/
}; };
/** Joysticks on the PS3 and Xbox controllers. */ /** Joysticks on the PS3 and Xbox controllers. */
enum AnalogHat { enum AnalogHat {
/** Left joystick x-axis */ /** Left joystick x-axis */
LeftHatX = 0, LeftHatX = 0,
/** Left joystick y-axis */ /** Left joystick y-axis */
LeftHatY = 1, LeftHatY = 1,
/** Right joystick x-axis */ /** Right joystick x-axis */
RightHatX = 2, RightHatX = 2,
/** Right joystick y-axis */ /** Right joystick y-axis */
RightHatY = 3, RightHatY = 3,
}; };
#endif #endif

View file

@ -41,15 +41,15 @@ public:
template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE> template <class BASE_CLASS, class LEN_TYPE, class OFFSET_TYPE>
void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) { void HexDumper<BASE_CLASS, LEN_TYPE, OFFSET_TYPE>::Parse(const LEN_TYPE len, const uint8_t *pbuf, const OFFSET_TYPE &offset) {
for (LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) { for(LEN_TYPE j = 0; j < len; j++, byteCount++, byteTotal++) {
if (!byteCount) { if(!byteCount) {
SerialPrintHex<OFFSET_TYPE > (byteTotal); SerialPrintHex<OFFSET_TYPE > (byteTotal);
Serial.print(": "); Serial.print(": ");
} }
SerialPrintHex<uint8_t > (pbuf[j]); SerialPrintHex<uint8_t > (pbuf[j]);
Serial.print(" "); Serial.print(" ");
if (byteCount == 15) { if(byteCount == 15) {
Serial.println(""); Serial.println("");
byteCount = 0xFF; byteCount = 0xFF;
} }

View file

@ -7,7 +7,7 @@ uint8_t HID::GetReportDescr(uint8_t ep, USBReadParser *parser) {
uint8_t buf[constBufLen]; uint8_t buf[constBufLen];
uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00, uint8_t rcode = pUsb->ctrlReq(bAddress, ep, bmREQ_HIDREPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*) parser); HID_DESCRIPTOR_REPORT, 0x0000, 128, constBufLen, buf, (USBReadParser*)parser);
//return ((rcode != hrSTALL) ? rcode : 0); //return ((rcode != hrSTALL) ? rcode : 0);
return rcode; return rcode;

View file

@ -17,7 +17,7 @@ e-mail : support@circuitsathome.com
#include "hidboot.h" #include "hidboot.h"
void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) { void MouseReportParser::Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
MOUSEINFO *pmi = (MOUSEINFO*) buf; MOUSEINFO *pmi = (MOUSEINFO*)buf;
if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1) if (prevState.mouseInfo.bmLeftButton == 0 && pmi->bmLeftButton == 1)
OnLeftButtonDown(pmi); OnLeftButtonDown(pmi);
@ -112,20 +112,20 @@ uint8_t KeyboardReportParser::OemToAscii(uint8_t mod, uint8_t key) {
// Lower case letters // Lower case letters
else else
return (key - 4 + 'a'); return (key - 4 + 'a');
} // Numbers }// Numbers
else if (key > 0x1d && key < 0x27) { else if (key > 0x1d && key < 0x27) {
if (shift) if (shift)
return ((uint8_t) pgm_read_byte(&numKeys[key - 0x1e])); return ((uint8_t)pgm_read_byte(&numKeys[key - 0x1e]));
else else
return (key - 0x1e + '1'); return (key - 0x1e + '1');
} // Keypad Numbers }// Keypad Numbers
else if (key > 0x58 && key < 0x62) { else if (key > 0x58 && key < 0x62) {
if (kbdLockingKeys.kbdLeds.bmNumLock == 1) if (kbdLockingKeys.kbdLeds.bmNumLock == 1)
return (key - 0x59 + '1'); return (key - 0x59 + '1');
} else if (key > 0x2c && key < 0x39) } else if (key > 0x2c && key < 0x39)
return ((shift) ? (uint8_t) pgm_read_byte(&symKeysUp[key - 0x2d]) : (uint8_t) pgm_read_byte(&symKeysLo[key - 0x2d])); return ((shift) ? (uint8_t)pgm_read_byte(&symKeysUp[key - 0x2d]) : (uint8_t)pgm_read_byte(&symKeysLo[key - 0x2d]));
else if (key > 0x53 && key < 0x59) else if (key > 0x53 && key < 0x59)
return (uint8_t) pgm_read_byte(&padKeys[key - 0x54]); return (uint8_t)pgm_read_byte(&padKeys[key - 0x54]);
else { else {
switch (key) { switch (key) {
case KEY_SPACE: return (0x20); case KEY_SPACE: return (0x20);

View file

@ -60,7 +60,7 @@ class MouseReportParser : public HIDReportParser {
union { union {
MOUSEINFO mouseInfo; MOUSEINFO mouseInfo;
uint8_t bInfo[sizeof (MOUSEINFO)]; uint8_t bInfo[sizeof(MOUSEINFO)];
} prevState; } prevState;
public: public:
@ -140,7 +140,7 @@ protected:
union { union {
KBDINFO kbdInfo; KBDINFO kbdInfo;
uint8_t bInfo[sizeof (KBDINFO)]; uint8_t bInfo[sizeof(KBDINFO)];
} prevState; } prevState;
union { union {
@ -221,13 +221,13 @@ bPollEnable(false),
pRptParser(NULL) { pRptParser(NULL) {
Initialize(); Initialize();
if (pUsb) if(pUsb)
pUsb->RegisterDeviceClass(this); pUsb->RegisterDeviceClass(this);
} }
template <const uint8_t BOOT_PROTOCOL> template <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::Initialize() { void HIDBoot<BOOT_PROTOCOL>::Initialize() {
for (uint8_t i = 0; i < totalEndpoints; i++) { for(uint8_t i = 0; i < totalEndpoints; i++) {
epInfo[i].epAddr = 0; epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8; epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0; epInfo[i].epAttribs = 0;
@ -240,7 +240,7 @@ void HIDBoot<BOOT_PROTOCOL>::Initialize() {
template <const uint8_t BOOT_PROTOCOL> template <const uint8_t BOOT_PROTOCOL>
uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed) { uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed) {
const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR); const uint8_t constBufSize = sizeof(USB_DEVICE_DESCRIPTOR);
uint8_t buf[constBufSize]; uint8_t buf[constBufSize];
uint8_t rcode; uint8_t rcode;
@ -256,16 +256,16 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
USBTRACE("BM Init\r\n"); USBTRACE("BM Init\r\n");
if (bAddress) if(bAddress)
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE; return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
// Get pointer to pseudo device with address 0 assigned // Get pointer to pseudo device with address 0 assigned
p = addrPool.GetUsbDevicePtr(0); p = addrPool.GetUsbDevicePtr(0);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
if (!p->epinfo) { if(!p->epinfo) {
USBTRACE("epinfo\r\n"); USBTRACE("epinfo\r\n");
return USB_ERROR_EPINFO_IS_NULL; return USB_ERROR_EPINFO_IS_NULL;
} }
@ -281,10 +281,10 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf);
if (!rcode) if(!rcode)
len = (buf[0] > constBufSize) ? constBufSize : buf[0]; len = (buf[0] > constBufSize) ? constBufSize : buf[0];
if (rcode) { if(rcode) {
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -297,7 +297,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, false, port); bAddress = addrPool.AllocAddress(parent, false, port);
if (!bAddress) if(!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
@ -306,7 +306,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
if (rcode) { if(rcode) {
p->lowspeed = false; p->lowspeed = false;
addrPool.FreeAddress(bAddress); addrPool.FreeAddress(bAddress);
bAddress = 0; bAddress = 0;
@ -320,15 +320,15 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
p = addrPool.GetUsbDevicePtr(bAddress); p = addrPool.GetUsbDevicePtr(bAddress);
if (!p) if(!p)
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL; return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
if (len) if(len)
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf);
if (rcode) if(rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations;
@ -336,12 +336,12 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
if (rcode) if(rcode)
goto FailSetDevTblEntry; goto FailSetDevTblEntry;
//USBTRACE2("NC:", num_of_conf); //USBTRACE2("NC:", num_of_conf);
for (uint8_t i = 0; i < num_of_conf; i++) { for(uint8_t i = 0; i < num_of_conf; i++) {
ConfigDescParser< ConfigDescParser<
USB_CLASS_HID, USB_CLASS_HID,
HID_BOOT_INTF_SUBCLASS, HID_BOOT_INTF_SUBCLASS,
@ -350,11 +350,11 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
if (bNumEP > 1) if(bNumEP > 1)
break; break;
} // for } // for
if (bNumEP < 2) if(bNumEP < 2)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
//USBTRACE2("\r\nbAddr:", bAddress); //USBTRACE2("\r\nbAddr:", bAddress);
@ -368,20 +368,20 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Init(uint8_t parent, uint8_t port, bool lowspeed
// Set Configuration Value // Set Configuration Value
rcode = pUsb->setConf(bAddress, 0, bConfNum); rcode = pUsb->setConf(bAddress, 0, bConfNum);
if (rcode) if(rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
//USBTRACE2("\r\nIf:", bIfaceNum); //USBTRACE2("\r\nIf:", bIfaceNum);
rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL); rcode = SetProtocol(bIfaceNum, HID_BOOT_PROTOCOL);
if (rcode) if(rcode)
goto FailSetProtocol; goto FailSetProtocol;
if (BOOT_PROTOCOL == 1) { if(BOOT_PROTOCOL == 1) {
rcode = SetIdle(bIfaceNum, 0, 0); rcode = SetIdle(bIfaceNum, 0, 0);
if (rcode) if(rcode)
goto FailSetIdle; goto FailSetIdle;
} }
USBTRACE("BM configured\r\n"); USBTRACE("BM configured\r\n");
@ -424,7 +424,7 @@ Fail:
template <const uint8_t BOOT_PROTOCOL> template <const uint8_t BOOT_PROTOCOL>
void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) { void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
// If the first configuration satisfies, the others are not concidered. // If the first configuration satisfies, the others are not concidered.
if (bNumEP > 1 && conf != bConfNum) if(bNumEP > 1 && conf != bConfNum)
return; return;
bConfNum = conf; bConfNum = conf;
@ -432,7 +432,7 @@ void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t
uint8_t index; uint8_t index;
if ((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) { if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80) {
index = epInterruptInIndex; index = epInterruptInIndex;
// Fill in the endpoint info structure // Fill in the endpoint info structure
@ -461,10 +461,10 @@ template <const uint8_t BOOT_PROTOCOL>
uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() { uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
uint8_t rcode = 0; uint8_t rcode = 0;
if (!bPollEnable) if(!bPollEnable)
return 0; return 0;
if (qNextPollTime <= millis()) { if(qNextPollTime <= millis()) {
qNextPollTime = millis() + 10; qNextPollTime = millis() + 10;
const uint8_t const_buff_len = 16; const uint8_t const_buff_len = 16;
@ -474,8 +474,8 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf); uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
if (rcode) { if(rcode) {
if (rcode != hrNAK) if(rcode != hrNAK)
USBTRACE2("Poll:", rcode); USBTRACE2("Poll:", rcode);
return rcode; return rcode;
} }
@ -484,7 +484,7 @@ uint8_t HIDBoot<BOOT_PROTOCOL>::Poll() {
//if (read) //if (read)
// Serial.println(""); // Serial.println("");
if (pRptParser) if(pRptParser)
pRptParser->Parse((HID*)this, 0, (uint8_t) read, buf); pRptParser->Parse((HID*)this, 0, (uint8_t) read, buf);
} }
return rcode; return rcode;

View file

@ -1,6 +1,6 @@
#include "hidescriptorparser.h" #include "hidescriptorparser.h"
const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM ={ const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM = {
pstrUsagePageGenericDesktopControls, pstrUsagePageGenericDesktopControls,
pstrUsagePageSimulationControls, pstrUsagePageSimulationControls,
pstrUsagePageVRControls, pstrUsagePageVRControls,
@ -18,7 +18,7 @@ const char * const ReportDescParserBase::usagePageTitles0[] PROGMEM ={
pstrUsagePageUnicode pstrUsagePageUnicode
}; };
const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM ={ const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM = {
pstrUsagePageBarCodeScanner, pstrUsagePageBarCodeScanner,
pstrUsagePageScale, pstrUsagePageScale,
pstrUsagePageMSRDevices, pstrUsagePageMSRDevices,
@ -26,7 +26,7 @@ const char * const ReportDescParserBase::usagePageTitles1[] PROGMEM ={
pstrUsagePageCameraControl, pstrUsagePageCameraControl,
pstrUsagePageArcade pstrUsagePageArcade
}; };
const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM ={ const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM = {
pstrUsagePointer, pstrUsagePointer,
pstrUsageMouse, pstrUsageMouse,
pstrUsageJoystick, pstrUsageJoystick,
@ -37,7 +37,7 @@ const char * const ReportDescParserBase::genDesktopTitles0[] PROGMEM ={
pstrUsageTabletPCSystemControls pstrUsageTabletPCSystemControls
}; };
const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM ={ const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM = {
pstrUsageX, pstrUsageX,
pstrUsageY, pstrUsageY,
pstrUsageZ, pstrUsageZ,
@ -64,7 +64,7 @@ const char * const ReportDescParserBase::genDesktopTitles1[] PROGMEM ={
pstrUsageFeatureNotification, pstrUsageFeatureNotification,
pstrUsageResolutionMultiplier pstrUsageResolutionMultiplier
}; };
const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM ={ const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM = {
pstrUsageSystemControl, pstrUsageSystemControl,
pstrUsageSystemPowerDown, pstrUsageSystemPowerDown,
pstrUsageSystemSleep, pstrUsageSystemSleep,
@ -86,7 +86,7 @@ const char * const ReportDescParserBase::genDesktopTitles2[] PROGMEM ={
pstrUsageDPadRight, pstrUsageDPadRight,
pstrUsageDPadLeft pstrUsageDPadLeft
}; };
const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM ={ const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM = {
pstrUsageSystemDock, pstrUsageSystemDock,
pstrUsageSystemUndock, pstrUsageSystemUndock,
pstrUsageSystemSetup, pstrUsageSystemSetup,
@ -97,7 +97,7 @@ const char * const ReportDescParserBase::genDesktopTitles3[] PROGMEM ={
pstrUsageSystemSpeakerMute, pstrUsageSystemSpeakerMute,
pstrUsageSystemHibernate pstrUsageSystemHibernate
}; };
const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM ={ const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM = {
pstrUsageSystemDisplayInvert, pstrUsageSystemDisplayInvert,
pstrUsageSystemDisplayInternal, pstrUsageSystemDisplayInternal,
pstrUsageSystemDisplayExternal, pstrUsageSystemDisplayExternal,
@ -107,7 +107,7 @@ const char * const ReportDescParserBase::genDesktopTitles4[] PROGMEM ={
pstrUsageSystemDisplaySwapPriSec, pstrUsageSystemDisplaySwapPriSec,
pstrUsageSystemDisplayLCDAutoscale pstrUsageSystemDisplayLCDAutoscale
}; };
const char * const ReportDescParserBase::simuTitles0[] PROGMEM ={ const char * const ReportDescParserBase::simuTitles0[] PROGMEM = {
pstrUsageFlightSimulationDevice, pstrUsageFlightSimulationDevice,
pstrUsageAutomobileSimulationDevice, pstrUsageAutomobileSimulationDevice,
pstrUsageTankSimulationDevice, pstrUsageTankSimulationDevice,
@ -121,7 +121,7 @@ const char * const ReportDescParserBase::simuTitles0[] PROGMEM ={
pstrUsageMagicCarpetSimulationDevice, pstrUsageMagicCarpetSimulationDevice,
pstrUsageBicycleSimulationDevice pstrUsageBicycleSimulationDevice
}; };
const char * const ReportDescParserBase::simuTitles1[] PROGMEM ={ const char * const ReportDescParserBase::simuTitles1[] PROGMEM = {
pstrUsageFlightControlStick, pstrUsageFlightControlStick,
pstrUsageFlightStick, pstrUsageFlightStick,
pstrUsageCyclicControl, pstrUsageCyclicControl,
@ -129,7 +129,7 @@ const char * const ReportDescParserBase::simuTitles1[] PROGMEM ={
pstrUsageFlightYoke, pstrUsageFlightYoke,
pstrUsageTrackControl pstrUsageTrackControl
}; };
const char * const ReportDescParserBase::simuTitles2[] PROGMEM ={ const char * const ReportDescParserBase::simuTitles2[] PROGMEM = {
pstrUsageAileron, pstrUsageAileron,
pstrUsageAileronTrim, pstrUsageAileronTrim,
pstrUsageAntiTorqueControl, pstrUsageAntiTorqueControl,
@ -164,7 +164,7 @@ const char * const ReportDescParserBase::simuTitles2[] PROGMEM ={
pstrUsageFrontBrake, pstrUsageFrontBrake,
pstrUsageRearBrake pstrUsageRearBrake
}; };
const char * const ReportDescParserBase::vrTitles0[] PROGMEM ={ const char * const ReportDescParserBase::vrTitles0[] PROGMEM = {
pstrUsageBelt, pstrUsageBelt,
pstrUsageBodySuit, pstrUsageBodySuit,
pstrUsageFlexor, pstrUsageFlexor,
@ -176,17 +176,17 @@ const char * const ReportDescParserBase::vrTitles0[] PROGMEM ={
pstrUsageVest, pstrUsageVest,
pstrUsageAnimatronicDevice pstrUsageAnimatronicDevice
}; };
const char * const ReportDescParserBase::vrTitles1[] PROGMEM ={ const char * const ReportDescParserBase::vrTitles1[] PROGMEM = {
pstrUsageStereoEnable, pstrUsageStereoEnable,
pstrUsageDisplayEnable pstrUsageDisplayEnable
}; };
const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM ={ const char * const ReportDescParserBase::sportsCtrlTitles0[] PROGMEM = {
pstrUsageBaseballBat, pstrUsageBaseballBat,
pstrUsageGolfClub, pstrUsageGolfClub,
pstrUsageRowingMachine, pstrUsageRowingMachine,
pstrUsageTreadmill pstrUsageTreadmill
}; };
const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM ={ const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM = {
pstrUsageOar, pstrUsageOar,
pstrUsageSlope, pstrUsageSlope,
pstrUsageRate, pstrUsageRate,
@ -198,7 +198,7 @@ const char * const ReportDescParserBase::sportsCtrlTitles1[] PROGMEM ={
pstrUsageStickType, pstrUsageStickType,
pstrUsageStickHeight pstrUsageStickHeight
}; };
const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM ={ const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM = {
pstrUsagePutter, pstrUsagePutter,
pstrUsage1Iron, pstrUsage1Iron,
pstrUsage2Iron, pstrUsage2Iron,
@ -220,12 +220,12 @@ const char * const ReportDescParserBase::sportsCtrlTitles2[] PROGMEM ={
pstrUsage7Wood, pstrUsage7Wood,
pstrUsage9Wood pstrUsage9Wood
}; };
const char * const ReportDescParserBase::gameTitles0[] PROGMEM ={ const char * const ReportDescParserBase::gameTitles0[] PROGMEM = {
pstrUsage3DGameController, pstrUsage3DGameController,
pstrUsagePinballDevice, pstrUsagePinballDevice,
pstrUsageGunDevice pstrUsageGunDevice
}; };
const char * const ReportDescParserBase::gameTitles1[] PROGMEM ={ const char * const ReportDescParserBase::gameTitles1[] PROGMEM = {
pstrUsagePointOfView, pstrUsagePointOfView,
pstrUsageTurnRightLeft, pstrUsageTurnRightLeft,
pstrUsagePitchForwardBackward, pstrUsagePitchForwardBackward,
@ -252,7 +252,7 @@ const char * const ReportDescParserBase::gameTitles1[] PROGMEM ={
pstrUsageGamepadFireJump, pstrUsageGamepadFireJump,
pstrUsageGamepadTrigger pstrUsageGamepadTrigger
}; };
const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM ={ const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM = {
pstrUsageBatteryStrength, pstrUsageBatteryStrength,
pstrUsageWirelessChannel, pstrUsageWirelessChannel,
pstrUsageWirelessID, pstrUsageWirelessID,
@ -261,7 +261,7 @@ const char * const ReportDescParserBase::genDevCtrlTitles[] PROGMEM ={
pstrUsageSecurityCodeCharErased, pstrUsageSecurityCodeCharErased,
pstrUsageSecurityCodeCleared pstrUsageSecurityCodeCleared
}; };
const char * const ReportDescParserBase::ledTitles[] PROGMEM ={ const char * const ReportDescParserBase::ledTitles[] PROGMEM = {
pstrUsageNumLock, pstrUsageNumLock,
pstrUsageCapsLock, pstrUsageCapsLock,
pstrUsageScrollLock, pstrUsageScrollLock,
@ -340,7 +340,7 @@ const char * const ReportDescParserBase::ledTitles[] PROGMEM ={
pstrUsageSystemSuspend, pstrUsageSystemSuspend,
pstrUsageExternalPowerConnected pstrUsageExternalPowerConnected
}; };
const char * const ReportDescParserBase::telTitles0 [] PROGMEM ={ const char * const ReportDescParserBase::telTitles0 [] PROGMEM = {
pstrUsagePhone, pstrUsagePhone,
pstrUsageAnsweringMachine, pstrUsageAnsweringMachine,
pstrUsageMessageControls, pstrUsageMessageControls,
@ -349,7 +349,7 @@ const char * const ReportDescParserBase::telTitles0 [] PROGMEM ={
pstrUsageTelephonyKeyPad, pstrUsageTelephonyKeyPad,
pstrUsageProgrammableButton pstrUsageProgrammableButton
}; };
const char * const ReportDescParserBase::telTitles1 [] PROGMEM ={ const char * const ReportDescParserBase::telTitles1 [] PROGMEM = {
pstrUsageHookSwitch, pstrUsageHookSwitch,
pstrUsageFlash, pstrUsageFlash,
pstrUsageFeature, pstrUsageFeature,
@ -369,20 +369,20 @@ const char * const ReportDescParserBase::telTitles1 [] PROGMEM ={
pstrUsageCallerID, pstrUsageCallerID,
pstrUsageSend pstrUsageSend
}; };
const char * const ReportDescParserBase::telTitles2 [] PROGMEM ={ const char * const ReportDescParserBase::telTitles2 [] PROGMEM = {
pstrUsageSpeedDial, pstrUsageSpeedDial,
pstrUsageStoreNumber, pstrUsageStoreNumber,
pstrUsageRecallNumber, pstrUsageRecallNumber,
pstrUsagePhoneDirectory pstrUsagePhoneDirectory
}; };
const char * const ReportDescParserBase::telTitles3 [] PROGMEM ={ const char * const ReportDescParserBase::telTitles3 [] PROGMEM = {
pstrUsageVoiceMail, pstrUsageVoiceMail,
pstrUsageScreenCalls, pstrUsageScreenCalls,
pstrUsageDoNotDisturb, pstrUsageDoNotDisturb,
pstrUsageMessage, pstrUsageMessage,
pstrUsageAnswerOnOff pstrUsageAnswerOnOff
}; };
const char * const ReportDescParserBase::telTitles4 [] PROGMEM ={ const char * const ReportDescParserBase::telTitles4 [] PROGMEM = {
pstrUsageInsideDialTone, pstrUsageInsideDialTone,
pstrUsageOutsideDialTone, pstrUsageOutsideDialTone,
pstrUsageInsideRingTone, pstrUsageInsideRingTone,
@ -399,7 +399,7 @@ const char * const ReportDescParserBase::telTitles4 [] PROGMEM ={
pstrUsageOutsideRingback, pstrUsageOutsideRingback,
pstrUsageRinger pstrUsageRinger
}; };
const char * const ReportDescParserBase::telTitles5 [] PROGMEM ={ const char * const ReportDescParserBase::telTitles5 [] PROGMEM = {
pstrUsagePhoneKey0, pstrUsagePhoneKey0,
pstrUsagePhoneKey1, pstrUsagePhoneKey1,
pstrUsagePhoneKey2, pstrUsagePhoneKey2,
@ -417,7 +417,7 @@ const char * const ReportDescParserBase::telTitles5 [] PROGMEM ={
pstrUsagePhoneKeyC, pstrUsagePhoneKeyC,
pstrUsagePhoneKeyD pstrUsagePhoneKeyD
}; };
const char * const ReportDescParserBase::consTitles0[] PROGMEM ={ const char * const ReportDescParserBase::consTitles0[] PROGMEM = {
pstrUsageConsumerControl, pstrUsageConsumerControl,
pstrUsageNumericKeyPad, pstrUsageNumericKeyPad,
pstrUsageProgrammableButton, pstrUsageProgrammableButton,
@ -425,12 +425,12 @@ const char * const ReportDescParserBase::consTitles0[] PROGMEM ={
pstrUsageHeadphone, pstrUsageHeadphone,
pstrUsageGraphicEqualizer pstrUsageGraphicEqualizer
}; };
const char * const ReportDescParserBase::consTitles1[] PROGMEM ={ const char * const ReportDescParserBase::consTitles1[] PROGMEM = {
pstrUsagePlus10, pstrUsagePlus10,
pstrUsagePlus100, pstrUsagePlus100,
pstrUsageAMPM pstrUsageAMPM
}; };
const char * const ReportDescParserBase::consTitles2[] PROGMEM ={ const char * const ReportDescParserBase::consTitles2[] PROGMEM = {
pstrUsagePower, pstrUsagePower,
pstrUsageReset, pstrUsageReset,
pstrUsageSleep, pstrUsageSleep,
@ -440,7 +440,7 @@ const char * const ReportDescParserBase::consTitles2[] PROGMEM ={
pstrUsageFunctionButtons pstrUsageFunctionButtons
}; };
const char * const ReportDescParserBase::consTitles3[] PROGMEM ={ const char * const ReportDescParserBase::consTitles3[] PROGMEM = {
pstrUsageMenu, pstrUsageMenu,
pstrUsageMenuPick, pstrUsageMenuPick,
pstrUsageMenuUp, pstrUsageMenuUp,
@ -451,7 +451,7 @@ const char * const ReportDescParserBase::consTitles3[] PROGMEM ={
pstrUsageMenuValueIncrease, pstrUsageMenuValueIncrease,
pstrUsageMenuValueDecrease pstrUsageMenuValueDecrease
}; };
const char * const ReportDescParserBase::consTitles4[] PROGMEM ={ const char * const ReportDescParserBase::consTitles4[] PROGMEM = {
pstrUsageDataOnScreen, pstrUsageDataOnScreen,
pstrUsageClosedCaption, pstrUsageClosedCaption,
pstrUsageClosedCaptionSelect, pstrUsageClosedCaptionSelect,
@ -460,7 +460,7 @@ const char * const ReportDescParserBase::consTitles4[] PROGMEM ={
pstrUsageSnapshot, pstrUsageSnapshot,
pstrUsageStill pstrUsageStill
}; };
const char * const ReportDescParserBase::consTitles5[] PROGMEM ={ const char * const ReportDescParserBase::consTitles5[] PROGMEM = {
pstrUsageSelection, pstrUsageSelection,
pstrUsageAssignSelection, pstrUsageAssignSelection,
pstrUsageModeStep, pstrUsageModeStep,
@ -499,7 +499,7 @@ const char * const ReportDescParserBase::consTitles5[] PROGMEM ={
pstrUsageWeekly, pstrUsageWeekly,
pstrUsageMonthly pstrUsageMonthly
}; };
const char * const ReportDescParserBase::consTitles6[] PROGMEM ={ const char * const ReportDescParserBase::consTitles6[] PROGMEM = {
pstrUsagePlay, pstrUsagePlay,
pstrUsagePause, pstrUsagePause,
pstrUsageRecord, pstrUsageRecord,
@ -532,7 +532,7 @@ const char * const ReportDescParserBase::consTitles6[] PROGMEM ={
pstrUsagePlayPause, pstrUsagePlayPause,
pstrUsagePlaySkip pstrUsagePlaySkip
}; };
const char * const ReportDescParserBase::consTitles7[] PROGMEM ={ const char * const ReportDescParserBase::consTitles7[] PROGMEM = {
pstrUsageVolume, pstrUsageVolume,
pstrUsageBalance, pstrUsageBalance,
pstrUsageMute, pstrUsageMute,
@ -545,7 +545,7 @@ const char * const ReportDescParserBase::consTitles7[] PROGMEM ={
pstrUsageVolumeIncrement, pstrUsageVolumeIncrement,
pstrUsageVolumeDecrement pstrUsageVolumeDecrement
}; };
const char * const ReportDescParserBase::consTitles8[] PROGMEM ={ const char * const ReportDescParserBase::consTitles8[] PROGMEM = {
pstrUsageSpeedSelect, pstrUsageSpeedSelect,
pstrUsagePlaybackSpeed, pstrUsagePlaybackSpeed,
pstrUsageStandardPlay, pstrUsageStandardPlay,
@ -553,7 +553,7 @@ const char * const ReportDescParserBase::consTitles8[] PROGMEM ={
pstrUsageExtendedPlay, pstrUsageExtendedPlay,
pstrUsageSlow pstrUsageSlow
}; };
const char * const ReportDescParserBase::consTitles9[] PROGMEM ={ const char * const ReportDescParserBase::consTitles9[] PROGMEM = {
pstrUsageFanEnable, pstrUsageFanEnable,
pstrUsageFanSpeed, pstrUsageFanSpeed,
pstrUsageLightEnable, pstrUsageLightEnable,
@ -569,7 +569,7 @@ const char * const ReportDescParserBase::consTitles9[] PROGMEM ={
pstrUsageHoldupAlarm, pstrUsageHoldupAlarm,
pstrUsageMedicalAlarm pstrUsageMedicalAlarm
}; };
const char * const ReportDescParserBase::consTitlesA[] PROGMEM ={ const char * const ReportDescParserBase::consTitlesA[] PROGMEM = {
pstrUsageBalanceRight, pstrUsageBalanceRight,
pstrUsageBalanceLeft, pstrUsageBalanceLeft,
pstrUsageBassIncrement, pstrUsageBassIncrement,
@ -577,7 +577,7 @@ const char * const ReportDescParserBase::consTitlesA[] PROGMEM ={
pstrUsageTrebleIncrement, pstrUsageTrebleIncrement,
pstrUsageTrebleDecrement pstrUsageTrebleDecrement
}; };
const char * const ReportDescParserBase::consTitlesB[] PROGMEM ={ const char * const ReportDescParserBase::consTitlesB[] PROGMEM = {
pstrUsageSpeakerSystem, pstrUsageSpeakerSystem,
pstrUsageChannelLeft, pstrUsageChannelLeft,
pstrUsageChannelRight, pstrUsageChannelRight,
@ -590,14 +590,14 @@ const char * const ReportDescParserBase::consTitlesB[] PROGMEM ={
pstrUsageChannelTop, pstrUsageChannelTop,
pstrUsageChannelUnknown pstrUsageChannelUnknown
}; };
const char * const ReportDescParserBase::consTitlesC[] PROGMEM ={ const char * const ReportDescParserBase::consTitlesC[] PROGMEM = {
pstrUsageSubChannel, pstrUsageSubChannel,
pstrUsageSubChannelIncrement, pstrUsageSubChannelIncrement,
pstrUsageSubChannelDecrement, pstrUsageSubChannelDecrement,
pstrUsageAlternateAudioIncrement, pstrUsageAlternateAudioIncrement,
pstrUsageAlternateAudioDecrement pstrUsageAlternateAudioDecrement
}; };
const char * const ReportDescParserBase::consTitlesD[] PROGMEM ={ const char * const ReportDescParserBase::consTitlesD[] PROGMEM = {
pstrUsageApplicationLaunchButtons, pstrUsageApplicationLaunchButtons,
pstrUsageALLaunchButtonConfigTool, pstrUsageALLaunchButtonConfigTool,
pstrUsageALProgrammableButton, pstrUsageALProgrammableButton,
@ -671,7 +671,7 @@ const char * const ReportDescParserBase::consTitlesD[] PROGMEM ={
pstrUsageALResearchSearchBrowser, pstrUsageALResearchSearchBrowser,
pstrUsageALAudioPlayer pstrUsageALAudioPlayer
}; };
const char * const ReportDescParserBase::consTitlesE[] PROGMEM ={ const char * const ReportDescParserBase::consTitlesE[] PROGMEM = {
pstrUsageGenericGUIAppControls, pstrUsageGenericGUIAppControls,
pstrUsageACNew, pstrUsageACNew,
pstrUsageACOpen, pstrUsageACOpen,
@ -814,7 +814,7 @@ const char * const ReportDescParserBase::consTitlesE[] PROGMEM ={
pstrUsageACDistributeHorizontaly, pstrUsageACDistributeHorizontaly,
pstrUsageACDistributeVerticaly pstrUsageACDistributeVerticaly
}; };
const char * const ReportDescParserBase::digitTitles0[] PROGMEM ={ const char * const ReportDescParserBase::digitTitles0[] PROGMEM = {
pstrUsageDigitizer, pstrUsageDigitizer,
pstrUsagePen, pstrUsagePen,
pstrUsageLightPen, pstrUsageLightPen,
@ -829,13 +829,13 @@ const char * const ReportDescParserBase::digitTitles0[] PROGMEM ={
pstrUsageMultiplePointDigitizer, pstrUsageMultiplePointDigitizer,
pstrUsageFreeSpaceWand pstrUsageFreeSpaceWand
}; };
const char * const ReportDescParserBase::digitTitles1[] PROGMEM ={ const char * const ReportDescParserBase::digitTitles1[] PROGMEM = {
pstrUsageStylus, pstrUsageStylus,
pstrUsagePuck, pstrUsagePuck,
pstrUsageFinger pstrUsageFinger
}; };
const char * const ReportDescParserBase::digitTitles2[] PROGMEM ={ const char * const ReportDescParserBase::digitTitles2[] PROGMEM = {
pstrUsageTipPressure, pstrUsageTipPressure,
pstrUsageBarrelPressure, pstrUsageBarrelPressure,
pstrUsageInRange, pstrUsageInRange,
@ -860,11 +860,11 @@ const char * const ReportDescParserBase::digitTitles2[] PROGMEM ={
pstrUsageEraser, pstrUsageEraser,
pstrUsageTabletPick pstrUsageTabletPick
}; };
const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM ={ const char * const ReportDescParserBase::aplphanumTitles0[] PROGMEM = {
pstrUsageAlphanumericDisplay, pstrUsageAlphanumericDisplay,
pstrUsageBitmappedDisplay pstrUsageBitmappedDisplay
}; };
const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM ={ const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM = {
pstrUsageDisplayAttributesReport, pstrUsageDisplayAttributesReport,
pstrUsageASCIICharacterSet, pstrUsageASCIICharacterSet,
pstrUsageDataReadBack, pstrUsageDataReadBack,
@ -912,7 +912,7 @@ const char * const ReportDescParserBase::aplphanumTitles1[] PROGMEM ={
pstrUsageCharAttributeUnderline, pstrUsageCharAttributeUnderline,
pstrUsageCharAttributeBlink pstrUsageCharAttributeBlink
}; };
const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM ={ const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM = {
pstrUsageBitmapSizeX, pstrUsageBitmapSizeX,
pstrUsageBitmapSizeY, pstrUsageBitmapSizeY,
pstrUsagePageReserved, pstrUsagePageReserved,
@ -935,7 +935,7 @@ const char * const ReportDescParserBase::aplphanumTitles2[] PROGMEM ={
pstrUsageSoftButtonOffset2, pstrUsageSoftButtonOffset2,
pstrUsageSoftButtonReport pstrUsageSoftButtonReport
}; };
const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM ={ const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM = {
pstrUsageVCRAcquisition, pstrUsageVCRAcquisition,
pstrUsageFreezeThaw, pstrUsageFreezeThaw,
pstrUsageClipStore, pstrUsageClipStore,
@ -945,18 +945,18 @@ const char * const ReportDescParserBase::medInstrTitles0[] PROGMEM ={
pstrUsagePrint, pstrUsagePrint,
pstrUsageMicrophoneEnable pstrUsageMicrophoneEnable
}; };
const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM ={ const char * const ReportDescParserBase::medInstrTitles1[] PROGMEM = {
pstrUsageCine, pstrUsageCine,
pstrUsageTransmitPower, pstrUsageTransmitPower,
pstrUsageVolume, pstrUsageVolume,
pstrUsageFocus, pstrUsageFocus,
pstrUsageDepth pstrUsageDepth
}; };
const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM ={ const char * const ReportDescParserBase::medInstrTitles2[] PROGMEM = {
pstrUsageSoftStepPrimary, pstrUsageSoftStepPrimary,
pstrUsageSoftStepSecondary pstrUsageSoftStepSecondary
}; };
const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM ={ const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM = {
pstrUsageZoomSelect, pstrUsageZoomSelect,
pstrUsageZoomAdjust, pstrUsageZoomAdjust,
pstrUsageSpectralDopplerModeSelect, pstrUsageSpectralDopplerModeSelect,
@ -968,14 +968,14 @@ const char * const ReportDescParserBase::medInstrTitles3[] PROGMEM ={
pstrUsage2DModeSelect, pstrUsage2DModeSelect,
pstrUsage2DModeAdjust pstrUsage2DModeAdjust
}; };
const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM ={ const char * const ReportDescParserBase::medInstrTitles4[] PROGMEM = {
pstrUsageSoftControlSelect, pstrUsageSoftControlSelect,
pstrUsageSoftControlAdjust pstrUsageSoftControlAdjust
}; };
void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) { void ReportDescParserBase::Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
uint16_t cntdn = (uint16_t) len; uint16_t cntdn = (uint16_t)len;
uint8_t *p = (uint8_t*) pbuf; uint8_t *p = (uint8_t*)pbuf;
totalSize = 0; totalSize = 0;
@ -1108,13 +1108,13 @@ uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
itemParseState = 3; itemParseState = 3;
case 3: case 3:
{ {
uint8_t data = *((uint8_t*) varBuffer); uint8_t data = *((uint8_t*)varBuffer);
switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { switch (itemPrefix & (TYPE_MASK | TAG_MASK)) {
case (TYPE_LOCAL | TAG_LOCAL_USAGE): case (TYPE_LOCAL | TAG_LOCAL_USAGE):
if (pfUsage) { if (pfUsage) {
if (theBuffer.valueSize > 1) if (theBuffer.valueSize > 1)
pfUsage(*((uint16_t*) varBuffer)); pfUsage(*((uint16_t*)varBuffer));
else else
pfUsage(data); pfUsage(data);
} }
@ -1179,7 +1179,7 @@ uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
case (TYPE_MAIN | TAG_MAIN_INPUT): case (TYPE_MAIN | TAG_MAIN_INPUT):
case (TYPE_MAIN | TAG_MAIN_OUTPUT): case (TYPE_MAIN | TAG_MAIN_OUTPUT):
case (TYPE_MAIN | TAG_MAIN_FEATURE): case (TYPE_MAIN | TAG_MAIN_FEATURE):
totalSize += (uint16_t) rptSize * (uint16_t) rptCount; totalSize += (uint16_t)rptSize * (uint16_t)rptCount;
rptSize = 0; rptSize = 0;
rptCount = 0; rptCount = 0;
Notify(PSTR("("), 0x80); Notify(PSTR("("), 0x80);
@ -1193,7 +1193,7 @@ uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
return enErrorSuccess; return enErrorSuccess;
} }
ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ ={ ReportDescParserBase::UsagePageFunc ReportDescParserBase::usagePageFunctions[] /*PROGMEM*/ = {
&ReportDescParserBase::PrintGenericDesktopPageUsage, &ReportDescParserBase::PrintGenericDesktopPageUsage,
&ReportDescParserBase::PrintSimulationControlsPageUsage, &ReportDescParserBase::PrintSimulationControlsPageUsage,
&ReportDescParserBase::PrintVRControlsPageUsage, &ReportDescParserBase::PrintVRControlsPageUsage,
@ -1240,13 +1240,13 @@ void ReportDescParserBase::PrintUsagePage(uint16_t page) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (page > 0x00 && page < 0x11) if (page > 0x00 && page < 0x11)
Notify((char*) pgm_read_word(&usagePageTitles0[page - 1]), 0x80); Notify((char*)pgm_read_word(&usagePageTitles0[page - 1]), 0x80);
else if (page > 0x7f && page < 0x84) else if (page > 0x7f && page < 0x84)
Notify(pstrUsagePageMonitor, 0x80); Notify(pstrUsagePageMonitor, 0x80);
else if (page > 0x83 && page < 0x8c) else if (page > 0x83 && page < 0x8c)
Notify(pstrUsagePagePower, 0x80); Notify(pstrUsagePagePower, 0x80);
else if (page > 0x8b && page < 0x92) else if (page > 0x8b && page < 0x92)
Notify((char*) pgm_read_word(&usagePageTitles1[page - 0x8c]), 0x80); Notify((char*)pgm_read_word(&usagePageTitles1[page - 0x8c]), 0x80);
else if (page > 0xfeff && page <= 0xffff) else if (page > 0xfeff && page <= 0xffff)
Notify(pstrUsagePageVendorDefined, 0x80); Notify(pstrUsagePageVendorDefined, 0x80);
else else
@ -1283,15 +1283,15 @@ void ReportDescParserBase::PrintGenericDesktopPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x0a) if (usage > 0x00 && usage < 0x0a)
Notify((char*) pgm_read_word(&genDesktopTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&genDesktopTitles0[usage - 1]), 0x80);
else if (usage > 0x2f && usage < 0x49) else if (usage > 0x2f && usage < 0x49)
Notify((char*) pgm_read_word(&genDesktopTitles1[usage - 0x30]), 0x80); Notify((char*)pgm_read_word(&genDesktopTitles1[usage - 0x30]), 0x80);
else if (usage > 0x7f && usage < 0x94) else if (usage > 0x7f && usage < 0x94)
Notify((char*) pgm_read_word(&genDesktopTitles2[usage - 0x80]), 0x80); Notify((char*)pgm_read_word(&genDesktopTitles2[usage - 0x80]), 0x80);
else if (usage > 0x9f && usage < 0xa9) else if (usage > 0x9f && usage < 0xa9)
Notify((char*) pgm_read_word(&genDesktopTitles3[usage - 0xa0]), 0x80); Notify((char*)pgm_read_word(&genDesktopTitles3[usage - 0xa0]), 0x80);
else if (usage > 0xaf && usage < 0xb8) else if (usage > 0xaf && usage < 0xb8)
Notify((char*) pgm_read_word(&genDesktopTitles4[usage - 0xb0]), 0x80); Notify((char*)pgm_read_word(&genDesktopTitles4[usage - 0xb0]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1300,11 +1300,11 @@ void ReportDescParserBase::PrintSimulationControlsPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x0d) if (usage > 0x00 && usage < 0x0d)
Notify((char*) pgm_read_word(&simuTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&simuTitles0[usage - 1]), 0x80);
else if (usage > 0x1f && usage < 0x26) else if (usage > 0x1f && usage < 0x26)
Notify((char*) pgm_read_word(&simuTitles1[usage - 0x20]), 0x80); Notify((char*)pgm_read_word(&simuTitles1[usage - 0x20]), 0x80);
else if (usage > 0xaf && usage < 0xd1) else if (usage > 0xaf && usage < 0xd1)
Notify((char*) pgm_read_word(&simuTitles2[usage - 0xb0]), 0x80); Notify((char*)pgm_read_word(&simuTitles2[usage - 0xb0]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1313,9 +1313,9 @@ void ReportDescParserBase::PrintVRControlsPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x0b) if (usage > 0x00 && usage < 0x0b)
Notify((char*) pgm_read_word(&vrTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&vrTitles0[usage - 1]), 0x80);
else if (usage > 0x1f && usage < 0x22) else if (usage > 0x1f && usage < 0x22)
Notify((char*) pgm_read_word(&vrTitles1[usage - 0x20]), 0x80); Notify((char*)pgm_read_word(&vrTitles1[usage - 0x20]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1324,11 +1324,11 @@ void ReportDescParserBase::PrintSportsControlsPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x05) if (usage > 0x00 && usage < 0x05)
Notify((char*) pgm_read_word(&sportsCtrlTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&sportsCtrlTitles0[usage - 1]), 0x80);
else if (usage > 0x2f && usage < 0x3a) else if (usage > 0x2f && usage < 0x3a)
Notify((char*) pgm_read_word(&sportsCtrlTitles1[usage - 0x30]), 0x80); Notify((char*)pgm_read_word(&sportsCtrlTitles1[usage - 0x30]), 0x80);
else if (usage > 0x4f && usage < 0x64) else if (usage > 0x4f && usage < 0x64)
Notify((char*) pgm_read_word(&sportsCtrlTitles2[usage - 0x50]), 0x80); Notify((char*)pgm_read_word(&sportsCtrlTitles2[usage - 0x50]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1337,9 +1337,9 @@ void ReportDescParserBase::PrintGameControlsPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x04) if (usage > 0x00 && usage < 0x04)
Notify((char*) pgm_read_word(&gameTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&gameTitles0[usage - 1]), 0x80);
else if (usage > 0x1f && usage < 0x3a) else if (usage > 0x1f && usage < 0x3a)
Notify((char*) pgm_read_word(&gameTitles1[usage - 0x20]), 0x80); Notify((char*)pgm_read_word(&gameTitles1[usage - 0x20]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1348,7 +1348,7 @@ void ReportDescParserBase::PrintGenericDeviceControlsPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x1f && usage < 0x27) if (usage > 0x1f && usage < 0x27)
Notify((char*) pgm_read_word(&genDevCtrlTitles[usage - 0x20]), 0x80); Notify((char*)pgm_read_word(&genDevCtrlTitles[usage - 0x20]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1357,7 +1357,7 @@ void ReportDescParserBase::PrintLEDPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x4e) if (usage > 0x00 && usage < 0x4e)
Notify((char*) pgm_read_word(&ledTitles[usage - 1]), 0x80); Notify((char*)pgm_read_word(&ledTitles[usage - 1]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1366,17 +1366,17 @@ void ReportDescParserBase::PrintTelephonyPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x08) if (usage > 0x00 && usage < 0x08)
Notify((char*) pgm_read_word(&telTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&telTitles0[usage - 1]), 0x80);
else if (usage > 0x1f && usage < 0x32) else if (usage > 0x1f && usage < 0x32)
Notify((char*) pgm_read_word(&telTitles1[usage - 0x1f]), 0x80); Notify((char*)pgm_read_word(&telTitles1[usage - 0x1f]), 0x80);
else if (usage > 0x4f && usage < 0x54) else if (usage > 0x4f && usage < 0x54)
Notify((char*) pgm_read_word(&telTitles2[usage - 0x4f]), 0x80); Notify((char*)pgm_read_word(&telTitles2[usage - 0x4f]), 0x80);
else if (usage > 0x6f && usage < 0x75) else if (usage > 0x6f && usage < 0x75)
Notify((char*) pgm_read_word(&telTitles3[usage - 0x6f]), 0x80); Notify((char*)pgm_read_word(&telTitles3[usage - 0x6f]), 0x80);
else if (usage > 0x8f && usage < 0x9f) else if (usage > 0x8f && usage < 0x9f)
Notify((char*) pgm_read_word(&telTitles4[usage - 0x8f]), 0x80); Notify((char*)pgm_read_word(&telTitles4[usage - 0x8f]), 0x80);
else if (usage > 0xaf && usage < 0xc0) else if (usage > 0xaf && usage < 0xc0)
Notify((char*) pgm_read_word(&telTitles5[usage - 0xaf]), 0x80); Notify((char*)pgm_read_word(&telTitles5[usage - 0xaf]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1385,35 +1385,35 @@ void ReportDescParserBase::PrintConsumerPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x07) if (usage > 0x00 && usage < 0x07)
Notify((char*) pgm_read_word(&consTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&consTitles0[usage - 1]), 0x80);
else if (usage > 0x1f && usage < 0x23) else if (usage > 0x1f && usage < 0x23)
Notify((char*) pgm_read_word(&consTitles1[usage - 0x1f]), 0x80); Notify((char*)pgm_read_word(&consTitles1[usage - 0x1f]), 0x80);
else if (usage > 0x2f && usage < 0x37) else if (usage > 0x2f && usage < 0x37)
Notify((char*) pgm_read_word(&consTitles2[usage - 0x2f]), 0x80); Notify((char*)pgm_read_word(&consTitles2[usage - 0x2f]), 0x80);
else if (usage > 0x3f && usage < 0x49) else if (usage > 0x3f && usage < 0x49)
Notify((char*) pgm_read_word(&consTitles3[usage - 0x3f]), 0x80); Notify((char*)pgm_read_word(&consTitles3[usage - 0x3f]), 0x80);
else if (usage > 0x5f && usage < 0x67) else if (usage > 0x5f && usage < 0x67)
Notify((char*) pgm_read_word(&consTitles4[usage - 0x5f]), 0x80); Notify((char*)pgm_read_word(&consTitles4[usage - 0x5f]), 0x80);
else if (usage > 0x7f && usage < 0xa5) else if (usage > 0x7f && usage < 0xa5)
Notify((char*) pgm_read_word(&consTitles5[usage - 0x7f]), 0x80); Notify((char*)pgm_read_word(&consTitles5[usage - 0x7f]), 0x80);
else if (usage > 0xaf && usage < 0xcf) else if (usage > 0xaf && usage < 0xcf)
Notify((char*) pgm_read_word(&consTitles6[usage - 0xaf]), 0x80); Notify((char*)pgm_read_word(&consTitles6[usage - 0xaf]), 0x80);
else if (usage > 0xdf && usage < 0xeb) else if (usage > 0xdf && usage < 0xeb)
Notify((char*) pgm_read_word(&consTitles7[usage - 0xdf]), 0x80); Notify((char*)pgm_read_word(&consTitles7[usage - 0xdf]), 0x80);
else if (usage > 0xef && usage < 0xf6) else if (usage > 0xef && usage < 0xf6)
Notify((char*) pgm_read_word(&consTitles8[usage - 0xef]), 0x80); Notify((char*)pgm_read_word(&consTitles8[usage - 0xef]), 0x80);
else if (usage > 0xff && usage < 0x10e) else if (usage > 0xff && usage < 0x10e)
Notify((char*) pgm_read_word(&consTitles9[usage - 0xff]), 0x80); Notify((char*)pgm_read_word(&consTitles9[usage - 0xff]), 0x80);
else if (usage > 0x14f && usage < 0x156) else if (usage > 0x14f && usage < 0x156)
Notify((char*) pgm_read_word(&consTitlesA[usage - 0x14f]), 0x80); Notify((char*)pgm_read_word(&consTitlesA[usage - 0x14f]), 0x80);
else if (usage > 0x15f && usage < 0x16b) else if (usage > 0x15f && usage < 0x16b)
Notify((char*) pgm_read_word(&consTitlesB[usage - 0x15f]), 0x80); Notify((char*)pgm_read_word(&consTitlesB[usage - 0x15f]), 0x80);
else if (usage > 0x16f && usage < 0x175) else if (usage > 0x16f && usage < 0x175)
Notify((char*) pgm_read_word(&consTitlesC[usage - 0x16f]), 0x80); Notify((char*)pgm_read_word(&consTitlesC[usage - 0x16f]), 0x80);
else if (usage > 0x17f && usage < 0x1c8) else if (usage > 0x17f && usage < 0x1c8)
Notify((char*) pgm_read_word(&consTitlesD[usage - 0x17f]), 0x80); Notify((char*)pgm_read_word(&consTitlesD[usage - 0x17f]), 0x80);
else if (usage > 0x1ff && usage < 0x29d) else if (usage > 0x1ff && usage < 0x29d)
Notify((char*) pgm_read_word(&consTitlesE[usage - 0x1ff]), 0x80); Notify((char*)pgm_read_word(&consTitlesE[usage - 0x1ff]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1422,11 +1422,11 @@ void ReportDescParserBase::PrintDigitizerPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x0e) if (usage > 0x00 && usage < 0x0e)
Notify((char*) pgm_read_word(&digitTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&digitTitles0[usage - 1]), 0x80);
else if (usage > 0x1f && usage < 0x23) else if (usage > 0x1f && usage < 0x23)
Notify((char*) pgm_read_word(&digitTitles1[usage - 0x1f]), 0x80); Notify((char*)pgm_read_word(&digitTitles1[usage - 0x1f]), 0x80);
else if (usage > 0x2f && usage < 0x47) else if (usage > 0x2f && usage < 0x47)
Notify((char*) pgm_read_word(&digitTitles2[usage - 0x2f]), 0x80); Notify((char*)pgm_read_word(&digitTitles2[usage - 0x2f]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1435,11 +1435,11 @@ void ReportDescParserBase::PrintAlphanumDisplayPageUsage(uint16_t usage) {
Notify(pstrSpace, 0x80); Notify(pstrSpace, 0x80);
if (usage > 0x00 && usage < 0x03) if (usage > 0x00 && usage < 0x03)
Notify((char*) pgm_read_word(&aplphanumTitles0[usage - 1]), 0x80); Notify((char*)pgm_read_word(&aplphanumTitles0[usage - 1]), 0x80);
else if (usage > 0x1f && usage < 0x4e) else if (usage > 0x1f && usage < 0x4e)
Notify((char*) pgm_read_word(&aplphanumTitles1[usage - 0x1f]), 0x80); Notify((char*)pgm_read_word(&aplphanumTitles1[usage - 0x1f]), 0x80);
else if (usage > 0x7f && usage < 0x96) else if (usage > 0x7f && usage < 0x96)
Notify((char*) pgm_read_word(&digitTitles2[usage - 0x80]), 0x80); Notify((char*)pgm_read_word(&digitTitles2[usage - 0x80]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1450,17 +1450,17 @@ void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) {
if (usage == 1) if (usage == 1)
Notify(pstrUsageMedicalUltrasound, 0x80); Notify(pstrUsageMedicalUltrasound, 0x80);
else if (usage > 0x1f && usage < 0x28) else if (usage > 0x1f && usage < 0x28)
Notify((char*) pgm_read_word(&medInstrTitles0[usage - 0x1f]), 0x80); Notify((char*)pgm_read_word(&medInstrTitles0[usage - 0x1f]), 0x80);
else if (usage > 0x3f && usage < 0x45) else if (usage > 0x3f && usage < 0x45)
Notify((char*) pgm_read_word(&medInstrTitles1[usage - 0x40]), 0x80); Notify((char*)pgm_read_word(&medInstrTitles1[usage - 0x40]), 0x80);
else if (usage > 0x5f && usage < 0x62) else if (usage > 0x5f && usage < 0x62)
Notify((char*) pgm_read_word(&medInstrTitles2[usage - 0x60]), 0x80); Notify((char*)pgm_read_word(&medInstrTitles2[usage - 0x60]), 0x80);
else if (usage == 0x70) else if (usage == 0x70)
Notify(pstrUsageDepthGainCompensation, 0x80); Notify(pstrUsageDepthGainCompensation, 0x80);
else if (usage > 0x7f && usage < 0x8a) else if (usage > 0x7f && usage < 0x8a)
Notify((char*) pgm_read_word(&medInstrTitles3[usage - 0x80]), 0x80); Notify((char*)pgm_read_word(&medInstrTitles3[usage - 0x80]), 0x80);
else if (usage > 0x9f && usage < 0xa2) else if (usage > 0x9f && usage < 0xa2)
Notify((char*) pgm_read_word(&medInstrTitles4[usage - 0xa0]), 0x80); Notify((char*)pgm_read_word(&medInstrTitles4[usage - 0xa0]), 0x80);
else else
Notify(pstrUsagePageUndefined, 0x80); Notify(pstrUsagePageUndefined, 0x80);
} }
@ -1497,13 +1497,13 @@ uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
itemParseState = 3; itemParseState = 3;
case 3: case 3:
{ {
uint8_t data = *((uint8_t*) varBuffer); uint8_t data = *((uint8_t*)varBuffer);
switch (itemPrefix & (TYPE_MASK | TAG_MASK)) { switch (itemPrefix & (TYPE_MASK | TAG_MASK)) {
case (TYPE_LOCAL | TAG_LOCAL_USAGE): case (TYPE_LOCAL | TAG_LOCAL_USAGE):
if (pfUsage) { if (pfUsage) {
if (theBuffer.valueSize > 1) if (theBuffer.valueSize > 1)
pfUsage(*((uint16_t*) varBuffer)); pfUsage(*((uint16_t*)varBuffer));
else else
pfUsage(data); pfUsage(data);
} }
@ -1536,7 +1536,7 @@ uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint16_t *pcntdn) {
case (TYPE_MAIN | TAG_MAIN_INPUT): case (TYPE_MAIN | TAG_MAIN_INPUT):
OnInputItem(data); OnInputItem(data);
totalSize += (uint16_t) rptSize * (uint16_t) rptCount; totalSize += (uint16_t)rptSize * (uint16_t)rptCount;
rptSize = 0; rptSize = 0;
rptCount = 0; rptCount = 0;

View file

@ -119,7 +119,7 @@ protected:
MultiValueBuffer theBuffer; MultiValueBuffer theBuffer;
MultiByteValueParser valParser; MultiByteValueParser valParser;
ByteSkipper theSkipper; ByteSkipper theSkipper;
uint8_t varBuffer[sizeof (USB_CONFIGURATION_DESCRIPTOR)]; uint8_t varBuffer[sizeof(USB_CONFIGURATION_DESCRIPTOR)];
uint8_t itemParseState; // Item parser state variable uint8_t itemParseState; // Item parser state variable
uint8_t itemSize; // Item size uint8_t itemSize; // Item size

View file

@ -112,7 +112,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
if (!rcode) if (!rcode)
len = (buf[0] > constBufSize) ? constBufSize : buf[0]; len = (buf[0] > constBufSize) ? constBufSize : buf[0];
@ -134,7 +134,7 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
@ -159,12 +159,12 @@ uint8_t HIDUniversal::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
if (len) if (len)
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
if (rcode) if (rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
@ -287,7 +287,7 @@ void HIDUniversal::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint
if (index) { if (index) {
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[bNumEP].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[bNumEP].maxPktSize = (uint8_t) pep->wMaxPacketSize; epInfo[bNumEP].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[bNumEP].epAttribs = 0; epInfo[bNumEP].epAttribs = 0;
epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT; epInfo[bNumEP].bmNakPower = USB_NAK_NOWAIT;
@ -339,7 +339,7 @@ uint8_t HIDUniversal::Poll() {
for (uint8_t i = 0; i < bNumIface; i++) { for (uint8_t i = 0; i < bNumIface; i++) {
uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex]; uint8_t index = hidInterfaces[i].epIndex[epInterruptInIndex];
uint16_t read = (uint16_t) epInfo[index].maxPktSize; uint16_t read = (uint16_t)epInfo[index].maxPktSize;
ZeroMemory(constBuffLen, buf); ZeroMemory(constBuffLen, buf);
@ -371,7 +371,7 @@ uint8_t HIDUniversal::Poll() {
HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0)); HIDReportParser *prs = GetReportParser(((bHasReportId) ? *buf : 0));
if (prs) if (prs)
prs->Parse(this, bHasReportId, (uint8_t) read, buf); prs->Parse(this, bHasReportId, (uint8_t)read, buf);
} }
} }
return rcode; return rcode;

View file

@ -82,7 +82,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
// Restore p->epinfo // Restore p->epinfo
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
@ -97,7 +97,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = (uint8_t) ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; epInfo[0].maxPktSize = (uint8_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
@ -121,7 +121,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
num_of_conf = ((USB_DEVICE_DESCRIPTOR*) buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
// Assign epInfo to epinfo pointer // Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo); rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
@ -220,7 +220,7 @@ uint8_t BulkOnly::Init(uint8_t parent, uint8_t port, bool lowspeed) {
PrintHex<uint8_t > (capacity.data[i], 0x80); PrintHex<uint8_t > (capacity.data[i], 0x80);
Notify(PSTR("\r\n\r\n"), 0x80); Notify(PSTR("\r\n\r\n"), 0x80);
// Only 512/1024/2048/4096 are valid values! // Only 512/1024/2048/4096 are valid values!
uint32_t c = ((uint32_t) capacity.data[4] << 24) + ((uint32_t) capacity.data[5] << 16) + ((uint32_t) capacity.data[6] << 8) + (uint32_t) capacity.data[7]; uint32_t c = ((uint32_t)capacity.data[4] << 24) + ((uint32_t)capacity.data[5] << 16) + ((uint32_t)capacity.data[6] << 8) + (uint32_t)capacity.data[7];
if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) { if (c != 0x0200LU && c != 0x0400LU && c != 0x0800LU && c != 0x1000LU) {
rcode = 255; rcode = 255;
goto FailInvalidSectorSize; goto FailInvalidSectorSize;
@ -354,7 +354,7 @@ void BulkOnly::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t
// Fill in the endpoint info structure // Fill in the endpoint info structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F); epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t) pep->wMaxPacketSize; epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
epInfo[index].epAttribs = 0; epInfo[index].epAttribs = 0;
bNumEP++; bNumEP++;
@ -611,7 +611,7 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
cbw.dCBWSignature = MASS_CBW_SIGNATURE; cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag; cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
cbw.bmCBWFlags = MASS_CMD_DIR_IN, cbw.bmCBWFlags = MASS_CMD_DIR_IN,
cbw.bmCBWLUN = lun; cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 10; cbw.bmCBWCBLength = 10;
@ -638,7 +638,7 @@ uint8_t BulkOnly::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t block
cbw.dCBWSignature = MASS_CBW_SIGNATURE; cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag; cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
cbw.bmCBWFlags = MASS_CMD_DIR_IN, cbw.bmCBWFlags = MASS_CMD_DIR_IN,
cbw.bmCBWLUN = lun; cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 10; cbw.bmCBWCBLength = 10;
@ -666,7 +666,7 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc
cbw.dCBWSignature = MASS_CBW_SIGNATURE; cbw.dCBWSignature = MASS_CBW_SIGNATURE;
cbw.dCBWTag = ++dCBWTag; cbw.dCBWTag = ++dCBWTag;
cbw.dCBWDataTransferLength = ((uint32_t) bsize * blocks); cbw.dCBWDataTransferLength = ((uint32_t)bsize * blocks);
cbw.bmCBWFlags = MASS_CMD_DIR_OUT, cbw.bmCBWFlags = MASS_CMD_DIR_OUT,
cbw.bmCBWLUN = lun; cbw.bmCBWLUN = lun;
cbw.bmCBWCBLength = 10; cbw.bmCBWCBLength = 10;
@ -681,7 +681,7 @@ uint8_t BulkOnly::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t bloc
cbw.CBWCB[3] = ((addr >> 16) & 0xff); cbw.CBWCB[3] = ((addr >> 16) & 0xff);
cbw.CBWCB[2] = ((addr >> 24) & 0xff); cbw.CBWCB[2] = ((addr >> 24) & 0xff);
return HandleSCSIError(Transaction(&cbw, bsize, (void*) buf, 0)); return HandleSCSIError(Transaction(&cbw, bsize, (void*)buf, 0));
} }
uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *pbuf) { uint8_t BulkOnly::ModeSense(uint8_t lun, uint8_t pc, uint8_t page, uint8_t subpage, uint8_t len, uint8_t *pbuf) {
@ -714,7 +714,7 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
ErrorMessage<uint8_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag); ErrorMessage<uint8_t > (PSTR("CBW.dCBWTag"), pcbw->dCBWTag);
ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*) pcbw), epDataOutIndex); ret = HandleUsbError(pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, sizeof (CommandBlockWrapper), (uint8_t*)pcbw), epDataOutIndex);
if (ret) { if (ret) {
ErrorMessage<uint8_t > (PSTR("CBW"), ret); ErrorMessage<uint8_t > (PSTR("CBW"), ret);
@ -732,16 +732,16 @@ uint8_t BulkOnly::Transaction(CommandBlockWrapper *pcbw, uint16_t buf_size, void
uint8_t rbuf[read]; uint8_t rbuf[read];
uint8_t err = 0; uint8_t err = 0;
ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, rbuf); ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, rbuf);
if (ret == hrSUCCESS) ((USBReadParser*) buf)->Parse(read, rbuf, 0); if (ret == hrSUCCESS) ((USBReadParser*)buf)->Parse(read, rbuf, 0);
if (ret == hrSTALL) err = ClearEpHalt(epDataInIndex); if (ret == hrSTALL) err = ClearEpHalt(epDataInIndex);
if (ret) { if (ret) {
ErrorMessage<uint8_t > (PSTR("RDR"), err); ErrorMessage<uint8_t > (PSTR("RDR"), err);
return MASS_ERR_GENERAL_USB_ERROR; return MASS_ERR_GENERAL_USB_ERROR;
} }
} else } else
ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*) buf); ret = pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, &read, (uint8_t*)buf);
} else } else
ret = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*) buf); ret = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, read, (uint8_t*)buf);
ret = HandleUsbError(ret, (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) ? epDataInIndex : epDataOutIndex); ret = HandleUsbError(ret, (pcbw->bmCBWFlags & MASS_CMD_DIR_IN) ? epDataInIndex : epDataOutIndex);
@ -798,7 +798,7 @@ uint8_t BulkOnly::HandleSCSIError(uint8_t status) {
switch (status) { switch (status) {
case 0: return MASS_ERR_SUCCESS; case 0: return MASS_ERR_SUCCESS;
//case 4: return MASS_ERR_UNIT_BUSY; //case 4: return MASS_ERR_UNIT_BUSY;
case 2: case 2:
ErrorMessage<uint8_t > (PSTR("Phase"), status); ErrorMessage<uint8_t > (PSTR("Phase"), status);
ResetRecovery(); ResetRecovery();

View file

@ -104,7 +104,7 @@ struct Capacity {
uint8_t data[8]; uint8_t data[8];
//uint32_t dwBlockAddress; //uint32_t dwBlockAddress;
//uint32_t dwBlockLength; //uint32_t dwBlockLength;
}__attribute__((packed)); } __attribute__((packed));
struct InquiryResponse { struct InquiryResponse {
uint8_t DeviceType : 5; uint8_t DeviceType : 5;
@ -136,14 +136,14 @@ struct InquiryResponse {
uint8_t VendorID[8]; uint8_t VendorID[8];
uint8_t ProductID[16]; uint8_t ProductID[16];
uint8_t RevisionID[4]; uint8_t RevisionID[4];
}__attribute__((packed)); } __attribute__((packed));
struct CommandBlockWrapperBase { struct CommandBlockWrapperBase {
uint32_t dCBWSignature; uint32_t dCBWSignature;
uint32_t dCBWTag; uint32_t dCBWTag;
uint32_t dCBWDataTransferLength; uint32_t dCBWDataTransferLength;
uint8_t bmCBWFlags; uint8_t bmCBWFlags;
}__attribute__((packed)); } __attribute__((packed));
struct CommandBlockWrapper : public CommandBlockWrapperBase { struct CommandBlockWrapper : public CommandBlockWrapperBase {
@ -158,14 +158,14 @@ struct CommandBlockWrapper : public CommandBlockWrapperBase {
}; };
uint8_t CBWCB[16]; uint8_t CBWCB[16];
}__attribute__((packed)); } __attribute__((packed));
struct CommandStatusWrapper { struct CommandStatusWrapper {
uint32_t dCSWSignature; uint32_t dCSWSignature;
uint32_t dCSWTag; uint32_t dCSWTag;
uint32_t dCSWDataResidue; uint32_t dCSWDataResidue;
uint8_t bCSWStatus; uint8_t bCSWStatus;
}__attribute__((packed)); } __attribute__((packed));
struct RequestSenseResponce { struct RequestSenseResponce {
uint8_t bResponseCode; uint8_t bResponseCode;
@ -184,7 +184,7 @@ struct RequestSenseResponce {
uint8_t bAdditionalSenseQualifier; uint8_t bAdditionalSenseQualifier;
uint8_t bFieldReplaceableUnitCode; uint8_t bFieldReplaceableUnitCode;
uint8_t SenseKeySpecific[3]; uint8_t SenseKeySpecific[3];
}__attribute__((packed)); } __attribute__((packed));
#define MASS_MAX_ENDPOINTS 3 #define MASS_MAX_ENDPOINTS 3

View file

@ -43,7 +43,7 @@ bool PTPListParser::Parse(uint8_t **pp, uint16_t *pcntdn, PTP_ARRAY_EL_FUNC pf,
return false; return false;
arLen = 0; arLen = 0;
arLen = (pBuf->valueSize >= 4) ? *((uint32_t*) pBuf->pValue) : (uint32_t) (*((uint16_t*) pBuf->pValue)); arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
arLenCntdn = arLen; arLenCntdn = arLen;
nStage = 2; nStage = 2;

View file

@ -32,7 +32,7 @@ e-mail : support@circuitsathome.com
struct MultiValueBuffer { struct MultiValueBuffer {
uint8_t valueSize; uint8_t valueSize;
void *pValue; void *pValue;
}__attribute__((packed)); } __attribute__((packed));
class MultiByteValueParser { class MultiByteValueParser {
uint8_t * pBuf; uint8_t * pBuf;
@ -72,17 +72,17 @@ public:
}; };
bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) { bool Skip(uint8_t **pp, uint16_t *pcntdn, uint16_t bytes_to_skip) {
switch (nStage) { switch(nStage) {
case 0: case 0:
countDown = bytes_to_skip; countDown = bytes_to_skip;
nStage++; nStage++;
case 1: case 1:
for (; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--); for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
if (!countDown) if(!countDown)
nStage = 0; nStage = 0;
}; };
return (!countDown); return(!countDown);
}; };
}; };
@ -132,7 +132,7 @@ public:
valSize = val_size; valSize = val_size;
prsMode = mode; prsMode = mode;
if (prsMode == modeRange) { if(prsMode == modeRange) {
arLenCntdn = arLen = 3; arLenCntdn = arLen = 3;
nStage = 2; nStage = 2;
} else { } else {

View file

@ -26,19 +26,19 @@ void Notifyc(char c, int lvl);
template <class T> template <class T>
void PrintHex(T val, int lvl) { void PrintHex(T val, int lvl) {
int num_nibbles = sizeof (T) * 2; int num_nibbles = sizeof(T) * 2;
do { do {
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
if (v > 57) v += 7; if(v > 57) v += 7;
Notifyc(v, lvl); Notifyc(v, lvl);
} while (--num_nibbles); } while(--num_nibbles);
} }
template <class T> template <class T>
void PrintBin(T val, int lvl) { void PrintBin(T val, int lvl) {
for (T mask = (((T) 1) << ((sizeof (T) << 3) - 1)); mask; mask >>= 1) for(T mask = (((T) 1) << ((sizeof(T) << 3) - 1)); mask; mask >>= 1)
if (val & mask) if(val & mask)
Notifyc('1', lvl); Notifyc('1', lvl);
else else
Notifyc('0', lvl); Notifyc('0', lvl);
@ -46,21 +46,21 @@ void PrintBin(T val, int lvl) {
template <class T> template <class T>
void SerialPrintHex(T val) { void SerialPrintHex(T val) {
int num_nibbles = sizeof (T) * 2; int num_nibbles = sizeof(T) * 2;
do { do {
char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f); char v = 48 + (((val >> (num_nibbles - 1) * 4)) & 0x0f);
if (v > 57) v += 7; if(v > 57) v += 7;
Serial.print(v); Serial.print(v);
} while (--num_nibbles); } while(--num_nibbles);
} }
template <class T> template <class T>
void PrintHex2(Print *prn, T val) { void PrintHex2(Print *prn, T val) {
T mask = (((T) 1) << (((sizeof (T) << 1) - 1) << 2)); T mask = (((T) 1) << (((sizeof(T) << 1) - 1) << 2));
while (mask > 1) { while(mask > 1) {
if (val < mask) if(val < mask)
prn->print("0"); prn->print("0");
mask >>= 4; mask >>= 4;

View file

@ -108,7 +108,7 @@ typedef struct {
uint8_t iProduct; // Index of String Descriptor describing the product. uint8_t iProduct; // Index of String Descriptor describing the product.
uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number.
uint8_t bNumConfigurations; // Number of possible configurations. uint8_t bNumConfigurations; // Number of possible configurations.
}__attribute__((packed)) USB_DEVICE_DESCRIPTOR; } __attribute__((packed)) USB_DEVICE_DESCRIPTOR;
/* Configuration descriptor structure */ /* Configuration descriptor structure */
typedef struct { typedef struct {
@ -120,7 +120,7 @@ typedef struct {
uint8_t iConfiguration; // Index of String Descriptor describing the configuration. uint8_t iConfiguration; // Index of String Descriptor describing the configuration.
uint8_t bmAttributes; // Configuration characteristics. uint8_t bmAttributes; // Configuration characteristics.
uint8_t bMaxPower; // Maximum power consumed by this configuration. uint8_t bMaxPower; // Maximum power consumed by this configuration.
}__attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; } __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR;
/* Interface descriptor structure */ /* Interface descriptor structure */
typedef struct { typedef struct {
@ -133,7 +133,7 @@ typedef struct {
uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF).
uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific.
uint8_t iInterface; // Index of String Descriptor describing the interface. uint8_t iInterface; // Index of String Descriptor describing the interface.
}__attribute__((packed)) USB_INTERFACE_DESCRIPTOR; } __attribute__((packed)) USB_INTERFACE_DESCRIPTOR;
/* Endpoint descriptor structure */ /* Endpoint descriptor structure */
typedef struct { typedef struct {
@ -143,7 +143,7 @@ typedef struct {
uint8_t bmAttributes; // Endpoint transfer type. uint8_t bmAttributes; // Endpoint transfer type.
uint16_t wMaxPacketSize; // Maximum packet size. uint16_t wMaxPacketSize; // Maximum packet size.
uint8_t bInterval; // Polling interval in frames. uint8_t bInterval; // Polling interval in frames.
}__attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; } __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR;
/* HID descriptor */ /* HID descriptor */
typedef struct { typedef struct {
@ -154,11 +154,11 @@ typedef struct {
uint8_t bNumDescriptors; // Number of additional class specific descriptors uint8_t bNumDescriptors; // Number of additional class specific descriptors
uint8_t bDescrType; // Type of class descriptor uint8_t bDescrType; // Type of class descriptor
uint16_t wDescriptorLength; // Total size of the Report descriptor uint16_t wDescriptorLength; // Total size of the Report descriptor
}__attribute__((packed)) USB_HID_DESCRIPTOR; } __attribute__((packed)) USB_HID_DESCRIPTOR;
typedef struct { typedef struct {
uint8_t bDescrType; // Type of class descriptor uint8_t bDescrType; // Type of class descriptor
uint16_t wDescriptorLength; // Total size of the Report descriptor uint16_t wDescriptorLength; // Total size of the Report descriptor
}__attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; } __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE;
#endif // _ch9_h_ #endif // _ch9_h_

View file

@ -96,9 +96,9 @@ template< typename SS, typename INTR >
void MAX3421e< SS, INTR >::regWr(uint8_t reg, uint8_t data) { void MAX3421e< SS, INTR >::regWr(uint8_t reg, uint8_t data) {
SS::Clear(); SS::Clear();
SPDR = (reg | 0x02); SPDR = (reg | 0x02);
while (!(SPSR & (1 << SPIF))); while(!(SPSR & (1 << SPIF)));
SPDR = data; SPDR = data;
while (!(SPSR & (1 << SPIF))); while(!(SPSR & (1 << SPIF)));
SS::Set(); SS::Set();
return; return;
}; };
@ -109,14 +109,14 @@ template< typename SS, typename INTR >
uint8_t* MAX3421e< SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { uint8_t* MAX3421e< SS, INTR >::bytesWr(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
SS::Clear(); SS::Clear();
SPDR = (reg | 0x02); //set WR bit and send register number SPDR = (reg | 0x02); //set WR bit and send register number
while (nbytes--) { while(nbytes--) {
while (!(SPSR & (1 << SPIF))); //check if previous byte was sent while(!(SPSR & (1 << SPIF))); //check if previous byte was sent
SPDR = (*data_p); // send next data byte SPDR = (*data_p); // send next data byte
data_p++; // advance data pointer data_p++; // advance data pointer
} }
while (!(SPSR & (1 << SPIF))); while(!(SPSR & (1 << SPIF)));
SS::Set(); SS::Set();
return ( data_p); return( data_p);
} }
/* GPIO write */ /* GPIO write */
/*GPIO byte is split between 2 registers, so two writes are needed to write one byte */ /*GPIO byte is split between 2 registers, so two writes are needed to write one byte */
@ -135,11 +135,11 @@ template< typename SS, typename INTR >
uint8_t MAX3421e< SS, INTR >::regRd(uint8_t reg) { uint8_t MAX3421e< SS, INTR >::regRd(uint8_t reg) {
SS::Clear(); SS::Clear();
SPDR = reg; SPDR = reg;
while (!(SPSR & (1 << SPIF))); while(!(SPSR & (1 << SPIF)));
SPDR = 0; //send empty byte SPDR = 0; //send empty byte
while (!(SPSR & (1 << SPIF))); while(!(SPSR & (1 << SPIF)));
SS::Set(); SS::Set();
return ( SPDR); return( SPDR);
} }
/* multiple-byte register read */ /* multiple-byte register read */
@ -148,16 +148,16 @@ template< typename SS, typename INTR >
uint8_t* MAX3421e< SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) { uint8_t* MAX3421e< SS, INTR >::bytesRd(uint8_t reg, uint8_t nbytes, uint8_t* data_p) {
SS::Clear(); SS::Clear();
SPDR = reg; SPDR = reg;
while (!(SPSR & (1 << SPIF))); //wait while(!(SPSR & (1 << SPIF))); //wait
while (nbytes) { while(nbytes) {
SPDR = 0; //send empty byte SPDR = 0; //send empty byte
nbytes--; nbytes--;
while (!(SPSR & (1 << SPIF))); while(!(SPSR & (1 << SPIF)));
*data_p = SPDR; *data_p = SPDR;
data_p++; data_p++;
} }
SS::Set(); SS::Set();
return ( data_p); return( data_p);
} }
/* GPIO read. See gpioWr for explanation */ /* GPIO read. See gpioWr for explanation */
@ -168,7 +168,7 @@ uint8_t MAX3421e< SS, INTR >::gpioRd() {
gpin = regRd(rIOPINS2); //pins 4-7 gpin = regRd(rIOPINS2); //pins 4-7
gpin &= 0xf0; //clean lower nibble gpin &= 0xf0; //clean lower nibble
gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation. gpin |= (regRd(rIOPINS1) >> 4); //shift low bits and OR with upper from previous operation.
return ( gpin); return( gpin);
} }
/* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset /* reset MAX3421E. Returns number of cycles it took for PLL to stabilize after reset
@ -178,12 +178,12 @@ uint16_t MAX3421e< SS, INTR >::reset() {
uint16_t i = 0; uint16_t i = 0;
regWr(rUSBCTL, bmCHIPRES); regWr(rUSBCTL, bmCHIPRES);
regWr(rUSBCTL, 0x00); regWr(rUSBCTL, 0x00);
while (++i) { while(++i) {
if ((regRd(rUSBIRQ) & bmOSCOKIRQ)) { if((regRd(rUSBIRQ) & bmOSCOKIRQ)) {
break; break;
} }
} }
return ( i); return( i);
} }
///* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ ///* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
//template< typename SS, typename INTR > //template< typename SS, typename INTR >
@ -200,8 +200,8 @@ uint16_t MAX3421e< SS, INTR >::reset() {
/* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */ /* initialize MAX3421E. Set Host mode, pullups, and stuff. Returns 0 if success, -1 if not */
template< typename SS, typename INTR > template< typename SS, typename INTR >
int8_t MAX3421e< SS, INTR >::Init() { int8_t MAX3421e< SS, INTR >::Init() {
if (reset() == 0) { //OSCOKIRQ hasn't asserted in time if(reset() == 0) { //OSCOKIRQ hasn't asserted in time
return ( -1); return( -1);
} }
regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host regWr(rMODE, bmDPPULLDN | bmDMPULLDN | bmHOST); // set pull-downs, Host
@ -209,13 +209,13 @@ int8_t MAX3421e< SS, INTR >::Init() {
/* check if device is connected */ /* check if device is connected */
regWr(rHCTL, bmSAMPLEBUS); // sample USB bus regWr(rHCTL, bmSAMPLEBUS); // sample USB bus
while (!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish while(!(regRd(rHCTL) & bmSAMPLEBUS)); //wait for sample operation to finish
busprobe(); //check if anything is connected busprobe(); //check if anything is connected
regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt regWr(rHIRQ, bmCONDETIRQ); //clear connection detect interrupt
regWr(rCPUCTL, 0x01); //enable interrupt pin regWr(rCPUCTL, 0x01); //enable interrupt pin
return ( 0); return( 0);
} }
/* probe bus to determine device presence and speed and switch host to this speed */ /* probe bus to determine device presence and speed and switch host to this speed */
@ -224,9 +224,9 @@ void MAX3421e< SS, INTR >::busprobe() {
uint8_t bus_sample; uint8_t bus_sample;
bus_sample = regRd(rHRSL); //Get J,K status bus_sample = regRd(rHRSL); //Get J,K status
bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte bus_sample &= (bmJSTATUS | bmKSTATUS); //zero the rest of the byte
switch (bus_sample) { //start full-speed or low-speed host switch(bus_sample) { //start full-speed or low-speed host
case( bmJSTATUS): case( bmJSTATUS):
if ((regRd(rMODE) & bmLOWSPEED) == 0) { if((regRd(rMODE) & bmLOWSPEED) == 0) {
regWr(rMODE, MODE_FS_HOST); //start full-speed host regWr(rMODE, MODE_FS_HOST); //start full-speed host
vbusState = FSHOST; vbusState = FSHOST;
} else { } else {
@ -235,7 +235,7 @@ void MAX3421e< SS, INTR >::busprobe() {
} }
break; break;
case( bmKSTATUS): case( bmKSTATUS):
if ((regRd(rMODE) & bmLOWSPEED) == 0) { if((regRd(rMODE) & bmLOWSPEED) == 0) {
regWr(rMODE, MODE_LS_HOST); //start low-speed host regWr(rMODE, MODE_LS_HOST); //start low-speed host
vbusState = LSHOST; vbusState = LSHOST;
} else { } else {
@ -262,7 +262,7 @@ uint8_t MAX3421e< SS, INTR >::Task(void) {
//Serial.println( vbusState, HEX ); //Serial.println( vbusState, HEX );
pinvalue = INTR::IsSet(); //Read(); pinvalue = INTR::IsSet(); //Read();
//pinvalue = digitalRead( MAX_INT ); //pinvalue = digitalRead( MAX_INT );
if (pinvalue == 0) { if(pinvalue == 0) {
rcode = IntHandler(); rcode = IntHandler();
} }
// pinvalue = digitalRead( MAX_GPX ); // pinvalue = digitalRead( MAX_GPX );
@ -270,7 +270,7 @@ uint8_t MAX3421e< SS, INTR >::Task(void) {
// GpxHandler(); // GpxHandler();
// } // }
// usbSM(); //USB state machine // usbSM(); //USB state machine
return ( rcode); return( rcode);
} }
template< typename SS, typename INTR > template< typename SS, typename INTR >
@ -281,13 +281,13 @@ uint8_t MAX3421e< SS, INTR >::IntHandler() {
//if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler //if( HIRQ & bmFRAMEIRQ ) { //->1ms SOF interrupt handler
// HIRQ_sendback |= bmFRAMEIRQ; // HIRQ_sendback |= bmFRAMEIRQ;
//}//end FRAMEIRQ handling //}//end FRAMEIRQ handling
if (HIRQ & bmCONDETIRQ) { if(HIRQ & bmCONDETIRQ) {
busprobe(); busprobe();
HIRQ_sendback |= bmCONDETIRQ; HIRQ_sendback |= bmCONDETIRQ;
} }
/* End HIRQ interrupts handling, clear serviced IRQs */ /* End HIRQ interrupts handling, clear serviced IRQs */
regWr(rHIRQ, HIRQ_sendback); regWr(rHIRQ, HIRQ_sendback);
return ( HIRQ_sendback); return( HIRQ_sendback);
} }
//template< typename SS, typename INTR > //template< typename SS, typename INTR >
//uint8_t MAX3421e< SS, INTR >::GpxHandler() //uint8_t MAX3421e< SS, INTR >::GpxHandler()

View file

@ -74,7 +74,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->lowspeed = lowspeed; p->lowspeed = lowspeed;
// Get device descriptor // Get device descriptor
rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*) buf); rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);
p->lowspeed = false; p->lowspeed = false;
@ -89,17 +89,17 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
// Extract device class from device descriptor // Extract device class from device descriptor
// If device class is not a hub return // If device class is not a hub return
if (((USB_DEVICE_DESCRIPTOR*) buf)->bDeviceClass != 0x09) if (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass != 0x09)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// Allocate new address according to device class // Allocate new address according to device class
bAddress = addrPool.AllocAddress(parent, (((USB_DEVICE_DESCRIPTOR*) buf)->bDeviceClass == 0x09) ? true : false, port); bAddress = addrPool.AllocAddress(parent, (((USB_DEVICE_DESCRIPTOR*)buf)->bDeviceClass == 0x09) ? true : false, port);
if (!bAddress) if (!bAddress)
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL; return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;
// Extract Max Packet Size from the device descriptor // Extract Max Packet Size from the device descriptor
epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*) buf)->bMaxPacketSize0; epInfo[0].maxPktSize = ((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
// Assign new address to the device // Assign new address to the device
rcode = pUsb->setAddr(0, 0, bAddress); rcode = pUsb->setAddr(0, 0, bAddress);
@ -118,7 +118,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
p->epinfo = oldep_ptr; p->epinfo = oldep_ptr;
if (len) if (len)
rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*) buf); rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);
if (rcode) if (rcode)
goto FailGetDevDescr; goto FailGetDevDescr;
@ -139,7 +139,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
goto FailGetHubDescr; goto FailGetHubDescr;
// Save number of ports for future use // Save number of ports for future use
bNbrPorts = ((HubDescriptor*) buf)->bNbrPorts; bNbrPorts = ((HubDescriptor*)buf)->bNbrPorts;
bInitState = 2; bInitState = 2;
@ -148,7 +148,7 @@ uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf); rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);
if (!rcode) { if (!rcode) {
cd_len = ((USB_CONFIGURATION_DESCRIPTOR*) buf)->wTotalLength; cd_len = ((USB_CONFIGURATION_DESCRIPTOR*)buf)->wTotalLength;
rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf); rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
} }
if (rcode) if (rcode)

View file

@ -155,11 +155,11 @@ struct HubDescriptor {
uint16_t TTThinkTime : 2; uint16_t TTThinkTime : 2;
uint16_t PortIndicatorsSupported : 1; uint16_t PortIndicatorsSupported : 1;
uint16_t Reserved : 8; uint16_t Reserved : 8;
}__attribute__((packed)); } __attribute__((packed));
uint8_t bPwrOn2PwrGood; uint8_t bPwrOn2PwrGood;
uint8_t bHubContrCurrent; uint8_t bHubContrCurrent;
}__attribute__((packed)); } __attribute__((packed));
struct HubEvent { struct HubEvent {
@ -168,11 +168,11 @@ struct HubEvent {
struct { struct {
uint16_t bmStatus; // port status bits uint16_t bmStatus; // port status bits
uint16_t bmChange; // port status change bits uint16_t bmChange; // port status change bits
}__attribute__((packed)); } __attribute__((packed));
uint32_t bmEvent; uint32_t bmEvent;
uint8_t evtBuff[4]; uint8_t evtBuff[4];
}; };
}__attribute__((packed)); } __attribute__((packed));
class USBHub : USBDeviceConfig { class USBHub : USBDeviceConfig {
static bool bResetInitiated; // True when reset is triggered static bool bResetInitiated; // True when reset is triggered
@ -216,42 +216,42 @@ public:
// Clear Hub Feature // Clear Hub Feature
inline uint8_t USBHub::ClearHubFeature(uint8_t fid) { inline uint8_t USBHub::ClearHubFeature(uint8_t fid) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_HUB_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
} }
// Clear Port Feature // Clear Port Feature
inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { inline uint8_t USBHub::ClearPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_CLEAR_PORT_FEATURE, USB_REQUEST_CLEAR_FEATURE, fid, 0, ((0x0000 | port) | (sel << 8)), 0, 0, NULL, NULL));
} }
// Get Hub Descriptor // Get Hub Descriptor
inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) { inline uint8_t USBHub::GetHubDescriptor(uint8_t index, uint16_t nbytes, uint8_t *dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_DESCRIPTOR, USB_REQUEST_GET_DESCRIPTOR, index, 0x29, 0, nbytes, nbytes, dataptr, NULL));
} }
// Get Hub Status // Get Hub Status
inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USBHub::GetHubStatus(uint16_t nbytes, uint8_t* dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_HUB_STATUS, USB_REQUEST_GET_STATUS, 0, 0, 0x0000, nbytes, nbytes, dataptr, NULL));
} }
// Get Port Status // Get Port Status
inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USBHub::GetPortStatus(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_GET_PORT_STATUS, USB_REQUEST_GET_STATUS, 0, 0, port, nbytes, nbytes, dataptr, NULL));
} }
// Set Hub Descriptor // Set Hub Descriptor
inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) { inline uint8_t USBHub::SetHubDescriptor(uint8_t port, uint16_t nbytes, uint8_t* dataptr) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_DESCRIPTOR, USB_REQUEST_SET_DESCRIPTOR, 0, 0, port, nbytes, nbytes, dataptr, NULL));
} }
// Set Hub Feature // Set Hub Feature
inline uint8_t USBHub::SetHubFeature(uint8_t fid) { inline uint8_t USBHub::SetHubFeature(uint8_t fid) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_HUB_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, 0, 0, 0, NULL, NULL));
} }
// Set Port Feature // Set Port Feature
inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) { inline uint8_t USBHub::SetPortFeature(uint8_t fid, uint8_t port, uint8_t sel) {
return ( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL)); return( pUsb->ctrlReq(bAddress, 0, bmREQ_SET_PORT_FEATURE, USB_REQUEST_SET_FEATURE, fid, 0, (((0x0000 | sel) << 8) | port), 0, 0, NULL, NULL));
} }
void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false); void PrintHubPortStatus(USB *usbptr, uint8_t addr, uint8_t port, bool print_changes = false);

View file

@ -22,43 +22,43 @@
/** Enum used to set special LED modes supported by the Xbox controller. */ /** Enum used to set special LED modes supported by the Xbox controller. */
enum LEDMode { enum LEDMode {
ROTATING = 0x0A, ROTATING = 0x0A,
FASTBLINK = 0x0B, FASTBLINK = 0x0B,
SLOWBLINK = 0x0C, SLOWBLINK = 0x0C,
ALTERNATING = 0x0D, ALTERNATING = 0x0D,
}; };
/** Used to set the LEDs on the controllers */ /** Used to set the LEDs on the controllers */
const uint8_t XBOXLEDS[] PROGMEM = { const uint8_t XBOXLEDS[] PROGMEM = {
0x02, // LED1 0x02, // LED1
0x03, // LED2 0x03, // LED2
0x04, // LED3 0x04, // LED3
0x05, // LED4 0x05, // LED4
0x01 // ALL - Used to blink all LEDs 0x01 // ALL - Used to blink all LEDs
}; };
/** Buttons on the controllers */ /** Buttons on the controllers */
const uint16_t XBOXBUTTONS[] PROGMEM = { const uint16_t XBOXBUTTONS[] PROGMEM = {
0x0100, // UP 0x0100, // UP
0x0800, // RIGHT 0x0800, // RIGHT
0x0200, // DOWN 0x0200, // DOWN
0x0400, // LEFT 0x0400, // LEFT
0x2000, // BACK 0x2000, // BACK
0x1000, // START 0x1000, // START
0x4000, // L3 0x4000, // L3
0x8000, // R3 0x8000, // R3
0,0, // Skip L2 and R2 as these are analog buttons 0, 0, // Skip L2 and R2 as these are analog buttons
0x0001, // L1 0x0001, // L1
0x0002, // R1 0x0002, // R1
0x0020, // B 0x0020, // B
0x0010, // A 0x0010, // A
0x0040, // X 0x0040, // X
0x0080, // Y 0x0080, // Y
0x0004, // XBOX 0x0004, // XBOX
0x0008 // SYNC 0x0008 // SYNC
}; };
#endif #endif