Minor revision

This commit is contained in:
Kristian Lauszus 2012-04-12 23:15:18 +02:00
parent a90c2ab4da
commit da6eb99a2f
3 changed files with 217 additions and 183 deletions

304
PS3BT.cpp
View file

@ -37,12 +37,12 @@ prog_char OUTPUT_REPORT_BUFFER[] PROGMEM =
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
PS3BT::PS3BT(USB *p):
pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory
bNumEP(1), // if config descriptor needs to be parsed
qNextPollTime(0),
bPollEnable(false) // don't start polling before dongle is connected
PS3BT::PS3BT(USB *p, uint8_t btadr5 = 0, uint8_t btadr4 = 0, uint8_t btadr3 = 0, uint8_t btadr2 = 0, uint8_t btadr1 = 0, uint8_t btadr0 = 0):
pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory
bNumEP(1), // if config descriptor needs to be parsed
qNextPollTime(0),
bPollEnable(false) // don't start polling before dongle is connected
{
for(uint8_t i=0; i<PS3_MAX_ENDPOINTS; i++)
{
@ -55,12 +55,31 @@ PS3BT::PS3BT(USB *p):
if (pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry
my_bdaddr[5] = 0x00; // Change to your dongle's Bluetooth address instead
my_bdaddr[4] = 0x1F;
my_bdaddr[3] = 0x81;
my_bdaddr[2] = 0x00;
my_bdaddr[1] = 0x08;
my_bdaddr[0] = 0x30;
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;
}
PS3BT::PS3BT(USB *p):
pUsb(p), // pointer to USB class instance - mandatory
bAddress(0), // device address - mandatory
bNumEP(1), // if config descriptor needs to be parsed
qNextPollTime(0),
bPollEnable(false) // don't start polling before dongle is connected
{
for(uint8_t i=0; i<PS3_MAX_ENDPOINTS; i++)
{
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;
}
if (pUsb) // register in USB subsystem
pUsb->RegisterDeviceClass(this); //set devConfig[] entry
}
uint8_t PS3BT::Init(uint8_t parent, uint8_t port, bool lowspeed)
@ -167,74 +186,8 @@ uint8_t PS3BT::Init(uint8_t parent, uint8_t port, bool lowspeed)
VID = ((USB_DEVICE_DESCRIPTOR*)buf)->idVendor;
PID = ((USB_DEVICE_DESCRIPTOR*)buf)->idProduct;
if((VID == CSR_VID || VID == ISSC_VID) && (PID == CSR_PID || PID == ISSC_PID))
{
#ifdef DEBUG
Notify(PSTR("\r\nBluetooth Dongle Connected"));
#endif
//Needed for PS3 Dualshock Controller commands to work via bluetooth
for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++)
HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]);//First two bytes reserved for report type and ID
HIDBuffer[0] = 0x52;// HID BT Set_report (0x50) | Report Type (Output 0x02)
HIDBuffer[1] = 0x01;// Report ID
//Needed for PS3 Move Controller commands to work via bluetooth
HIDMoveBuffer[0] = 0xA2;// HID BT DATA_request (0xA0) | Report Type (Output 0x02)
HIDMoveBuffer[1] = 0x02;// Report ID
/* Set device cid for the control and intterrupt channelse - LSB */
control_dcid[0] = 0x40;//0x0040
control_dcid[1] = 0x00;
interrupt_dcid[0] = 0x41;//0x0041
interrupt_dcid[1] = 0x00;
//check if attached device is a Bluetooth dongle and fill endpoint data structure
//first interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
//and 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT,
//not necessarily in this order
for (uint8_t i=0; i<num_of_conf; i++) {
ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
if(rcode)
goto FailGetConfDescr;
if( bNumEP > 3 ) //all endpoints extracted
break;
} // for (uint8_t i=0; i<num_of_conf; i++...
if (bNumEP < PS3_MAX_ENDPOINTS) {
#ifdef DEBUG
Notify(PSTR("\r\nBluetooth dongle is not supported"));
#endif
goto Fail;
}
// Assign epInfo to epinfo pointer - this time all 3 endpoins
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
if( rcode )
goto FailSetDevTblEntry;
delay(200); // Give time for address change
// Set Configuration Value
rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);
if( rcode )
goto FailSetConf;
hci_state = HCI_INIT_STATE;
hci_counter = 0;
l2cap_state = L2CAP_EV_WAIT;
#ifdef DEBUG
Notify(PSTR("\r\nCSR Initialized"));
#endif
watingForConnection = false;
bPollEnable = true;
}
else if((VID == PS3_VID || VID == PS3NAVIGATION_VID || VID == PS3MOVE_VID) && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID))
{
/*The application will work in reduced host mode, so we can save program and data
if(VID == PS3_VID && (PID == PS3_PID || PID == PS3NAVIGATION_PID || PID == PS3MOVE_PID)) {
/* 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 */
@ -262,9 +215,9 @@ uint8_t PS3BT::Init(uint8_t parent, uint8_t port, bool lowspeed)
if( rcode )
goto FailSetConf;
if((VID == PS3_VID || VID == PS3NAVIGATION_VID) && (PID == PS3_PID || PID == PS3NAVIGATION_PID))
if(PID == PS3_PID || PID == PS3NAVIGATION_PID)
{
if(VID == PS3_VID && PID == PS3_PID) {
if(PID == PS3_PID) {
#ifdef DEBUG
Notify(PSTR("\r\nDualshock 3 Controller Connected"));
#endif
@ -285,46 +238,112 @@ uint8_t PS3BT::Init(uint8_t parent, uint8_t port, bool lowspeed)
}
}
else
goto FailUnknownDevice;
{
//check if attached device is a Bluetooth dongle and fill endpoint data structure
//first interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
//and 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT,
//not necessarily in this order
for (uint8_t i=0; i<num_of_conf; i++) {
ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
if(rcode)
goto FailGetConfDescr;
if(bNumEP > 3) //all endpoints extracted
break;
} // for (uint8_t i=0; i<num_of_conf; i++...
if (bNumEP < PS3_MAX_ENDPOINTS)
goto FailUnknownDevice;
// Assign epInfo to epinfo pointer - this time all 3 endpoins
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
if(rcode)
goto FailSetDevTblEntry;
delay(200); // Give time for address change
// Set Configuration Value
rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, bConfNum);
if(rcode)
goto FailSetConf;
if(VID == CSR_VID && PID == CSR_PID) {
if((uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice < 0x1915) { // I don't know the exact number, plese let me know if you do
#ifdef DEBUG
Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour Revision ID is: 0x"));
PrintHex<uint16_t>((uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->bcdDevice);
Notify(PSTR("\r\nBut should be at least 0x1915\r\nThis usually means that it doesn't support Bluetooth Version 2.0+EDR"));
#endif
}
}
//Needed for PS3 Dualshock Controller commands to work via bluetooth
for (uint8_t i = 0; i < OUTPUT_REPORT_BUFFER_SIZE; i++)
HIDBuffer[i + 2] = pgm_read_byte(&OUTPUT_REPORT_BUFFER[i]);//First two bytes reserved for report type and ID
HIDBuffer[0] = 0x52;// HID BT Set_report (0x50) | Report Type (Output 0x02)
HIDBuffer[1] = 0x01;// Report ID
//Needed for PS3 Move Controller commands to work via bluetooth
HIDMoveBuffer[0] = 0xA2;// HID BT DATA_request (0xA0) | Report Type (Output 0x02)
HIDMoveBuffer[1] = 0x02;// Report ID
/* Set device cid for the control and intterrupt channelse - LSB */
control_dcid[0] = 0x40;//0x0040
control_dcid[1] = 0x00;
interrupt_dcid[0] = 0x41;//0x0041
interrupt_dcid[1] = 0x00;
hci_num_reset_loops = 10; // only loop 10 times before trying to send the hci reset command
hci_state = HCI_INIT_STATE;
hci_counter = 0;
l2cap_state = L2CAP_EV_WAIT;
#ifdef DEBUG
Notify(PSTR("\r\nBluetooth Dongle Initialized"));
#endif
watingForConnection = false;
bPollEnable = true;
}
return 0; //successful configuration
/* diagnostic messages */
FailGetDevDescr:
#ifdef DEBUG
Notify(PSTR("\r\ngetDevDescr:"));
#endif
goto Fail;
FailSetDevTblEntry:
#ifdef DEBUG
Notify(PSTR("\r\nsetDevTblEn:"));
#endif
goto Fail;
FailGetConfDescr:
#ifdef DEBUG
Notify(PSTR("\r\ngetConf:"));
#endif
goto Fail;
FailSetConf:
#ifdef DEBUG
Notify(PSTR("\r\nsetConf:"));
#endif
goto Fail;
FailUnknownDevice:
#ifdef DEBUG
Notify(PSTR("\r\nUnknown Device Connected - VID: "));
PrintHex<uint16_t>(VID);
Notify(PSTR(" PID: "));
PrintHex<uint16_t>(PID);
#endif
goto Fail;
Fail:
#ifdef DEBUG
Notify(PSTR("\r\nPS3 Init Failed, error code: "));
Serial.print(rcode);
#endif
Release();
return rcode;
/* diagnostic messages */
FailGetDevDescr:
#ifdef DEBUG
Notify(PSTR("\r\ngetDevDescr:"));
#endif
goto Fail;
FailSetDevTblEntry:
#ifdef DEBUG
Notify(PSTR("\r\nsetDevTblEn:"));
#endif
goto Fail;
FailGetConfDescr:
#ifdef DEBUG
Notify(PSTR("\r\ngetConf:"));
#endif
goto Fail;
FailSetConf:
#ifdef DEBUG
Notify(PSTR("\r\nsetConf:"));
#endif
goto Fail;
FailUnknownDevice:
#ifdef DEBUG
Notify(PSTR("\r\nUnknown Device Connected - VID: "));
PrintHex<uint16_t>(VID);
Notify(PSTR(" PID: "));
PrintHex<uint16_t>(PID);
#endif
goto Fail;
Fail:
#ifdef DEBUG
Notify(PSTR("\r\nPS3 Init Failed, error code: "));
Serial.print(rcode);
#endif
Release();
return rcode;
}
/* Extracts interrupt-IN, bulk-IN, bulk-OUT endpoint information from config descriptor */
void PS3BT::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep)
@ -352,7 +371,7 @@ void PS3BT::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t pro
//Fill the rest of endpoint data structure
epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
#ifdef EXTRADEBUG
#ifdef EXTRADEBUG
PrintEndpointDescriptor(pep);
#endif
if(pollInterval < pep->bInterval) // Set the polling interval as the largest polling interval obtained from endpoints
@ -511,11 +530,11 @@ double PS3BT::getAngle(Angle a, boolean resolution) // Boolean indicate if 360-d
{
double accXin;
double accXval;
double Pitch;
double angleX;
double accYin;
double accYval;
double Roll;
double angleY;
double accZin;
double accZval;
@ -543,36 +562,36 @@ double PS3BT::getAngle(Angle a, boolean resolution) // Boolean indicate if 360-d
{
//the result will come out as radians, so it is multiplied by 180/pi, to convert to degrees
//In the end it is minus by 90, so its 0 degrees when in horizontal postion
Pitch = acos(accXval / R) * 180 / PI - 90;
angleX = acos(accXval / R) * 180 / PI - 90;
if(resolution)
{
if (accZval < 0)//Convert to 360 degrees resolution - set resolution false if you need both pitch and roll
{
if (Pitch < 0)
Pitch = -180 - Pitch;
if (angleX < 0)
angleX = -180 - angleX;
else
Pitch = 180 - Pitch;
angleX = 180 - angleX;
}
}
return Pitch;
return angleX;
}
else
{
//the result will come out as radians, so it is multiplied by 180/pi, to convert to degrees
//In the end it is minus by 90, so its 0 degrees when in horizontal postion
Roll = acos(accYval / R) * 180 / PI - 90;
angleY = acos(accYval / R) * 180 / PI - 90;
if(resolution)
{
if (accZval < 0)//Convert to 360 degrees resolution - set resolution false if you need both pitch and roll
{
if (Roll < 0)
Roll = -180 - Roll;
if (angleY < 0)
angleY = -180 - angleY;
else
Roll = 180 - Roll;
angleY = 180 - angleY;
}
}
return Roll;
return angleY;
}
}
bool PS3BT::getStatus(Status c)
@ -739,15 +758,15 @@ void PS3BT::HCI_event_task()
break;
default:
#ifdef EXTRADEBUG
if(hcibuf[0] != 0x00)
{
#ifdef EXTRADEBUG
if(hcibuf[0] != 0x00)
{
Notify(PSTR("\r\nUnmanaged Event: "));
PrintHex<uint8_t>(hcibuf[0]);
}
#endif
}
#endif
break;
} // switch
} // switch
HCI_task();
}
else {
@ -764,7 +783,7 @@ void PS3BT::HCI_task()
switch (hci_state){
case HCI_INIT_STATE:
hci_counter++;
if (hci_counter > 1000) // wait until we have looped 1000 times to clear any old events
if (hci_counter > hci_num_reset_loops) // wait until we have looped x times to clear any old events
{
hci_reset();
hci_state = HCI_RESET_STATE;
@ -782,8 +801,11 @@ void PS3BT::HCI_task()
hci_state = HCI_BDADDR_STATE;
hci_read_bdaddr();
}
else if (hci_counter > 1000)
else if (hci_counter > hci_num_reset_loops)
{
hci_num_reset_loops *= 10;
if(hci_num_reset_loops > 2000)
hci_num_reset_loops = 2000;
#ifdef DEBUG
Notify(PSTR("\r\nNo response to HCI Reset"));
#endif
@ -930,7 +952,7 @@ void PS3BT::ACL_event_task()
{
Serial.print("\r\nL2CAP Signaling Command - 0x");
PrintHex<uint8_t>(l2capoutbuf[8]);
}
}
*/
if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT)
{

10
PS3BT.h
View file

@ -45,13 +45,9 @@
//PID and VID of the different devices
#define CSR_VID 0x0A12 // Cambridge Silicon Radio Ltd.
#define CSR_PID 0x0001 // Bluetooth HCI Device
#define ISSC_VID 0x1131 // Integrated System Solution Corp.
#define ISSC_PID 0x1004 // Bluetooth Device
#define PS3_VID 0x054C // Sony Corporation
#define PS3_PID 0x0268 // PS3 Controller DualShock 3
#define PS3NAVIGATION_VID 0x054C // Sony Corporation
#define PS3NAVIGATION_PID 0x042F // Navigation controller
#define PS3MOVE_VID 0x054C // Sony Corporation
#define PS3MOVE_PID 0x03D5 // Motion controller
#define HID_BUFFERSIZE 50 // size of the buffer for the Playstation Motion Controller
@ -157,10 +153,12 @@
#define PENDING 0x01
#define SUCCESSFUL 0x00
#define PS3_MAX_ENDPOINTS 4
// Used to determine if it is a Bluetooth dongle
#define WI_SUBCLASS_RF 0x01
#define WI_PROTOCOL_BT 0x01
#define PS3_MAX_ENDPOINTS 4
enum LED
{
LED1 = 0x01,
@ -319,6 +317,7 @@ enum Rumble
class PS3BT : public USBDeviceConfig, public UsbConfigXtracter
{
public:
PS3BT(USB *pUsb, uint8_t btadr5, uint8_t btadr4, uint8_t btadr3, uint8_t btadr2, uint8_t btadr1, uint8_t btadr0);
PS3BT(USB *pUsb);
// USBDeviceConfig implementation
@ -395,6 +394,7 @@ private:
/* variables used by high level HCI task */
uint8_t hci_state; //current state of bluetooth hci connection
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
uint16_t hci_event_flag;// hci flags of received bluetooth events
/* variables used by high level L2CAP task */

View file

@ -6,9 +6,12 @@
#include <PS3BT.h>
USB Usb;
PS3BT BT(&Usb);
/* You can create the instance of the class in two ways */
PS3BT BT(&Usb); // This will just create the instance
//PS3BT BT(&Usb,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch
boolean printTemperature;
boolean printAngle;
void setup()
{
@ -28,19 +31,19 @@ void loop()
if(BT.getAnalogHat(LeftHatX) > 137 || BT.getAnalogHat(LeftHatX) < 117 || BT.getAnalogHat(LeftHatY) > 137 || BT.getAnalogHat(LeftHatY) < 117 || BT.getAnalogHat(RightHatX) > 137 || BT.getAnalogHat(RightHatX) < 117 || BT.getAnalogHat(RightHatY) > 137 || BT.getAnalogHat(RightHatY) < 117) {
if(BT.getAnalogHat(LeftHatX) > 137 || BT.getAnalogHat(LeftHatX) < 117) {
Serial.print(F("LeftHatX: "));
Serial.print(BT.getAnalogHat(LeftHatX), DEC);
Serial.print(BT.getAnalogHat(LeftHatX));
Serial.print("\t");
} if(BT.getAnalogHat(LeftHatY) > 137 || BT.getAnalogHat(LeftHatY) < 117) {
Serial.print(F("LeftHatY: "));
Serial.print(BT.getAnalogHat(LeftHatY), DEC);
Serial.print(BT.getAnalogHat(LeftHatY));
Serial.print("\t");
} if(BT.getAnalogHat(RightHatX) > 137 || BT.getAnalogHat(RightHatX) < 117) {
Serial.print(F("RightHatX: "));
Serial.print(BT.getAnalogHat(RightHatX), DEC);
Serial.print(BT.getAnalogHat(RightHatX));
Serial.print("\t");
} if(BT.getAnalogHat(RightHatY) > 137 || BT.getAnalogHat(RightHatY) < 117) {
Serial.print(F("RightHatY: "));
Serial.print(BT.getAnalogHat(RightHatY), DEC);
Serial.print(BT.getAnalogHat(RightHatY));
}
Serial.println("");
}
@ -49,11 +52,11 @@ void loop()
if(BT.getAnalogButton(L2_ANALOG) > 0 || BT.getAnalogButton(R2_ANALOG) > 0) {
if(BT.getAnalogButton(L2_ANALOG) > 0) {
Serial.print(F("L2: "));
Serial.print(BT.getAnalogButton(L2_ANALOG), DEC);
Serial.print(BT.getAnalogButton(L2_ANALOG));
Serial.print("\t");
} if(BT.getAnalogButton(R2_ANALOG) > 0) {
Serial.print(F("R2: "));
Serial.print(BT.getAnalogButton(R2_ANALOG), DEC);
Serial.print(BT.getAnalogButton(R2_ANALOG));
}
Serial.println("");
}
@ -109,18 +112,27 @@ void loop()
if(BT.getButton(SELECT)) {
Serial.print(F(" - Select - "));
Serial.print(BT.getStatusString());
} if(BT.getButton(START))
} if(BT.getButton(START)) {
Serial.print(F(" - Start"));
printAngle = !printAngle;
while(BT.getButton(START))
Usb.Task();
}
Serial.println("");
}
}
if(printAngle) {
Serial.print(F("Pitch: "));
Serial.print(BT.getAngle(Pitch,false));
Serial.print(F("\tRoll: "));
Serial.println(BT.getAngle(Roll,false));
}
}
else if(BT.PS3MoveBTConnected)
{
if(BT.getAnalogButton(T_MOVE_ANALOG) > 0) {
Serial.print(F("T: "));
Serial.println(BT.getAnalogButton(T_MOVE_ANALOG), DEC);
Serial.println(BT.getAnalogButton(T_MOVE_ANALOG));
} if(BT.buttonPressed) {
Serial.print(F("PS3 Move Controller"));
@ -161,7 +173,7 @@ void loop()
if(printTemperature) {
String templow;
String temphigh;
String input = String(BT.getSensor(tempMove), DEC);
String input = String(BT.getSensor(tempMove));
if (input.length() > 3) {
temphigh = input.substring(0, 2);