2012-05-26 01:48:12 +02:00
/* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2013-03-28 09:37:09 +01:00
2012-05-26 01:48:12 +02:00
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
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
on this software must also be made publicly available under the terms of
the GPL2 ( " Copyleft " ) .
2013-03-28 09:37:09 +01:00
2012-05-26 01:48:12 +02:00
Contact information
- - - - - - - - - - - - - - - - - - -
2013-03-28 09:37:09 +01:00
2012-05-26 01:48:12 +02:00
Kristian Lauszus , TKJ Electronics
Web : http : //www.tkjelectronics.com
e - mail : kristianl @ tkjelectronics . com
*/
# include "PS3USB.h"
2013-11-11 11:48:09 +01:00
// To enable serial debugging see "settings.h"
2012-05-26 01:48:12 +02:00
//#define EXTRADEBUG // Uncomment to get even more debugging data
//#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers
2013-03-28 09:46:43 +01:00
PS3USB : : PS3USB ( USB * p , uint8_t btadr5 , uint8_t btadr4 , uint8_t btadr3 , uint8_t btadr2 , uint8_t btadr1 , uint8_t btadr0 ) :
2012-05-26 01:48:12 +02:00
pUsb ( p ) , // pointer to USB class instance - mandatory
bAddress ( 0 ) , // device address - mandatory
bPollEnable ( false ) // don't start polling before dongle is connected
{
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < PS3_MAX_ENDPOINTS ; i + + ) {
2013-03-28 09:46:43 +01:00
epInfo [ i ] . epAddr = 0 ;
epInfo [ i ] . maxPktSize = ( i ) ? 0 : 8 ;
epInfo [ i ] . epAttribs = 0 ;
epInfo [ i ] . bmNakPower = ( i ) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER ;
}
2013-12-25 11:09:57 +01:00
if ( pUsb ) // register in USB subsystem
2013-03-28 09:46:43 +01:00
pUsb - > RegisterDeviceClass ( this ) ; //set devConfig[] entry
my_bdaddr [ 5 ] = btadr5 ; // Change to your dongle's Bluetooth address instead
my_bdaddr [ 4 ] = btadr4 ;
my_bdaddr [ 3 ] = btadr3 ;
my_bdaddr [ 2 ] = btadr2 ;
my_bdaddr [ 1 ] = btadr1 ;
my_bdaddr [ 0 ] = btadr0 ;
2012-05-26 01:48:12 +02:00
}
2012-08-04 19:08:43 +02:00
uint8_t PS3USB : : Init ( uint8_t parent , uint8_t port , bool lowspeed ) {
2013-03-28 09:46:43 +01:00
uint8_t buf [ sizeof ( USB_DEVICE_DESCRIPTOR ) ] ;
2013-12-05 00:40:23 +01:00
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast < USB_DEVICE_DESCRIPTOR * > ( buf ) ;
2013-03-28 09:46:43 +01:00
uint8_t rcode ;
UsbDevice * p = NULL ;
EpInfo * oldep_ptr = NULL ;
uint16_t PID ;
uint16_t VID ;
// get memory address of USB device address pool
AddressPool & addrPool = pUsb - > GetAddressPool ( ) ;
2012-05-26 01:48:12 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n PS3USB Init " ) , 0x80 ) ;
2012-05-26 01:48:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
// check if address has already been assigned to an instance
2013-12-25 11:09:57 +01:00
if ( bAddress ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Address in use " ) , 0x80 ) ;
2012-05-26 01:48:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE ;
}
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
// Get pointer to pseudo device with address 0 assigned
p = addrPool . GetUsbDevicePtr ( 0 ) ;
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( ! p ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Address not found " ) , 0x80 ) ;
2012-05-26 01:48:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL ;
}
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( ! p - > epinfo ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n epinfo is null " ) , 0x80 ) ;
2012-05-26 01:48:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
return USB_ERROR_EPINFO_IS_NULL ;
}
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
// Save old pointer to EP_RECORD of address 0
oldep_ptr = p - > epinfo ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
// Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
p - > epinfo = epInfo ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
p - > lowspeed = lowspeed ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
// 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 ;
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-28 09:46:43 +01:00
goto FailGetDevDescr ;
2013-03-28 09:37:09 +01:00
2013-12-05 00:40:23 +01:00
VID = udd - > idVendor ;
PID = udd - > idProduct ;
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( VID ! = PS3_VID | | ( PID ! = PS3_PID & & PID ! = PS3NAVIGATION_PID & & PID ! = PS3MOVE_PID ) )
2013-03-28 09:46:43 +01:00
goto FailUnknownDevice ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
// Allocate new address according to device class
bAddress = addrPool . AllocAddress ( parent , false , port ) ;
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( ! bAddress )
2013-03-28 09:46:43 +01:00
return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
// Extract Max Packet Size from device descriptor
2013-12-05 00:40:23 +01:00
epInfo [ 0 ] . maxPktSize = udd - > bMaxPacketSize0 ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
// Assign new address to the device
rcode = pUsb - > setAddr ( 0 , 0 , bAddress ) ;
2013-12-25 11:09:57 +01:00
if ( rcode ) {
2013-03-28 09:46:43 +01:00
p - > lowspeed = false ;
addrPool . FreeAddress ( bAddress ) ;
bAddress = 0 ;
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n setAddr: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( rcode , 0x80 ) ;
2013-07-20 12:57:23 +02:00
# endif
2013-03-28 09:46:43 +01:00
return rcode ;
}
2012-05-26 01:48:12 +02:00
# ifdef EXTRADEBUG
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Addr: " ) , 0x80 ) ;
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( bAddress , 0x80 ) ;
2012-05-26 01:48:12 +02:00
# endif
2013-12-19 03:58:24 +01:00
//delay(300); // Spec says you should wait at least 200ms
2013-12-05 00:40:23 +01:00
2013-03-28 09:46:43 +01:00
p - > lowspeed = false ;
//get pointer to assigned address record
p = addrPool . GetUsbDevicePtr ( bAddress ) ;
2013-12-25 11:09:57 +01:00
if ( ! p )
2013-03-28 09:46:43 +01:00
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 ) ;
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-28 09:46:43 +01:00
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 ;
2013-12-05 00:40:23 +01:00
epInfo [ PS3_OUTPUT_PIPE ] . bmSndToggle = 0 ;
epInfo [ PS3_OUTPUT_PIPE ] . bmRcvToggle = 0 ;
2013-03-28 09:46:43 +01:00
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 ;
2013-12-05 00:40:23 +01:00
epInfo [ PS3_INPUT_PIPE ] . bmSndToggle = 0 ;
epInfo [ PS3_INPUT_PIPE ] . bmRcvToggle = 0 ;
2013-03-28 09:46:43 +01:00
rcode = pUsb - > setEpInfoEntry ( bAddress , 3 , epInfo ) ;
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-28 09:46:43 +01:00
goto FailSetDevTblEntry ;
delay ( 200 ) ; //Give time for address change
rcode = pUsb - > setConf ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , 1 ) ;
2013-12-25 11:09:57 +01:00
if ( rcode )
2013-03-30 15:29:16 +01:00
goto FailSetConfDescr ;
2013-03-28 09:46:43 +01:00
2013-12-25 11:09:57 +01:00
if ( PID = = PS3_PID | | PID = = PS3NAVIGATION_PID ) {
if ( PID = = PS3_PID ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Dualshock 3 Controller Connected " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2013-03-28 09:46:43 +01:00
PS3Connected = true ;
} else { // must be a navigation controller
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Navigation Controller Connected " ) , 0x80 ) ;
2012-05-26 01:48:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
PS3NavigationConnected = true ;
}
2013-07-15 20:17:28 +02:00
enable_sixaxis ( ) ; // The PS3 controller needs a special command before it starts sending data
2013-03-28 09:46:43 +01:00
// Needed for PS3 Dualshock and Navigation commands to work
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < PS3_REPORT_BUFFER_SIZE ; i + + )
2013-03-28 09:46:43 +01:00
writeBuf [ i ] = pgm_read_byte ( & PS3_REPORT_BUFFER [ i ] ) ;
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 6 ; i < 10 ; i + + )
2013-03-28 09:46:43 +01:00
readBuf [ i ] = 0x7F ; // Set the analog joystick values to center position
} else { // must be a Motion controller
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n Motion Controller Connected " ) , 0x80 ) ;
2013-03-28 09:37:09 +01:00
# endif
2013-03-28 09:46:43 +01:00
PS3MoveConnected = true ;
2013-04-02 00:12:38 +02:00
writeBuf [ 0 ] = 0x02 ; // Set report ID, this is needed for Move commands to work
2013-03-28 09:46:43 +01:00
}
2013-12-25 11:09:57 +01:00
if ( my_bdaddr [ 0 ] ! = 0x00 | | my_bdaddr [ 1 ] ! = 0x00 | | my_bdaddr [ 2 ] ! = 0x00 | | my_bdaddr [ 3 ] ! = 0x00 | | my_bdaddr [ 4 ] ! = 0x00 | | my_bdaddr [ 5 ] ! = 0x00 ) {
if ( PS3MoveConnected )
2013-07-15 18:22:13 +02:00
setMoveBdaddr ( my_bdaddr ) ; // Set internal Bluetooth address
else
setBdaddr ( my_bdaddr ) ; // Set internal Bluetooth address
2012-05-26 01:48:12 +02:00
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-07-15 18:22:13 +02:00
Notify ( PSTR ( " \r \n Bluetooth Address was set to: " ) , 0x80 ) ;
2013-12-25 11:09:57 +01:00
for ( int8_t i = 5 ; i > 0 ; i - - ) {
2013-07-15 18:22:13 +02:00
D_PrintHex < uint8_t > ( my_bdaddr [ i ] , 0x80 ) ;
Notify ( PSTR ( " : " ) , 0x80 ) ;
}
D_PrintHex < uint8_t > ( my_bdaddr [ 0 ] , 0x80 ) ;
2013-04-03 21:28:44 +02:00
# endif
2013-07-15 18:22:13 +02:00
}
2013-07-16 17:07:25 +02:00
onInit ( ) ;
2013-04-03 21:28:44 +02:00
2013-03-28 09:46:43 +01:00
bPollEnable = true ;
Notify ( PSTR ( " \r \n " ) , 0x80 ) ;
timer = millis ( ) ;
2013-12-06 22:58:16 +01:00
return 0 ; // Successful configuration
2013-03-28 09:37:09 +01:00
2013-12-06 22:58:16 +01:00
/* Diagnostic messages */
2012-05-26 01:48:12 +02:00
FailGetDevDescr :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-30 15:29:16 +01:00
NotifyFailGetDevDescr ( ) ;
2013-03-28 09:46:43 +01:00
goto Fail ;
2013-05-16 22:43:51 +02:00
# endif
2013-12-06 22:58:16 +01:00
2012-05-26 01:48:12 +02:00
FailSetDevTblEntry :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-30 15:29:16 +01:00
NotifyFailSetDevTblEntry ( ) ;
2013-03-28 09:46:43 +01:00
goto Fail ;
2013-05-16 22:43:51 +02:00
# endif
2013-03-30 15:29:16 +01:00
FailSetConfDescr :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-03-30 15:29:16 +01:00
NotifyFailSetConfDescr ( ) ;
2013-12-05 00:40:23 +01:00
# endif
2013-12-06 22:58:16 +01:00
goto Fail ;
2013-12-05 00:40:23 +01:00
2012-05-26 01:48:12 +02:00
FailUnknownDevice :
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-05-16 22:43:51 +02:00
NotifyFailUnknownDevice ( VID , PID ) ;
# endif
2013-03-28 09:46:43 +01:00
rcode = USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED ;
2013-03-30 15:29:16 +01:00
2013-12-05 00:40:23 +01:00
Fail :
2013-12-06 22:58:16 +01:00
# ifdef DEBUG_USB_HOST
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n PS3 Init Failed, error code: " ) , 0x80 ) ;
2013-03-30 15:29:16 +01:00
NotifyFail ( rcode ) ;
2013-05-16 22:43:51 +02:00
# endif
2013-03-28 09:46:43 +01:00
Release ( ) ;
return rcode ;
2012-05-26 01:48:12 +02:00
}
/* Performs a cleanup after failed Init() attempt */
2012-08-04 19:08:43 +02:00
uint8_t PS3USB : : Release ( ) {
2013-03-28 09:46:43 +01:00
PS3Connected = false ;
PS3MoveConnected = false ;
PS3NavigationConnected = false ;
pUsb - > GetAddressPool ( ) . FreeAddress ( bAddress ) ;
bAddress = 0 ;
bPollEnable = false ;
return 0 ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2013-03-28 09:37:09 +01:00
uint8_t PS3USB : : Poll ( ) {
2013-12-25 11:09:57 +01:00
if ( ! bPollEnable )
2013-03-28 09:46:43 +01:00
return 0 ;
2013-12-25 11:09:57 +01:00
if ( PS3Connected | | PS3NavigationConnected ) {
2013-03-28 09:46:43 +01:00
uint16_t BUFFER_SIZE = EP_MAXPKTSIZE ;
pUsb - > inTransfer ( bAddress , epInfo [ PS3_INPUT_PIPE ] . epAddr , & BUFFER_SIZE , readBuf ) ; // input on endpoint 1
2013-12-25 11:09:57 +01:00
if ( millis ( ) - timer > 100 ) { // Loop 100ms before processing data
2013-03-28 09:46:43 +01:00
readReport ( ) ;
2012-05-26 01:48:12 +02:00
# ifdef PRINTREPORT
2013-03-28 09:46:43 +01:00
printReport ( ) ; // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
2012-05-26 01:48:12 +02:00
# endif
2013-03-28 09:46:43 +01:00
}
2013-12-25 11:09:57 +01:00
} 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
2013-03-28 09:46:43 +01:00
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 ( ) ;
}
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
return 0 ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:37:09 +01:00
void PS3USB : : readReport ( ) {
2013-03-28 09:46:43 +01:00
ButtonState = ( uint32_t ) ( readBuf [ 2 ] | ( ( uint16_t ) readBuf [ 3 ] < < 8 ) | ( ( uint32_t ) readBuf [ 4 ] < < 16 ) ) ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
//Notify(PSTR("\r\nButtonState", 0x80);
//PrintHex<uint32_t>(ButtonState, 0x80);
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( ButtonState ! = OldButtonState ) {
2013-03-28 09:46:43 +01:00
ButtonClickState = ButtonState & ~ OldButtonState ; // Update click state variable
OldButtonState = ButtonState ;
}
2012-10-02 01:43:00 +02:00
}
2012-05-26 01:48:12 +02:00
2013-11-12 19:44:12 +01:00
void PS3USB : : printReport ( ) { // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
2013-01-19 15:43:28 +01:00
# ifdef PRINTREPORT
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < PS3_REPORT_BUFFER_SIZE ; i + + ) {
2013-06-17 21:37:09 +02:00
D_PrintHex < uint8_t > ( readBuf [ i ] , 0x80 ) ;
2013-04-26 23:50:39 +02:00
Notify ( PSTR ( " " ) , 0x80 ) ;
2013-03-28 09:46:43 +01:00
}
2013-04-26 23:50:39 +02:00
Notify ( PSTR ( " \r \n " ) , 0x80 ) ;
2013-01-19 15:43:28 +01:00
# endif
2012-05-26 01:48:12 +02:00
}
2012-09-09 22:13:52 +02:00
bool PS3USB : : getButtonPress ( Button b ) {
2013-03-28 09:46:43 +01:00
return ( ButtonState & pgm_read_dword ( & BUTTONS [ ( uint8_t ) b ] ) ) ;
2012-09-09 22:13:52 +02:00
}
2013-03-28 09:46:43 +01:00
2012-09-09 22:13:52 +02:00
bool PS3USB : : getButtonClick ( Button b ) {
2013-03-28 09:46:43 +01:00
uint32_t button = pgm_read_dword ( & BUTTONS [ ( uint8_t ) b ] ) ;
bool click = ( ButtonClickState & button ) ;
2013-11-12 19:44:12 +01:00
ButtonClickState & = ~ button ; // Clear "click" event
2013-03-28 09:46:43 +01:00
return click ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2013-01-27 22:02:33 +01:00
uint8_t PS3USB : : getAnalogButton ( Button a ) {
2013-03-28 09:46:43 +01:00
return ( uint8_t ) ( readBuf [ ( pgm_read_byte ( & ANALOGBUTTONS [ ( uint8_t ) a ] ) ) - 9 ] ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
uint8_t PS3USB : : getAnalogHat ( AnalogHat a ) {
2013-03-28 09:46:43 +01:00
return ( uint8_t ) ( readBuf [ ( ( uint8_t ) a + 6 ) ] ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
uint16_t PS3USB : : getSensor ( Sensor a ) {
2013-03-28 09:46:43 +01:00
return ( ( readBuf [ ( ( uint16_t ) a ) - 9 ] < < 8 ) | readBuf [ ( ( uint16_t ) a + 1 ) - 9 ] ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2013-03-28 09:37:09 +01:00
double PS3USB : : getAngle ( Angle a ) {
2013-12-25 11:09:57 +01:00
if ( PS3Connected ) {
2013-03-28 09:46:43 +01:00
double accXval ;
double accYval ;
double accZval ;
// Data for the Kionix KXPC4 used in the DualShock 3
const double zeroG = 511.5 ; // 1.65/3.3*1023 (1,65V)
accXval = - ( ( double ) getSensor ( aX ) - zeroG ) ;
accYval = - ( ( double ) getSensor ( aY ) - zeroG ) ;
accZval = - ( ( double ) getSensor ( aZ ) - zeroG ) ;
// Convert to 360 degrees resolution
// atan2 outputs the value of -π to π (radians)
// We are then converting it to 0 to 2π and then to degrees
2013-12-25 11:09:57 +01:00
if ( a = = Pitch )
2013-11-12 19:44:12 +01:00
return ( atan2 ( accYval , accZval ) + PI ) * RAD_TO_DEG ;
else
return ( atan2 ( accXval , accZval ) + PI ) * RAD_TO_DEG ;
2013-03-28 09:46:43 +01:00
} else
return 0 ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
bool PS3USB : : getStatus ( Status c ) {
2013-11-12 19:44:12 +01:00
return ( readBuf [ ( ( uint16_t ) c > > 8 ) - 9 ] = = ( ( uint8_t ) c & 0xff ) ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
String PS3USB : : getStatusString ( ) {
2013-12-25 11:09:57 +01:00
if ( PS3Connected | | PS3NavigationConnected ) {
2013-03-28 09:46:43 +01:00
char statusOutput [ 100 ] ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
strcpy ( statusOutput , " ConnectionStatus: " ) ;
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( getStatus ( Plugged ) ) strcat ( statusOutput , " Plugged " ) ;
else if ( getStatus ( Unplugged ) ) strcat ( statusOutput , " Unplugged " ) ;
2013-03-28 09:46:43 +01:00
else strcat ( statusOutput , " Error " ) ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
strcat ( statusOutput , " - PowerRating: " ) ;
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( getStatus ( Charging ) ) strcat ( statusOutput , " Charging " ) ;
else if ( getStatus ( NotCharging ) ) strcat ( statusOutput , " Not Charging " ) ;
else if ( getStatus ( Shutdown ) ) strcat ( statusOutput , " Shutdown " ) ;
else if ( getStatus ( Dying ) ) strcat ( statusOutput , " Dying " ) ;
else if ( getStatus ( Low ) ) strcat ( statusOutput , " Low " ) ;
else if ( getStatus ( High ) ) strcat ( statusOutput , " High " ) ;
else if ( getStatus ( Full ) ) strcat ( statusOutput , " Full " ) ;
2013-03-28 09:46:43 +01:00
else strcat ( statusOutput , " Error " ) ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
strcat ( statusOutput , " - WirelessStatus: " ) ;
2013-03-28 09:37:09 +01:00
2013-12-25 11:09:57 +01:00
if ( getStatus ( CableRumble ) ) strcat ( statusOutput , " Cable - Rumble is on " ) ;
else if ( getStatus ( Cable ) ) strcat ( statusOutput , " Cable - Rumble is off " ) ;
else if ( getStatus ( BluetoothRumble ) ) strcat ( statusOutput , " Bluetooth - Rumble is on " ) ;
else if ( getStatus ( Bluetooth ) ) strcat ( statusOutput , " Bluetooth - Rumble is off " ) ;
2013-03-28 09:46:43 +01:00
else strcat ( statusOutput , " Error " ) ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
return statusOutput ;
2013-04-03 18:12:05 +02:00
} else
return " Error " ;
2012-05-26 01:48:12 +02:00
}
/* Playstation Sixaxis Dualshock and Navigation Controller commands */
2013-11-12 19:44:12 +01:00
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)
2013-03-28 09:46:43 +01:00
pUsb - > ctrlReq ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , bmREQ_HID_OUT , HID_REQUEST_SET_REPORT , 0x01 , 0x02 , 0x00 , nbytes , nbytes , data , NULL ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
void PS3USB : : setAllOff ( ) {
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < PS3_REPORT_BUFFER_SIZE ; i + + )
2013-03-28 09:46:43 +01:00
writeBuf [ i ] = pgm_read_byte ( & PS3_REPORT_BUFFER [ i ] ) ; // Reset buffer
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
PS3_Command ( writeBuf , PS3_REPORT_BUFFER_SIZE ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
void PS3USB : : setRumbleOff ( ) {
2013-03-28 09:46:43 +01:00
writeBuf [ 1 ] = 0x00 ;
2013-11-12 19:44:12 +01:00
writeBuf [ 2 ] = 0x00 ; // Low mode off
2013-03-28 09:46:43 +01:00
writeBuf [ 3 ] = 0x00 ;
2013-11-12 19:44:12 +01:00
writeBuf [ 4 ] = 0x00 ; // High mode off
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
PS3_Command ( writeBuf , PS3_REPORT_BUFFER_SIZE ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
void PS3USB : : setRumbleOn ( Rumble mode ) {
2013-12-25 11:09:57 +01:00
if ( ( mode & 0x30 ) > 0x00 ) {
2013-05-16 22:43:51 +02:00
uint8_t power [ 2 ] = { 0xff , 0x00 } ; // Defaults to RumbleLow
2013-12-25 11:09:57 +01:00
if ( mode = = RumbleHigh ) {
2013-03-30 09:15:25 +01:00
power [ 0 ] = 0x00 ;
power [ 1 ] = 0xff ;
}
setRumbleOn ( 0xfe , power [ 0 ] , 0xfe , power [ 1 ] ) ;
2012-05-26 01:48:12 +02:00
}
}
2013-03-30 09:15:25 +01:00
2013-03-30 05:54:13 +01:00
void PS3USB : : setRumbleOn ( uint8_t rightDuration , uint8_t rightPower , uint8_t leftDuration , uint8_t leftPower ) {
2013-03-30 09:15:25 +01:00
writeBuf [ 1 ] = rightDuration ;
writeBuf [ 2 ] = rightPower ;
writeBuf [ 3 ] = leftDuration ;
writeBuf [ 4 ] = leftPower ;
PS3_Command ( writeBuf , PS3_REPORT_BUFFER_SIZE ) ;
2013-03-30 05:54:13 +01:00
}
2013-03-30 09:15:25 +01:00
2013-04-01 15:38:15 +02:00
void PS3USB : : setLedRaw ( uint8_t value ) {
2013-05-16 19:29:59 +02:00
writeBuf [ 9 ] = value < < 1 ;
2013-04-01 15:38:15 +02:00
PS3_Command ( writeBuf , PS3_REPORT_BUFFER_SIZE ) ;
}
2013-05-16 22:43:51 +02:00
2012-08-04 19:08:43 +02:00
void PS3USB : : setLedOff ( LED a ) {
2013-03-28 09:46:43 +01:00
writeBuf [ 9 ] & = ~ ( ( uint8_t ) ( ( pgm_read_byte ( & LEDS [ ( uint8_t ) a ] ) & 0x0f ) < < 1 ) ) ;
PS3_Command ( writeBuf , PS3_REPORT_BUFFER_SIZE ) ;
2012-05-26 01:48:12 +02:00
}
2013-05-16 22:43:51 +02:00
2012-08-04 19:08:43 +02:00
void PS3USB : : setLedOn ( LED a ) {
2013-03-28 09:46:43 +01:00
writeBuf [ 9 ] | = ( uint8_t ) ( ( pgm_read_byte ( & LEDS [ ( uint8_t ) a ] ) & 0x0f ) < < 1 ) ;
PS3_Command ( writeBuf , PS3_REPORT_BUFFER_SIZE ) ;
2012-05-26 01:48:12 +02:00
}
2013-05-16 22:43:51 +02:00
2012-08-04 19:08:43 +02:00
void PS3USB : : setLedToggle ( LED a ) {
2013-03-28 09:46:43 +01:00
writeBuf [ 9 ] ^ = ( uint8_t ) ( ( pgm_read_byte ( & LEDS [ ( uint8_t ) a ] ) & 0x0f ) < < 1 ) ;
PS3_Command ( writeBuf , PS3_REPORT_BUFFER_SIZE ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2013-11-12 19:44:12 +01:00
void PS3USB : : setBdaddr ( uint8_t * bdaddr ) {
/* Set the internal Bluetooth address */
2013-03-28 09:46:43 +01:00
uint8_t buf [ 8 ] ;
buf [ 0 ] = 0x01 ;
buf [ 1 ] = 0x00 ;
2013-11-12 19:44:12 +01:00
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-11-12 19:44:12 +01:00
buf [ i + 2 ] = bdaddr [ 5 - i ] ; // Copy into buffer, has to be written reversed, so it is MSB first
2013-03-28 09:46:43 +01:00
2013-11-12 19:44:12 +01:00
// 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
2013-03-28 09:46:43 +01:00
pUsb - > ctrlReq ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , bmREQ_HID_OUT , HID_REQUEST_SET_REPORT , 0xF5 , 0x03 , 0x00 , 8 , 8 , buf , NULL ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2013-11-12 19:44:12 +01:00
void PS3USB : : getBdaddr ( uint8_t * bdaddr ) {
uint8_t buf [ 8 ] ;
// bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0xF5), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
pUsb - > ctrlReq ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , bmREQ_HID_IN , HID_REQUEST_GET_REPORT , 0xF5 , 0x03 , 0x00 , 8 , 8 , buf , NULL ) ;
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-11-12 19:44:12 +01:00
bdaddr [ 5 - i ] = buf [ i + 2 ] ; // Copy into buffer reversed, so it is LSB first
}
void PS3USB : : enable_sixaxis ( ) { // Command used to enable the Dualshock 3 and Navigation controller to send data via USB
2013-03-28 09:46:43 +01:00
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 ;
2013-11-12 19:44:12 +01:00
// 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)
2013-03-28 09:46:43 +01:00
pUsb - > ctrlReq ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , bmREQ_HID_OUT , HID_REQUEST_SET_REPORT , 0xF4 , 0x03 , 0x00 , 4 , 4 , cmd_buf , NULL ) ;
2012-05-26 01:48:12 +02:00
}
/* Playstation Move Controller commands */
2013-11-12 19:44:12 +01:00
void PS3USB : : Move_Command ( uint8_t * data , uint16_t nbytes ) {
2013-03-28 09:46:43 +01:00
pUsb - > outTransfer ( bAddress , epInfo [ PS3_OUTPUT_PIPE ] . epAddr , nbytes , data ) ;
2013-03-28 09:37:09 +01:00
}
2012-05-26 01:48:12 +02:00
2013-11-12 19:44:12 +01:00
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
2013-03-28 09:46:43 +01:00
writeBuf [ 2 ] = r ;
writeBuf [ 3 ] = g ;
writeBuf [ 4 ] = b ;
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
Move_Command ( writeBuf , MOVE_REPORT_BUFFER_SIZE ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2013-11-12 19:44:12 +01:00
void PS3USB : : moveSetBulb ( Colors color ) { // Use this to set the Color using the predefined colors in "enums.h"
2013-03-28 09:46:43 +01:00
moveSetBulb ( ( uint8_t ) ( color > > 16 ) , ( uint8_t ) ( color > > 8 ) , ( uint8_t ) ( color ) ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2012-08-04 19:08:43 +02:00
void PS3USB : : moveSetRumble ( uint8_t rumble ) {
2013-06-12 05:11:43 +02:00
# ifdef DEBUG_USB_HOST
2013-12-25 11:09:57 +01:00
if ( rumble < 64 & & rumble ! = 0 ) // The rumble value has to at least 64, or approximately 25% (64/255*100)
2013-03-28 09:46:43 +01:00
Notify ( PSTR ( " \r \n The rumble value has to at least 64, or approximately 25% " ) , 0x80 ) ;
2012-05-26 01:48:12 +02:00
# endif
2013-11-12 19:44:12 +01:00
writeBuf [ 6 ] = rumble ; // Set the rumble value into the write buffer
2013-03-28 09:37:09 +01:00
2013-03-28 09:46:43 +01:00
Move_Command ( writeBuf , MOVE_REPORT_BUFFER_SIZE ) ;
2012-05-26 01:48:12 +02:00
}
2013-03-28 09:46:43 +01:00
2013-11-12 19:44:12 +01:00
void PS3USB : : setMoveBdaddr ( uint8_t * bdaddr ) {
/* Set the internal Bluetooth address */
2013-03-28 09:46:43 +01:00
uint8_t buf [ 11 ] ;
buf [ 0 ] = 0x05 ;
buf [ 7 ] = 0x10 ;
buf [ 8 ] = 0x01 ;
buf [ 9 ] = 0x02 ;
buf [ 10 ] = 0x12 ;
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-11-12 19:44:12 +01:00
buf [ i + 1 ] = bdaddr [ i ] ;
2013-03-28 09:46:43 +01:00
2013-11-12 19:44:12 +01:00
// 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
2013-03-28 09:46:43 +01:00
pUsb - > ctrlReq ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , bmREQ_HID_OUT , HID_REQUEST_SET_REPORT , 0x05 , 0x03 , 0x00 , 11 , 11 , buf , NULL ) ;
2013-03-30 09:15:25 +01:00
}
2013-07-14 00:43:35 +02:00
2013-11-12 19:44:12 +01:00
void PS3USB : : getMoveBdaddr ( uint8_t * bdaddr ) {
uint8_t buf [ 16 ] ;
// bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x04), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
pUsb - > ctrlReq ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , bmREQ_HID_IN , HID_REQUEST_GET_REPORT , 0x04 , 0x03 , 0x00 , 16 , 16 , buf , NULL ) ;
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 6 ; i + + )
2013-11-12 19:44:12 +01:00
bdaddr [ i ] = buf [ 10 + i ] ;
}
void PS3USB : : getMoveCalibration ( uint8_t * data ) {
uint8_t buf [ 49 ] ;
2013-12-25 11:09:57 +01:00
for ( uint8_t i = 0 ; i < 3 ; i + + ) {
2013-11-12 19:44:12 +01:00
// bmRequest = Device to host (0x80) | Class (0x20) | Interface (0x01) = 0xA1, bRequest = Get Report (0x01), Report ID (0x10), Report Type (Feature 0x03), interface (0x00), datalength, datalength, data
pUsb - > ctrlReq ( bAddress , epInfo [ PS3_CONTROL_PIPE ] . epAddr , bmREQ_HID_IN , HID_REQUEST_GET_REPORT , 0x10 , 0x03 , 0x00 , 49 , 49 , buf , NULL ) ;
2013-12-25 11:09:57 +01:00
for ( byte j = 0 ; j < 49 ; j + + )
2013-11-12 19:44:12 +01:00
data [ 49 * i + j ] = buf [ j ] ;
}
}
2013-07-14 00:43:35 +02:00
void PS3USB : : onInit ( ) {
2013-12-25 11:09:57 +01:00
if ( pFuncOnInit )
2013-07-14 00:43:35 +02:00
pFuncOnInit ( ) ; // Call the user function
else {
2013-12-25 11:09:57 +01:00
if ( PS3MoveConnected )
2013-07-14 00:43:35 +02:00
moveSetBulb ( Red ) ;
else // Dualshock 3 or Navigation controller
setLedOn ( LED1 ) ;
}
2013-07-16 17:07:25 +02:00
}