mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Clean up code formatting to industry standards.
This commit is contained in:
parent
9b224b9899
commit
904f2ff25a
42 changed files with 5429 additions and 5202 deletions
621
BTD.h
621
BTD.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -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 */
|
|
||||||
/**
|
|
||||||
* Initialize the Bluetooth dongle.
|
|
||||||
* @param parent Hub number.
|
|
||||||
* @param port Port number on the hub.
|
|
||||||
* @param lowspeed Speed of the device.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
|
||||||
/**
|
|
||||||
* Release the USB device.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
virtual uint8_t Release();
|
|
||||||
/**
|
|
||||||
* Poll the USB Input endpoins and run the state machines.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
/**
|
|
||||||
* UsbConfigXtracter implementation, used to extract endpoint information.
|
|
||||||
* @param conf Configuration value.
|
|
||||||
* @param iface Interface number.
|
|
||||||
* @param alt Alternate setting.
|
|
||||||
* @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. */
|
/** @name USBDeviceConfig implementation */
|
||||||
void disconnect() {
|
/**
|
||||||
for (uint8_t i=0; i<BTD_NUMSERVICES; i++)
|
* Initialize the Bluetooth dongle.
|
||||||
if (btService[i])
|
* @param parent Hub number.
|
||||||
btService[i]->disconnect();
|
* @param port Port number on the hub.
|
||||||
};
|
* @param lowspeed Speed of the device.
|
||||||
/**
|
* @return 0 on success.
|
||||||
* Register bluetooth dongle members/services.
|
*/
|
||||||
* @param pService Pointer to BluetoothService class instance.
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
* @return The serice ID on succes or -1 on fail.
|
/**
|
||||||
*/
|
* Release the USB device.
|
||||||
int8_t registerServiceClass(BluetoothService *pService) {
|
* @return 0 on success.
|
||||||
for (uint8_t i=0; i<BTD_NUMSERVICES; i++) {
|
*/
|
||||||
if (!btService[i]) {
|
virtual uint8_t Release();
|
||||||
btService[i] = pService;
|
/**
|
||||||
return i; // Return ID
|
* Poll the USB Input endpoins and run the state machines.
|
||||||
}
|
* @return 0 on success.
|
||||||
}
|
*/
|
||||||
return -1; // ErrorregisterServiceClass
|
virtual uint8_t Poll();
|
||||||
};
|
|
||||||
|
/**
|
||||||
/** @name HCI Commands */
|
* Get the device address.
|
||||||
/**
|
* @return The device address.
|
||||||
* Used to send a HCI Command.
|
*/
|
||||||
* @param data Data to send.
|
virtual uint8_t GetAddress() {
|
||||||
* @param nbytes Number of bytes to send.
|
return bAddress;
|
||||||
*/
|
};
|
||||||
void HCI_Command(uint8_t* data, uint16_t nbytes);
|
|
||||||
/** Reset the Bluetooth dongle. */
|
/**
|
||||||
void hci_reset();
|
* Used to check if the dongle has been initialized.
|
||||||
/** Read the Bluetooth address of the dongle. */
|
* @return True if it's ready.
|
||||||
void hci_read_bdaddr();
|
*/
|
||||||
/** Read the HCI Version of the Bluetooth dongle. */
|
virtual bool isReady() {
|
||||||
void hci_read_local_version_information();
|
return bPollEnable;
|
||||||
/**
|
};
|
||||||
* Set the local name of the Bluetooth dongle.
|
/**@}*/
|
||||||
* @param name Desired name.
|
|
||||||
*/
|
/** @name UsbConfigXtracter implementation */
|
||||||
void hci_set_local_name(const char* name);
|
/**
|
||||||
/** Enable visibility to other Bluetooth devices. */
|
* UsbConfigXtracter implementation, used to extract endpoint information.
|
||||||
void hci_write_scan_enable();
|
* @param conf Configuration value.
|
||||||
/** Disable visibility to other Bluetooth devices. */
|
* @param iface Interface number.
|
||||||
void hci_write_scan_disable();
|
* @param alt Alternate setting.
|
||||||
/** Read the remote devices name. */
|
* @param proto Interface Protocol.
|
||||||
void hci_remote_name();
|
* @param ep Endpoint Descriptor.
|
||||||
/** Accept the connection with the Bluetooth device. */
|
*/
|
||||||
void hci_accept_connection();
|
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep);
|
||||||
/**
|
/**@}*/
|
||||||
* Disconnect the HCI connection.
|
|
||||||
* @param handle The HCI Handle for the connection.
|
/** Disconnects both the L2CAP Channel and the HCI Connection for all Bluetooth services. */
|
||||||
*/
|
void disconnect() {
|
||||||
void hci_disconnect(uint16_t handle);
|
for(uint8_t i = 0; i < BTD_NUMSERVICES; i++)
|
||||||
/**
|
if(btService[i])
|
||||||
* Respond with the pin for the connection.
|
btService[i]->disconnect();
|
||||||
* The pin is automatically set for the Wii library,
|
};
|
||||||
* but can be customized for the SPP library.
|
|
||||||
*/
|
/**
|
||||||
void hci_pin_code_request_reply();
|
* Register bluetooth dongle members/services.
|
||||||
/** Respons when no pin was set. */
|
* @param pService Pointer to BluetoothService class instance.
|
||||||
void hci_pin_code_negative_request_reply();
|
* @return The serice ID on succes or -1 on fail.
|
||||||
/**
|
*/
|
||||||
* Command is used to reply to a Link Key Request event from the BR/EDR Controller
|
int8_t registerServiceClass(BluetoothService *pService) {
|
||||||
* if the Host does not have a stored Link Key for the connection.
|
for(uint8_t i = 0; i < BTD_NUMSERVICES; i++) {
|
||||||
*/
|
if(!btService[i]) {
|
||||||
void hci_link_key_request_negative_reply();
|
btService[i] = pService;
|
||||||
/** Used to try to authenticate with the remote device. */
|
return i; // Return ID
|
||||||
void hci_authentication_request();
|
}
|
||||||
/** Start a HCI inquiry. */
|
}
|
||||||
void hci_inquiry();
|
return -1; // ErrorregisterServiceClass
|
||||||
/** Cancel a HCI inquiry. */
|
};
|
||||||
void hci_inquiry_cancel();
|
|
||||||
/** Connect to a device. */
|
/** @name HCI Commands */
|
||||||
void hci_connect();
|
/**
|
||||||
/** Used to a set the class of the device. */
|
* Used to send a HCI Command.
|
||||||
void hci_write_class_of_device();
|
* @param data Data to send.
|
||||||
/**@}*/
|
* @param nbytes Number of bytes to send.
|
||||||
|
*/
|
||||||
/** @name L2CAP Commands */
|
void HCI_Command(uint8_t* data, uint16_t nbytes);
|
||||||
/**
|
/** Reset the Bluetooth dongle. */
|
||||||
* Used to send L2CAP Commands.
|
void hci_reset();
|
||||||
* @param handle HCI Handle.
|
/** Read the Bluetooth address of the dongle. */
|
||||||
* @param data Data to send.
|
void hci_read_bdaddr();
|
||||||
* @param nbytes Number of bytes to send.
|
/** Read the HCI Version of the Bluetooth dongle. */
|
||||||
* @param channelLow,channelHigh Low and high byte of channel to send to.
|
void hci_read_local_version_information();
|
||||||
* If argument is omitted then the Standard L2CAP header: Channel ID (0x01) for ACL-U will be used.
|
/**
|
||||||
*/
|
* Set the local name of the Bluetooth dongle.
|
||||||
void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00);
|
* @param name Desired name.
|
||||||
/**
|
*/
|
||||||
* L2CAP Connection Request.
|
void hci_set_local_name(const char* name);
|
||||||
* @param handle HCI handle.
|
/** Enable visibility to other Bluetooth devices. */
|
||||||
* @param rxid Identifier.
|
void hci_write_scan_enable();
|
||||||
* @param scid Source Channel Identifier.
|
/** Disable visibility to other Bluetooth devices. */
|
||||||
* @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.
|
void hci_write_scan_disable();
|
||||||
*/
|
/** Read the remote devices name. */
|
||||||
void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);
|
void hci_remote_name();
|
||||||
/**
|
/** Accept the connection with the Bluetooth device. */
|
||||||
* L2CAP Connection Response.
|
void hci_accept_connection();
|
||||||
* @param handle HCI handle.
|
/**
|
||||||
* @param rxid Identifier.
|
* Disconnect the HCI connection.
|
||||||
* @param dcid Destination Channel Identifier.
|
* @param handle The HCI Handle for the connection.
|
||||||
* @param scid Source Channel Identifier.
|
*/
|
||||||
* @param result Result - First send ::PENDING and then ::SUCCESSFUL.
|
void hci_disconnect(uint16_t handle);
|
||||||
*/
|
/**
|
||||||
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
|
* Respond with the pin for the connection.
|
||||||
/**
|
* The pin is automatically set for the Wii library,
|
||||||
* L2CAP Config Request.
|
* but can be customized for the SPP library.
|
||||||
* @param handle HCI Handle.
|
*/
|
||||||
* @param rxid Identifier.
|
void hci_pin_code_request_reply();
|
||||||
* @param dcid Destination Channel Identifier.
|
/** Respons when no pin was set. */
|
||||||
*/
|
void hci_pin_code_negative_request_reply();
|
||||||
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);
|
/**
|
||||||
/**
|
* Command is used to reply to a Link Key Request event from the BR/EDR Controller
|
||||||
* L2CAP Config Response.
|
* if the Host does not have a stored Link Key for the connection.
|
||||||
* @param handle HCI Handle.
|
*/
|
||||||
* @param rxid Identifier.
|
void hci_link_key_request_negative_reply();
|
||||||
* @param scid Source Channel Identifier.
|
/** Used to try to authenticate with the remote device. */
|
||||||
*/
|
void hci_authentication_request();
|
||||||
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);
|
/** Start a HCI inquiry. */
|
||||||
/**
|
void hci_inquiry();
|
||||||
* L2CAP Disconnection Request.
|
/** Cancel a HCI inquiry. */
|
||||||
* @param handle HCI Handle.
|
void hci_inquiry_cancel();
|
||||||
* @param rxid Identifier.
|
/** Connect to a device. */
|
||||||
* @param dcid Device Channel Identifier.
|
void hci_connect();
|
||||||
* @param scid Source Channel Identifier.
|
/** Used to a set the class of the device. */
|
||||||
*/
|
void hci_write_class_of_device();
|
||||||
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
|
/**@}*/
|
||||||
/**
|
|
||||||
* L2CAP Disconnection Response.
|
/** @name L2CAP Commands */
|
||||||
* @param handle HCI Handle.
|
/**
|
||||||
* @param rxid Identifier.
|
* Used to send L2CAP Commands.
|
||||||
* @param dcid Device Channel Identifier.
|
* @param handle HCI Handle.
|
||||||
* @param scid Source Channel Identifier.
|
* @param data Data to send.
|
||||||
*/
|
* @param nbytes Number of bytes to send.
|
||||||
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
|
* @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.
|
||||||
* L2CAP Information Response.
|
*/
|
||||||
* @param handle HCI Handle.
|
void L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t channelLow = 0x01, uint8_t channelHigh = 0x00);
|
||||||
* @param rxid Identifier.
|
/**
|
||||||
* @param infoTypeLow,infoTypeHigh Infotype.
|
* L2CAP Connection Request.
|
||||||
*/
|
* @param handle HCI handle.
|
||||||
void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh);
|
* @param rxid Identifier.
|
||||||
/**@}*/
|
* @param scid Source Channel Identifier.
|
||||||
|
* @param psm Protocol/Service Multiplexer - see: https://www.bluetooth.org/Technical/AssignedNumbers/logical_link.htm.
|
||||||
/** Use this to see if it is waiting for a incoming connection. */
|
*/
|
||||||
bool watingForConnection;
|
void l2cap_connection_request(uint16_t handle, uint8_t rxid, uint8_t* scid, uint16_t psm);
|
||||||
/** This is used by the service to know when to store the device information. */
|
/**
|
||||||
bool l2capConnectionClaimed;
|
* L2CAP Connection Response.
|
||||||
/** This is used by the SPP library to claim the current SDP incoming request. */
|
* @param handle HCI handle.
|
||||||
bool sdpConnectionClaimed;
|
* @param rxid Identifier.
|
||||||
/** This is used by the SPP library to claim the current RFCOMM incoming request. */
|
* @param dcid Destination Channel Identifier.
|
||||||
bool rfcommConnectionClaimed;
|
* @param scid Source Channel Identifier.
|
||||||
|
* @param result Result - First send ::PENDING and then ::SUCCESSFUL.
|
||||||
/** The name you wish to make the dongle show up as. It is set automatically by the SPP library. */
|
*/
|
||||||
const char* btdName;
|
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result);
|
||||||
/** The pin you wish to make the dongle use for authentication. It is set automatically by the SPP library. */
|
/**
|
||||||
const char* btdPin;
|
* L2CAP Config Request.
|
||||||
|
* @param handle HCI Handle.
|
||||||
/** The bluetooth dongles Bluetooth address. */
|
* @param rxid Identifier.
|
||||||
uint8_t my_bdaddr[6];
|
* @param dcid Destination Channel Identifier.
|
||||||
/** HCI handle for the last connection. */
|
*/
|
||||||
uint16_t hci_handle;
|
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t* dcid);
|
||||||
/** Last incoming devices Bluetooth address. */
|
/**
|
||||||
uint8_t disc_bdaddr[6];
|
* L2CAP Config Response.
|
||||||
/** First 30 chars of last remote name. */
|
* @param handle HCI Handle.
|
||||||
uint8_t remote_name[30];
|
* @param rxid Identifier.
|
||||||
/**
|
* @param scid Source Channel Identifier.
|
||||||
* The supported HCI Version read from the Bluetooth dongle.
|
*/
|
||||||
* Used by the PS3BT library to check the HCI Version of the Bluetooth dongle,
|
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t* scid);
|
||||||
* it should be at least 3 to work properly with the library.
|
/**
|
||||||
*/
|
* L2CAP Disconnection Request.
|
||||||
uint8_t hci_version;
|
* @param handle HCI Handle.
|
||||||
/** Call this function to pair with a Wiimote */
|
* @param rxid Identifier.
|
||||||
void pairWithWiimote() { pairWithWii = true; hci_state = HCI_CHECK_WII_SERVICE; };
|
* @param dcid Device Channel Identifier.
|
||||||
/** Used to only send the ACL data to the wiimote. */
|
* @param scid Source Channel Identifier.
|
||||||
bool connectToWii;
|
*/
|
||||||
/** True if a Wiimote is connecting. */
|
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid);
|
||||||
bool incomingWii;
|
/**
|
||||||
/** True when it should pair with the incoming Wiimote. */
|
* L2CAP Disconnection Response.
|
||||||
bool pairWithWii;
|
* @param handle HCI Handle.
|
||||||
/** True if it's the new Wiimote with the Motion Plus Inside or a Wii U Pro Controller. */
|
* @param rxid Identifier.
|
||||||
bool motionPlusInside;
|
* @param dcid Device Channel Identifier.
|
||||||
/** True if it's a Wii U Pro Controller. */
|
* @param scid Source Channel Identifier.
|
||||||
bool wiiUProController;
|
*/
|
||||||
|
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;
|
||||||
|
/** This is used by the service to know when to store the device information. */
|
||||||
|
bool l2capConnectionClaimed;
|
||||||
|
/** 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;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
||||||
|
|
360
PS3BT.h
360
PS3BT.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -60,187 +60,187 @@
|
||||||
/**
|
/**
|
||||||
* This BluetoothService class implements support for all the official PS3 Controllers:
|
* This BluetoothService class implements support for all the official PS3 Controllers:
|
||||||
* Dualshock 3, Navigation or a Motion controller via Bluetooth.
|
* Dualshock 3, Navigation or a Motion controller via Bluetooth.
|
||||||
*
|
*
|
||||||
* Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
|
* Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
|
||||||
*/
|
*/
|
||||||
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
|
269
PS3Enums.h
269
PS3Enums.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -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
|
|
||||||
0x0200, // R2
|
|
||||||
0x0400, // L1
|
|
||||||
0x0800, // R1
|
|
||||||
|
|
||||||
0x1000, // TRIANGLE
|
0x0100, // L2
|
||||||
0x2000, // CIRCLE
|
0x0200, // R2
|
||||||
0x4000, // CROSS
|
0x0400, // L1
|
||||||
0x8000, // SQUARE
|
0x0800, // R1
|
||||||
|
|
||||||
0x010000, // PS
|
0x1000, // TRIANGLE
|
||||||
0x080000, // MOVE - covers 12 bits - we only need to read the top 8
|
0x2000, // CIRCLE
|
||||||
0x100000 // T - covers 12 bits - we only need to read the top 8
|
0x4000, // CROSS
|
||||||
|
0x8000, // SQUARE
|
||||||
|
|
||||||
|
0x010000, // PS
|
||||||
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,122 +72,125 @@ 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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sensors inside the Sixaxis Dualshock 3 and Move controller.
|
* Sensors inside the Sixaxis Dualshock 3 and Move controller.
|
||||||
*
|
*
|
||||||
* <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 {
|
|
||||||
RumbleHigh = 0x10,
|
enum Rumble {
|
||||||
RumbleLow = 0x20,
|
RumbleHigh = 0x10,
|
||||||
|
RumbleLow = 0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
808
PS3USB.cpp
808
PS3USB.cpp
|
@ -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;
|
||||||
}
|
}
|
366
PS3USB.h
366
PS3USB.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -56,193 +56,199 @@
|
||||||
/**
|
/**
|
||||||
* This class implements support for all the official PS3 Controllers:
|
* This class implements support for all the official PS3 Controllers:
|
||||||
* Dualshock 3, Navigation or a Motion controller via USB.
|
* Dualshock 3, Navigation or a Motion controller via USB.
|
||||||
*
|
*
|
||||||
* One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB on the Move controller.
|
* One can only set the color of the bulb, set the rumble, set and get the bluetooth address and calibrate the magnetometer via USB on the Move controller.
|
||||||
*
|
*
|
||||||
* Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
|
* Information about the protocol can be found at the wiki: https://github.com/felis/USB_Host_Shield_2.0/wiki/PS3-Information.
|
||||||
*/
|
*/
|
||||||
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 */
|
|
||||||
/**
|
|
||||||
* Initialize the PS3 Controller.
|
|
||||||
* @param parent Hub number.
|
|
||||||
* @param port Port number on the hub.
|
|
||||||
* @param lowspeed Speed of the device.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
|
||||||
/**
|
|
||||||
* Release the USB device.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
virtual uint8_t Release();
|
|
||||||
/**
|
|
||||||
* Poll the USB Input endpoins and run the state machines.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
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 USBDeviceConfig implementation */
|
||||||
* Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller.
|
/**
|
||||||
* @param BDADDR Your dongles Bluetooth address.
|
* Initialize the PS3 Controller.
|
||||||
*/
|
* @param parent Hub number.
|
||||||
void setBdaddr(uint8_t* BDADDR);
|
* @param port Port number on the hub.
|
||||||
/**
|
* @param lowspeed Speed of the device.
|
||||||
* Used to set the Bluetooth address inside the Move controller.
|
* @return 0 on success.
|
||||||
* @param BDADDR Your dongles Bluetooth address.
|
*/
|
||||||
*/
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
void setMoveBdaddr(uint8_t* BDADDR);
|
/**
|
||||||
|
* Release the USB device.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
|
virtual uint8_t Release();
|
||||||
|
/**
|
||||||
|
* Poll the USB Input endpoins and run the state machines.
|
||||||
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
|
virtual uint8_t Poll();
|
||||||
|
|
||||||
/** @name PS3 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).
|
|
||||||
*/
|
|
||||||
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 check if the controller has been initialized.
|
||||||
/** Turn off ::Rumble. */
|
* @return True if it's ready.
|
||||||
void setRumbleOff();
|
*/
|
||||||
/**
|
virtual bool isReady() {
|
||||||
* Turn on ::Rumble.
|
return bPollEnable;
|
||||||
* @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;
|
* Used to set the Bluetooth address inside the Dualshock 3 and Navigation controller.
|
||||||
/** Variable used to indicate if the move controller is successfully connected. */
|
* @param BDADDR Your dongles Bluetooth address.
|
||||||
bool PS3MoveConnected;
|
*/
|
||||||
/** Variable used to indicate if the navigation controller is successfully connected. */
|
void setBdaddr(uint8_t* BDADDR);
|
||||||
bool PS3NavigationConnected;
|
/**
|
||||||
|
* Used to set the Bluetooth address inside the Move controller.
|
||||||
protected:
|
* @param BDADDR Your dongles Bluetooth address.
|
||||||
/** Pointer to USB class instance. */
|
*/
|
||||||
USB *pUsb;
|
void setMoveBdaddr(uint8_t* BDADDR);
|
||||||
/** Device address. */
|
|
||||||
uint8_t bAddress;
|
|
||||||
/** Endpoint info structure. */
|
|
||||||
EpInfo epInfo[PS3_MAX_ENDPOINTS];
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool bPollEnable;
|
|
||||||
|
|
||||||
uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values
|
|
||||||
|
|
||||||
uint32_t ButtonState;
|
/** @name PS3 Controller functions */
|
||||||
uint32_t OldButtonState;
|
/**
|
||||||
uint32_t ButtonClickState;
|
* getButtonPress(Button b) will return true as long as the button is held down.
|
||||||
|
*
|
||||||
uint8_t my_bdaddr[6]; // Change to your dongles Bluetooth address in the constructor
|
* While getButtonClick(Button b) will only return it once.
|
||||||
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
|
*
|
||||||
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
|
* 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).
|
||||||
void readReport(); // read incoming data
|
*/
|
||||||
void printReport(); // print incoming date - Uncomment for debugging
|
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();
|
||||||
|
|
||||||
/* Private commands */
|
/** Used to set all LEDs and ::Rumble off. */
|
||||||
void PS3_Command(uint8_t* data, uint16_t nbytes);
|
void setAllOff();
|
||||||
void enable_sixaxis(); // Command used to enable the Dualshock 3 and Navigation controller to send data via USB
|
/** Turn off ::Rumble. */
|
||||||
void Move_Command(uint8_t* data, uint16_t nbytes);
|
void setRumbleOff();
|
||||||
|
/**
|
||||||
|
* 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:
|
||||||
|
/** Pointer to USB class instance. */
|
||||||
|
USB *pUsb;
|
||||||
|
/** Device address. */
|
||||||
|
uint8_t bAddress;
|
||||||
|
/** Endpoint info structure. */
|
||||||
|
EpInfo epInfo[PS3_MAX_ENDPOINTS];
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool bPollEnable;
|
||||||
|
|
||||||
|
uint32_t timer; // used to continuously set PS3 Move controller Bulb and rumble values
|
||||||
|
|
||||||
|
uint32_t ButtonState;
|
||||||
|
uint32_t OldButtonState;
|
||||||
|
uint32_t ButtonClickState;
|
||||||
|
|
||||||
|
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 writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
|
||||||
|
|
||||||
|
void readReport(); // read incoming data
|
||||||
|
void printReport(); // print incoming date - Uncomment for debugging
|
||||||
|
|
||||||
|
/* Private commands */
|
||||||
|
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 Move_Command(uint8_t* data, uint16_t nbytes);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
550
SPP.h
550
SPP.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
|
|
||||||
#define extendAddress 0x01 // Allways 1
|
#define extendAddress 0x01 // Allways 1
|
||||||
|
|
||||||
// Multiplexer message types
|
// Multiplexer message types
|
||||||
#define BT_RFCOMM_PN_CMD 0x83
|
#define BT_RFCOMM_PN_CMD 0x83
|
||||||
#define BT_RFCOMM_PN_RSP 0x81
|
#define BT_RFCOMM_PN_RSP 0x81
|
||||||
#define BT_RFCOMM_MSC_CMD 0xE3
|
#define BT_RFCOMM_MSC_CMD 0xE3
|
||||||
|
@ -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. */
|
|
||||||
bool connected;
|
|
||||||
|
|
||||||
/** @name Serial port profile (SPP) Print functions */
|
|
||||||
/**
|
|
||||||
* Used to send Arduino String data type.
|
|
||||||
* @param str String to send.
|
|
||||||
*/
|
|
||||||
void print(const String &str);
|
|
||||||
/**
|
|
||||||
* Same as print(const String &str), but will include newline and carriage return.
|
|
||||||
* @param str String to send.
|
|
||||||
*/
|
|
||||||
void println(const String &str);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to send standard strings.
|
|
||||||
* @param str String to send.
|
|
||||||
*/
|
|
||||||
void print(const char* str);
|
|
||||||
/**
|
|
||||||
* Same as print(const char* str), but will include newline and carriage return.
|
|
||||||
* @param str String to send.
|
|
||||||
*/
|
|
||||||
void println(const char* str);
|
|
||||||
|
|
||||||
/**
|
/** Variable used to indicate if the connection is established. */
|
||||||
* Used to send single bytes.
|
bool connected;
|
||||||
* @param data Data to send.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
void println(uint8_t data);
|
|
||||||
|
|
||||||
/**
|
/** @name Serial port profile (SPP) Print functions */
|
||||||
* Used to send arrays.
|
/**
|
||||||
* @param array Array to send.
|
* Used to send Arduino String data type.
|
||||||
* @param length Number of bytes to send.
|
* @param str String to send.
|
||||||
*/
|
*/
|
||||||
void print(uint8_t* array, uint8_t length);
|
void print(const String &str);
|
||||||
/**
|
/**
|
||||||
* Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return.
|
* Same as print(const String &str), but will include newline and carriage return.
|
||||||
* @param array Array to send.
|
* @param str String to send.
|
||||||
* @param length Number of bytes to send.
|
*/
|
||||||
*/
|
void println(const String &str);
|
||||||
void println(uint8_t* array, uint8_t length);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to print strings stored in flash.
|
* Used to send standard strings.
|
||||||
* Use "SerialBT.print(F("String"));" to print a string stored in flash.
|
* @param str String to send.
|
||||||
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
|
*/
|
||||||
*/
|
void print(const char* str);
|
||||||
void print(const __FlashStringHelper *ifsh) { printFlashString(ifsh,false); };
|
/**
|
||||||
/**
|
* Same as print(const char* str), but will include newline and carriage return.
|
||||||
* Same as print(const __FlashStringHelper *ifsh), but will include newline and carriage return.
|
* @param str String to send.
|
||||||
* @param ifsh String to send - see: http://playground.arduino.cc/Learning/Memory.
|
*/
|
||||||
*/
|
void println(const char* str);
|
||||||
void println(const __FlashStringHelper *ifsh) { printFlashString(ifsh,true); };
|
|
||||||
/**
|
/**
|
||||||
* Helper function to print a string stored in flash.
|
* Used to send single bytes.
|
||||||
* @param ifsh String stored in flash you want to print.
|
* @param data Data to send.
|
||||||
* @param newline Set this to true to include newline and carriage return.
|
*/
|
||||||
*/
|
void print(uint8_t data) {
|
||||||
void printFlashString(const __FlashStringHelper *ifsh, bool newline);
|
print(&data, 1);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Same as print(uint8_t data), but will include newline and carriage return.
|
||||||
|
* @param data Data to send.
|
||||||
|
*/
|
||||||
|
void println(uint8_t data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to send arrays.
|
||||||
|
* @param array Array to send.
|
||||||
|
* @param length Number of bytes to send.
|
||||||
|
*/
|
||||||
|
void print(uint8_t* array, uint8_t length);
|
||||||
|
/**
|
||||||
|
* Same as print(uint8_t* array, uint8_t length), but will include newline and carriage return.
|
||||||
|
* @param array Array to send.
|
||||||
|
* @param length Number of bytes to send.
|
||||||
|
*/
|
||||||
|
void println(uint8_t* array, uint8_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to print strings 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.
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 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.
|
|
||||||
* @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.
|
* Same as printNumber(int8_t n), but will include newline and carriage return.
|
||||||
* @param input Unsigned integer to convert.
|
* @param n Signed integer to send.
|
||||||
* @param output Output buffer.
|
*/
|
||||||
*/
|
void printNumberln(int8_t n) {
|
||||||
void intToString(int32_t input, char* output);
|
printNumberln((int32_t) n);
|
||||||
/**
|
};
|
||||||
* Helper function to convert from a signed integer to a string.
|
|
||||||
* @param input Signed integer to convert.
|
/**
|
||||||
* @param output Output buffer.
|
* Used to print unsigned integers.
|
||||||
*/
|
* @param n Unsigned integer to send.
|
||||||
void intToString(uint32_t input, char* output);
|
*/
|
||||||
|
void printNumber(uint16_t n) {
|
||||||
|
printNumber((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.
|
||||||
|
* @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;
|
||||||
|
};
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 */
|
|
||||||
bool SDPConnected;
|
|
||||||
bool RFCOMMConnected;
|
|
||||||
|
|
||||||
uint16_t hci_handle; // The HCI Handle for the connection
|
|
||||||
|
|
||||||
/* Variables used by L2CAP state maschines */
|
|
||||||
uint8_t l2cap_sdp_state;
|
|
||||||
uint8_t l2cap_rfcomm_state;
|
|
||||||
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 rfcommbuf[10]; // Buffer for RFCOMM Commands
|
|
||||||
|
|
||||||
/* L2CAP Channels */
|
|
||||||
uint8_t sdp_scid[2]; // L2CAP source CID for SDP
|
|
||||||
uint8_t sdp_dcid[2]; // 0x0050
|
|
||||||
uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM
|
|
||||||
uint8_t rfcomm_dcid[2]; // 0x0051
|
|
||||||
uint8_t identifier; // Identifier for command
|
|
||||||
|
|
||||||
/* RFCOMM Variables */
|
/* Set true when a channel is created */
|
||||||
uint8_t rfcommChannel;
|
bool SDPConnected;
|
||||||
uint8_t rfcommChannelConnection; // This is the channel the SPP chanel will be running at
|
bool RFCOMMConnected;
|
||||||
uint8_t rfcommDirection;
|
|
||||||
uint8_t rfcommCommandResponse;
|
uint16_t hci_handle; // The HCI Handle for the connection
|
||||||
uint8_t rfcommChannelType;
|
|
||||||
uint8_t rfcommPfBit;
|
/* Variables used by L2CAP state maschines */
|
||||||
|
uint8_t l2cap_sdp_state;
|
||||||
unsigned long timer;
|
uint8_t l2cap_rfcomm_state;
|
||||||
bool waitForLastCommand;
|
uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events
|
||||||
bool creditSent;
|
|
||||||
|
uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
|
||||||
uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
|
uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
|
||||||
uint8_t rfcommAvailable;
|
|
||||||
|
/* L2CAP Channels */
|
||||||
bool firstMessage; // Used to see if it's the first SDP request received
|
uint8_t sdp_scid[2]; // L2CAP source CID for SDP
|
||||||
uint8_t bytesRead; // Counter to see when it's time to send more credit
|
uint8_t sdp_dcid[2]; // 0x0050
|
||||||
|
uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM
|
||||||
/* State machines */
|
uint8_t rfcomm_dcid[2]; // 0x0051
|
||||||
void SDP_task(); // SDP state machine
|
uint8_t identifier; // Identifier for command
|
||||||
void RFCOMM_task(); // RFCOMM state machine
|
|
||||||
|
/* RFCOMM Variables */
|
||||||
/* SDP Commands */
|
uint8_t rfcommChannel;
|
||||||
void SDP_Command(uint8_t* data, uint8_t nbytes);
|
uint8_t rfcommChannelConnection; // This is the channel the SPP chanel will be running at
|
||||||
void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
uint8_t rfcommDirection;
|
||||||
void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
uint8_t rfcommCommandResponse;
|
||||||
void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
uint8_t rfcommChannelType;
|
||||||
void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
uint8_t rfcommPfBit;
|
||||||
void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
|
||||||
|
unsigned long timer;
|
||||||
/* RFCOMM Commands */
|
bool waitForLastCommand;
|
||||||
void RFCOMM_Command(uint8_t* data, uint8_t nbytes);
|
bool creditSent;
|
||||||
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);
|
uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
|
||||||
uint8_t calcFcs(uint8_t *data);
|
uint8_t rfcommAvailable;
|
||||||
uint8_t __crc(uint8_t* data);
|
|
||||||
|
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
|
||||||
|
|
||||||
|
/* State machines */
|
||||||
|
void SDP_task(); // SDP state machine
|
||||||
|
void RFCOMM_task(); // RFCOMM state machine
|
||||||
|
|
||||||
|
/* SDP Commands */
|
||||||
|
void SDP_Command(uint8_t* data, uint8_t nbytes);
|
||||||
|
void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
||||||
|
void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
||||||
|
void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
||||||
|
void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
||||||
|
void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
|
||||||
|
|
||||||
|
/* RFCOMM Commands */
|
||||||
|
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 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 __crc(uint8_t* data);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
8
Usb.cpp
8
Usb.cpp
|
@ -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
20
Usb.h
|
@ -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)
|
||||||
|
|
701
Wii.h
701
Wii.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
#define L2CAP_CONTROL_CONNECT_REQUEST 3
|
#define L2CAP_CONTROL_CONNECT_REQUEST 3
|
||||||
#define L2CAP_CONTROL_CONFIG_REQUEST 4
|
#define L2CAP_CONTROL_CONFIG_REQUEST 4
|
||||||
#define L2CAP_INTERRUPT_CONNECT_REQUEST 5
|
#define L2CAP_INTERRUPT_CONNECT_REQUEST 5
|
||||||
|
|
||||||
#define L2CAP_INTERRUPT_CONFIG_REQUEST 6
|
#define L2CAP_INTERRUPT_CONFIG_REQUEST 6
|
||||||
|
|
||||||
#define L2CAP_CHECK_MOTION_PLUS_STATE 7
|
#define L2CAP_CHECK_MOTION_PLUS_STATE 7
|
||||||
|
@ -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();
|
|
||||||
/** Turn off rumble. */
|
|
||||||
void setRumbleOff();
|
|
||||||
/** Turn on rumble. */
|
|
||||||
void setRumbleOn();
|
|
||||||
/** 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.
|
* Roll calculated from the Wiimote. A complimentary filter is used if the Motion Plus is connected.
|
||||||
* @return The battery level in the range 0-255.
|
* @return Roll in the range from 0-360.
|
||||||
*/
|
*/
|
||||||
uint8_t getBatteryLevel() { return batteryLevel; };
|
double getRoll() {
|
||||||
/**
|
return roll;
|
||||||
* Return the Wiimote state.
|
};
|
||||||
* @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.
|
|
||||||
*/
|
|
||||||
uint8_t getWiiState() { return wiiState; };
|
|
||||||
/**@}*/
|
|
||||||
|
|
||||||
/**@{*/
|
/**
|
||||||
/** Variable used to indicate if a Wiimote is connected. */
|
* This is the yaw calculated by the gyro.
|
||||||
bool wiimoteConnected;
|
*
|
||||||
/** Variable used to indicate if a Nunchuck controller is connected. */
|
* <B>NOTE:</B> This angle will drift a lot and is only available if the Motion Plus extension is connected.
|
||||||
bool nunchuckConnected;
|
* @return The angle calculated using the gyro.
|
||||||
/** Variable used to indicate if a Nunchuck controller is connected. */
|
*/
|
||||||
bool motionPlusConnected;
|
double getYaw() {
|
||||||
/** Variable used to indicate if a Wii U Pro controller is connected. */
|
return gyroYaw;
|
||||||
bool wiiUProControllerConnected;
|
};
|
||||||
/**@}*/
|
|
||||||
|
|
||||||
/* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
|
|
||||||
|
|
||||||
/**@{*/
|
|
||||||
/** Pitch and roll calculated from the accelerometer inside the Wiimote. */
|
|
||||||
double wiimotePitch;
|
|
||||||
double wiimoteRoll;
|
|
||||||
/**@}*/
|
|
||||||
|
|
||||||
/**@{*/
|
/** Used to set all LEDs and rumble off. */
|
||||||
/** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
|
void setAllOff();
|
||||||
double nunchuckPitch;
|
/** Turn off rumble. */
|
||||||
double nunchuckRoll;
|
void setRumbleOff();
|
||||||
/**@}*/
|
/** Turn on rumble. */
|
||||||
|
void setRumbleOn();
|
||||||
|
/** 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();
|
||||||
|
|
||||||
/**@{*/
|
/**
|
||||||
/** Accelerometer values used to calculate pitch and roll. */
|
* Return the battery level of the Wiimote.
|
||||||
int16_t accX;
|
* @return The battery level in the range 0-255.
|
||||||
int16_t accY;
|
*/
|
||||||
int16_t accZ;
|
uint8_t getBatteryLevel() {
|
||||||
/**@}*/
|
return batteryLevel;
|
||||||
|
};
|
||||||
|
|
||||||
/* Variables for the gyro inside the Motion Plus */
|
/**
|
||||||
/** This is the pitch calculated by the gyro - use this to tune WII#pitchGyroScale. */
|
* Return the Wiimote state.
|
||||||
double gyroPitch;
|
* @return See: http://wiibrew.org/wiki/Wiimote#0x20:_Status.
|
||||||
/** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
|
*/
|
||||||
double gyroRoll;
|
uint8_t getWiiState() {
|
||||||
/** This is the yaw calculated by the gyro - use this to tune WII#yawGyroScale. */
|
return wiiState;
|
||||||
double gyroYaw;
|
};
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
/**@{*/
|
/**@{*/
|
||||||
/** The speed in deg/s from the gyro. */
|
/** Variable used to indicate if a Wiimote is connected. */
|
||||||
double pitchGyroSpeed;
|
bool wiimoteConnected;
|
||||||
double rollGyroSpeed;
|
/** Variable used to indicate if a Nunchuck controller is connected. */
|
||||||
double yawGyroSpeed;
|
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. */
|
||||||
/** You might need to fine-tune these values. */
|
bool wiiUProControllerConnected;
|
||||||
uint16_t pitchGyroScale;
|
/**@}*/
|
||||||
uint16_t rollGyroScale;
|
|
||||||
uint16_t yawGyroScale;
|
/* IMU Data, might be usefull if you need to do something more advanced than just calculating the angle */
|
||||||
/**@}*/
|
|
||||||
|
/**@{*/
|
||||||
/**@{*/
|
/** Pitch and roll calculated from the accelerometer inside the Wiimote. */
|
||||||
/** Raw value read directly from the Motion Plus. */
|
double wiimotePitch;
|
||||||
int16_t gyroYawRaw;
|
double wiimoteRoll;
|
||||||
int16_t gyroRollRaw;
|
/**@}*/
|
||||||
int16_t gyroPitchRaw;
|
|
||||||
/**@}*/
|
/**@{*/
|
||||||
|
/** Pitch and roll calculated from the accelerometer inside the Nunchuck. */
|
||||||
/**@{*/
|
double nunchuckPitch;
|
||||||
/** These values are set when the controller is first initialized. */
|
double nunchuckRoll;
|
||||||
int16_t gyroYawZero;
|
/**@}*/
|
||||||
int16_t gyroRollZero;
|
|
||||||
int16_t gyroPitchZero;
|
/**@{*/
|
||||||
/**@}*/
|
/** 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. */
|
||||||
|
double gyroPitch;
|
||||||
|
/** This is the roll calculated by the gyro - use this to tune WII#rollGyroScale. */
|
||||||
|
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. */
|
||||||
|
double pitchGyroSpeed;
|
||||||
|
double rollGyroSpeed;
|
||||||
|
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
|
|
||||||
|
|
||||||
/* Variables filled from HCI event management */
|
|
||||||
uint16_t hci_handle;
|
|
||||||
bool activeConnection; // Used to indicate if it's already has established a connection
|
|
||||||
|
|
||||||
/* variables used by high level L2CAP task */
|
|
||||||
uint8_t l2cap_state;
|
|
||||||
uint16_t l2cap_event_flag;// l2cap flags of received bluetooth events
|
|
||||||
|
|
||||||
uint32_t ButtonState;
|
|
||||||
uint32_t OldButtonState;
|
|
||||||
uint32_t ButtonClickState;
|
|
||||||
uint16_t hatValues[4];
|
|
||||||
|
|
||||||
uint8_t HIDBuffer[3];// Used to store HID commands
|
|
||||||
|
|
||||||
uint16_t stateCounter;
|
|
||||||
bool unknownExtensionConnected;
|
|
||||||
bool extensionConnected;
|
|
||||||
|
|
||||||
/* L2CAP Channels */
|
|
||||||
uint8_t control_scid[2]; // L2CAP source CID for HID_Control
|
|
||||||
uint8_t control_dcid[2]; // 0x0060
|
|
||||||
uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
|
|
||||||
uint8_t interrupt_dcid[2]; // 0x0061
|
|
||||||
uint8_t identifier; // Identifier for connection
|
|
||||||
|
|
||||||
/* HID Commands */
|
|
||||||
void HID_Command(uint8_t* data, uint8_t nbytes);
|
|
||||||
void setReportMode(bool continuous, uint8_t mode);
|
|
||||||
void statusRequest();
|
|
||||||
|
|
||||||
void writeData(uint32_t offset, uint8_t size, uint8_t* data);
|
|
||||||
void initExtension1();
|
|
||||||
void initExtension2();
|
|
||||||
|
|
||||||
void readData(uint32_t offset, uint16_t size, bool EEPROM);
|
|
||||||
void readExtensionType();
|
|
||||||
void readCalData();
|
|
||||||
|
|
||||||
void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote
|
|
||||||
void initMotionPlus();
|
|
||||||
void activateMotionPlus();
|
|
||||||
|
|
||||||
double pitch; // Fusioned angle using a complimentary filter if the Motion Plus is connected
|
void L2CAP_task(); // L2CAP state machine
|
||||||
double roll; // Fusioned angle using a complimentary filter if the Motion Plus is connected
|
|
||||||
|
/* Variables filled from HCI event management */
|
||||||
bool activateNunchuck;
|
uint16_t hci_handle;
|
||||||
bool motionValuesReset; // This bool is true when the gyro values has been reset
|
bool activeConnection; // Used to indicate if it's already has established a connection
|
||||||
unsigned long timer;
|
|
||||||
|
/* variables used by high level L2CAP task */
|
||||||
|
uint8_t l2cap_state;
|
||||||
|
uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events
|
||||||
|
|
||||||
|
uint32_t ButtonState;
|
||||||
|
uint32_t OldButtonState;
|
||||||
|
uint32_t ButtonClickState;
|
||||||
|
uint16_t hatValues[4];
|
||||||
|
|
||||||
|
uint8_t HIDBuffer[3]; // Used to store HID commands
|
||||||
|
|
||||||
|
uint16_t stateCounter;
|
||||||
|
bool unknownExtensionConnected;
|
||||||
|
bool extensionConnected;
|
||||||
|
|
||||||
|
/* L2CAP Channels */
|
||||||
|
uint8_t control_scid[2]; // L2CAP source CID for HID_Control
|
||||||
|
uint8_t control_dcid[2]; // 0x0060
|
||||||
|
uint8_t interrupt_scid[2]; // L2CAP source CID for HID_Interrupt
|
||||||
|
uint8_t interrupt_dcid[2]; // 0x0061
|
||||||
|
uint8_t identifier; // Identifier for connection
|
||||||
|
|
||||||
|
/* HID Commands */
|
||||||
|
void HID_Command(uint8_t* data, uint8_t nbytes);
|
||||||
|
void setReportMode(bool continuous, uint8_t mode);
|
||||||
|
void statusRequest();
|
||||||
|
|
||||||
|
void writeData(uint32_t offset, uint8_t size, uint8_t* data);
|
||||||
|
void initExtension1();
|
||||||
|
void initExtension2();
|
||||||
|
|
||||||
|
void readData(uint32_t offset, uint16_t size, bool EEPROM);
|
||||||
|
void readExtensionType();
|
||||||
|
void readCalData();
|
||||||
|
|
||||||
|
void checkMotionPresent(); // Used to see if a Motion Plus is connected to the Wiimote
|
||||||
|
void initMotionPlus();
|
||||||
|
void activateMotionPlus();
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
bool activateNunchuck;
|
||||||
|
bool motionValuesReset; // This bool is true when the gyro values has been reset
|
||||||
|
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 batteryLevel;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
#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
|
705
XBOXRECV.cpp
705
XBOXRECV.cpp
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
334
XBOXRECV.h
334
XBOXRECV.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Usb.h"
|
#include "Usb.h"
|
||||||
#include "xboxEnums.h"
|
#include "xboxEnums.h"
|
||||||
|
|
||||||
/* Data Xbox 360 taken from descriptors */
|
/* Data Xbox 360 taken from descriptors */
|
||||||
#define EP_MAXPKTSIZE 32 // max size for data via USB
|
#define EP_MAXPKTSIZE 32 // max size for data via USB
|
||||||
|
@ -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.
|
||||||
protected:
|
*
|
||||||
/** Pointer to USB class instance. */
|
* So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b),
|
||||||
USB *pUsb;
|
* but if you need to drive a robot forward you would use getButtonPress(uint8_t controller, Button b).
|
||||||
/** Device address. */
|
* @param controller The controller to read from.
|
||||||
uint8_t bAddress;
|
* @param b ::Button to read.
|
||||||
/** Endpoint info structure. */
|
* @return getButtonClick(uint8_t controller, Button b) will return a bool, but getButtonPress(uint8_t controller, Button b)
|
||||||
EpInfo epInfo[XBOX_MAX_ENDPOINTS];
|
* will return a byte if reading ::L2 or ::R2.
|
||||||
|
*/
|
||||||
private:
|
uint8_t getButtonPress(uint8_t controller, Button b);
|
||||||
bool bPollEnable;
|
bool getButtonClick(uint8_t controller, Button b);
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
/* Variables to store the buttons */
|
/** @name Xbox Controller functions */
|
||||||
uint32_t ButtonState[4];
|
/**
|
||||||
uint32_t OldButtonState[4];
|
* Return the analog value from the joysticks on the controller.
|
||||||
uint16_t ButtonClickState[4];
|
* @param controller The controller to read from.
|
||||||
int16_t hatValue[4][4];
|
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
|
||||||
uint16_t controllerStatus[4];
|
* @return Returns a signed 16-bit integer.
|
||||||
bool buttonStateChanged[4]; // True if a button has changed
|
*/
|
||||||
|
int16_t getAnalogHat(uint8_t controller, AnalogHat a);
|
||||||
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];
|
|
||||||
|
|
||||||
unsigned long timer; // Timing for checkStatus() signals
|
/**
|
||||||
|
* Turn rumble off and all the LEDs on the specific controller.
|
||||||
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
|
* @param controller The controller to write to.
|
||||||
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
|
*/
|
||||||
|
void setAllOff(uint8_t controller) {
|
||||||
void readReport(uint8_t controller); // read incoming data
|
setRumbleOn(controller, 0, 0);
|
||||||
void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging
|
setLedOff(controller);
|
||||||
|
};
|
||||||
|
|
||||||
/* Private commands */
|
/**
|
||||||
void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes);
|
* Turn rumble off the specific controller.
|
||||||
void checkStatus();
|
* @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:
|
||||||
|
/** Pointer to USB class instance. */
|
||||||
|
USB *pUsb;
|
||||||
|
/** Device address. */
|
||||||
|
uint8_t bAddress;
|
||||||
|
/** Endpoint info structure. */
|
||||||
|
EpInfo epInfo[XBOX_MAX_ENDPOINTS];
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool bPollEnable;
|
||||||
|
|
||||||
|
/* Variables to store the buttons */
|
||||||
|
uint32_t ButtonState[4];
|
||||||
|
uint32_t OldButtonState[4];
|
||||||
|
uint16_t ButtonClickState[4];
|
||||||
|
int16_t hatValue[4][4];
|
||||||
|
uint16_t controllerStatus[4];
|
||||||
|
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 R2Clicked[4];
|
||||||
|
|
||||||
|
unsigned long timer; // Timing for checkStatus() signals
|
||||||
|
|
||||||
|
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
|
||||||
|
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
|
||||||
|
|
||||||
|
void readReport(uint8_t controller); // read incoming data
|
||||||
|
void printReport(uint8_t controller, uint8_t nBytes); // print incoming date - Uncomment for debugging
|
||||||
|
|
||||||
|
/* Private commands */
|
||||||
|
void XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes);
|
||||||
|
void checkStatus();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
442
XBOXUSB.cpp
442
XBOXUSB.cpp
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
279
XBOXUSB.h
279
XBOXUSB.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Usb.h"
|
#include "Usb.h"
|
||||||
#include "xboxEnums.h"
|
#include "xboxEnums.h"
|
||||||
|
|
||||||
/* Data Xbox 360 taken from descriptors */
|
/* Data Xbox 360 taken from descriptors */
|
||||||
#define EP_MAXPKTSIZE 32 // max size for data via USB
|
#define EP_MAXPKTSIZE 32 // max size for data via USB
|
||||||
|
@ -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 */
|
|
||||||
/**
|
|
||||||
* Initialize the Xbox Controller.
|
|
||||||
* @param parent Hub number.
|
|
||||||
* @param port Port number on the hub.
|
|
||||||
* @param lowspeed Speed of the device.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
|
||||||
/**
|
|
||||||
* Release the USB device.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
virtual uint8_t Release();
|
|
||||||
/**
|
|
||||||
* Poll the USB Input endpoins and run the state machines.
|
|
||||||
* @return 0 on success.
|
|
||||||
*/
|
|
||||||
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 */
|
|
||||||
/**
|
|
||||||
* getButtonPress(Button b) will return true as long as the button is held down.
|
|
||||||
*
|
|
||||||
* 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),
|
|
||||||
* 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 */
|
/** @name USBDeviceConfig implementation */
|
||||||
/**
|
/**
|
||||||
* Return the analog value from the joysticks on the controller.
|
* Initialize the Xbox Controller.
|
||||||
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
|
* @param parent Hub number.
|
||||||
* @return Returns a signed 16-bit integer.
|
* @param port Port number on the hub.
|
||||||
*/
|
* @param lowspeed Speed of the device.
|
||||||
int16_t getAnalogHat(AnalogHat a);
|
* @return 0 on success.
|
||||||
|
*/
|
||||||
/** Turn rumble off and all the LEDs on the controller. */
|
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed);
|
||||||
void setAllOff() { setRumbleOn(0,0); setLedRaw(0); };
|
/**
|
||||||
/** Turn rumble off the controller. */
|
* Release the USB device.
|
||||||
void setRumbleOff() { setRumbleOn(0,0); };
|
* @return 0 on success.
|
||||||
/**
|
*/
|
||||||
* Turn rumble on.
|
virtual uint8_t Release();
|
||||||
* @param lValue Left motor (big weight) inside the controller.
|
/**
|
||||||
* @param rValue Right motor (small weight) inside the controller.
|
* Poll the USB Input endpoins and run the state machines.
|
||||||
*/
|
* @return 0 on success.
|
||||||
void setRumbleOn(uint8_t lValue, uint8_t rValue);
|
*/
|
||||||
/**
|
virtual uint8_t Poll();
|
||||||
* 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:
|
|
||||||
/** Pointer to USB class instance. */
|
|
||||||
USB *pUsb;
|
|
||||||
/** Device address. */
|
|
||||||
uint8_t bAddress;
|
|
||||||
/** Endpoint info structure. */
|
|
||||||
EpInfo epInfo[XBOX_MAX_ENDPOINTS];
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool bPollEnable;
|
|
||||||
|
|
||||||
/* Variables to store the buttons */
|
/**
|
||||||
uint32_t ButtonState;
|
* Get the device address.
|
||||||
uint32_t OldButtonState;
|
* @return The device address.
|
||||||
uint16_t ButtonClickState;
|
*/
|
||||||
int16_t hatValue[4];
|
virtual uint8_t GetAddress() {
|
||||||
uint16_t controllerStatus;
|
return bAddress;
|
||||||
|
};
|
||||||
bool L2Clicked; // These buttons are analog, so we use we use these bools to check if they where clicked or not
|
|
||||||
bool R2Clicked;
|
/**
|
||||||
|
* Used to check if the controller has been initialized.
|
||||||
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
|
* @return True if it's ready.
|
||||||
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
|
*/
|
||||||
|
virtual bool isReady() {
|
||||||
void readReport(); // read incoming data
|
return bPollEnable;
|
||||||
void printReport(); // print incoming date - Uncomment for debugging
|
};
|
||||||
|
/**@}*/
|
||||||
/* Private commands */
|
|
||||||
void XboxCommand(uint8_t* data, uint16_t nbytes);
|
/** @name Xbox Controller functions */
|
||||||
|
/**
|
||||||
|
* getButtonPress(Button b) will return true as long as the button is held down.
|
||||||
|
*
|
||||||
|
* 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),
|
||||||
|
* 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 */
|
||||||
|
/**
|
||||||
|
* 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:
|
||||||
|
/** Pointer to USB class instance. */
|
||||||
|
USB *pUsb;
|
||||||
|
/** Device address. */
|
||||||
|
uint8_t bAddress;
|
||||||
|
/** Endpoint info structure. */
|
||||||
|
EpInfo epInfo[XBOX_MAX_ENDPOINTS];
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool bPollEnable;
|
||||||
|
|
||||||
|
/* Variables to store the buttons */
|
||||||
|
uint32_t ButtonState;
|
||||||
|
uint32_t OldButtonState;
|
||||||
|
uint16_t ButtonClickState;
|
||||||
|
int16_t hatValue[4];
|
||||||
|
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 R2Clicked;
|
||||||
|
|
||||||
|
uint8_t readBuf[EP_MAXPKTSIZE]; // General purpose buffer for input data
|
||||||
|
uint8_t writeBuf[EP_MAXPKTSIZE]; // General purpose buffer for output data
|
||||||
|
|
||||||
|
void readReport(); // read incoming data
|
||||||
|
void printReport(); // print incoming date - Uncomment for debugging
|
||||||
|
|
||||||
|
/* Private commands */
|
||||||
|
void XboxCommand(uint8_t* data, uint16_t nbytes);
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
52
address.h
52
address.h
|
@ -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
15
adk.cpp
|
@ -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
6
adk.h
|
@ -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_
|
10
avrpins.h
10
avrpins.h
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
12
cdcacm.cpp
12
cdcacm.cpp
|
@ -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) {
|
||||||
|
|
12
cdcftdi.cpp
12
cdcftdi.cpp
|
@ -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++;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2013 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -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,
|
|
||||||
R2 = 9,
|
|
||||||
L1 = 10,
|
|
||||||
R1 = 11,
|
|
||||||
TRIANGLE = 12,
|
|
||||||
CIRCLE = 13,
|
|
||||||
CROSS = 14,
|
|
||||||
SQUARE = 15,
|
|
||||||
|
|
||||||
PS = 16,
|
|
||||||
|
|
||||||
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
|
|
||||||
/**@}*/
|
|
||||||
|
|
||||||
/**@{*/
|
L2 = 8,
|
||||||
/** Xbox buttons */
|
R2 = 9,
|
||||||
BACK = 4,
|
L1 = 10,
|
||||||
X = 14,
|
R1 = 11,
|
||||||
Y = 15,
|
TRIANGLE = 12,
|
||||||
XBOX = 16,
|
CIRCLE = 13,
|
||||||
SYNC = 17,
|
CROSS = 14,
|
||||||
/**@}*/
|
SQUARE = 15,
|
||||||
|
|
||||||
|
PS = 16,
|
||||||
|
|
||||||
|
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
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/**@{*/
|
||||||
|
/** Xbox buttons */
|
||||||
|
BACK = 4,
|
||||||
|
X = 14,
|
||||||
|
Y = 15,
|
||||||
|
XBOX = 16,
|
||||||
|
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
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
2
hid.cpp
2
hid.cpp
|
@ -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;
|
||||||
|
|
12
hidboot.cpp
12
hidboot.cpp
|
@ -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);
|
||||||
|
|
60
hidboot.h
60
hidboot.h
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
12
masstorage.h
12
masstorage.h
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
12
parsetools.h
12
parsetools.h
|
@ -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 {
|
||||||
|
|
22
printhex.h
22
printhex.h
|
@ -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;
|
||||||
|
|
12
usb_ch9.h
12
usb_ch9.h
|
@ -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_
|
||||||
|
|
56
usbhost.h
56
usbhost.h
|
@ -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()
|
||||||
|
|
14
usbhub.cpp
14
usbhub.cpp
|
@ -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)
|
||||||
|
|
24
usbhub.h
24
usbhub.h
|
@ -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);
|
||||||
|
|
62
xboxEnums.h
62
xboxEnums.h
|
@ -1,15 +1,15 @@
|
||||||
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
|
||||||
|
|
||||||
This software may be distributed and modified under the terms of the GNU
|
This software may be distributed and modified under the terms of the GNU
|
||||||
General Public License version 2 (GPL2) as published by the Free Software
|
General Public License version 2 (GPL2) as published by the Free Software
|
||||||
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
Foundation and appearing in the file GPL2.TXT included in the packaging of
|
||||||
this file. Please note that GPL2 Section 2[b] requires that all works based
|
this file. Please note that GPL2 Section 2[b] requires that all works based
|
||||||
on this software must also be made publicly available under the terms of
|
on this software must also be made publicly available under the terms of
|
||||||
the GPL2 ("Copyleft").
|
the GPL2 ("Copyleft").
|
||||||
|
|
||||||
Contact information
|
Contact information
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Kristian Lauszus, TKJ Electronics
|
Kristian Lauszus, TKJ Electronics
|
||||||
Web : http://www.tkjelectronics.com
|
Web : http://www.tkjelectronics.com
|
||||||
e-mail : kristianl@tkjelectronics.com
|
e-mail : kristianl@tkjelectronics.com
|
||||||
|
@ -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
|
Loading…
Reference in a new issue