Some minor changes

This commit is contained in:
Kristian Lauszus 2012-08-08 05:40:53 +02:00
parent a70deaf5cc
commit 1ff0135b31
6 changed files with 111 additions and 95 deletions

22
BTD.cpp
View file

@ -295,7 +295,7 @@ void BTD::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
uint8_t BTD::Release() {
for (uint8_t i=0; i<BTD_NUMDEVICES; i++)
if (btService[i])
btService[i]->Release(); // Reset both the L2CAP Channel and the HCI Connection
btService[i]->Reset(); // Reset both the L2CAP Channel and the HCI Connection
pUsb->GetAddressPool().FreeAddress(bAddress);
bAddress = 0;
bPollEnable = false;
@ -560,13 +560,16 @@ void BTD::HCI_task() {
Notify(PSTR("\r\nScan Disabled"));
#endif
hci_event_flag = 0;
hci_state = HCI_DONE_STATE;
hci_state = HCI_DONE_STATE;
}
break;
case HCI_DONE_STATE:
hci_state = HCI_SCANNING_STATE;
connectionClaimed = false;
hci_counter++;
if (hci_counter > 100) { // Wait until we have looped 100 times to make sure that the L2CAP connection has been started
hci_state = HCI_SCANNING_STATE;
l2capConnectionClaimed = false;
}
break;
case HCI_DISCONNECT_STATE:
@ -591,8 +594,8 @@ void BTD::HCI_task() {
}
void BTD::ACL_event_task() {
uint16_t MAX_BUFFER_SIZE = BULK_MAXPKTSIZE;
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &MAX_BUFFER_SIZE, l2capinbuf); // input on endpoint 2
uint16_t MAX_BUFFER_SIZE = BULK_MAXPKTSIZE;
uint8_t rcode = pUsb->inTransfer(bAddress, epInfo[ BTD_DATAIN_PIPE ].epAddr, &MAX_BUFFER_SIZE, l2capinbuf); // input on endpoint 2
if(!rcode) { // Check for errors
for (uint8_t i=0; i<BTD_NUMDEVICES; i++)
if (btService[i])
@ -605,7 +608,7 @@ void BTD::ACL_event_task() {
}
for (uint8_t i=0; i<BTD_NUMDEVICES; i++)
if (btService[i])
btService[i]->Poll();
btService[i]->Run();
}
/************************************************************/
@ -792,15 +795,16 @@ void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t
uint8_t rcode = pUsb->outTransfer(bAddress, epInfo[ BTD_DATAOUT_PIPE ].epAddr, (8 + nbytes), buf);
if(rcode) {
delay(100); // This small delay prevents it from overflowing if it fails
#ifdef DEBUG
Notify(PSTR("\r\nError sending L2CAP message: 0x"));
Notify(PSTR("\r\nError sending L2CAP message: 0x"));
PrintHex<uint8_t>(rcode);
Notify(PSTR(" - Channel ID: "));
Serial.print(channelHigh);
Notify(PSTR(" "));
Serial.print(channelLow);
#endif
}
}
}
void BTD::l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t* dcid, uint8_t* scid, uint8_t result) {
l2capoutbuf[0] = L2CAP_CMD_CONNECTION_RESPONSE; // Code

8
BTD.h
View file

@ -115,8 +115,8 @@
class BluetoothService { // All services should include this class
public:
virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services
virtual void Poll(); // Used to run the different state machines
virtual void Release(); // Used to reset the services
virtual void Run(); // Used to run the different state machines
virtual void Reset(); // Used to reset the services
virtual void disconnect(); // Used to disconnect both the L2CAP Channel and the HCI Connection
};
@ -152,8 +152,8 @@ public:
return 1; // ErrorregisterServiceClass
};
void claimConnection() { connectionClaimed = true; }; // This is used by the service to know when to store the device information
bool connectionClaimed;
void claimConnection() { l2capConnectionClaimed = true; }; // This is used by the service to know when to store the device information
bool l2capConnectionClaimed;
const char* btdName; // These are set by the SPP library
const char* btdPin;

135
PS3BT.cpp
View file

@ -58,7 +58,7 @@ pBtd(p) // pointer to USB class instance - mandatory
interrupt_dcid[0] = 0x41;//0x0041
interrupt_dcid[1] = 0x00;
Release();
Reset();
}
bool PS3BT::getButton(Button b) {
if (l2capinbuf == NULL)
@ -209,7 +209,7 @@ String PS3BT::getStatusString() {
return statusOutput;
}
}
void PS3BT::Release() {
void PS3BT::Reset() {
PS3Connected = false;
PS3MoveConnected = false;
PS3NavigationConnected = false;
@ -233,11 +233,9 @@ void PS3BT::disconnect() { //Use this void to disconnect any of the controllers
}
void PS3BT::ACLData(uint8_t* ACLData) {
for(uint8_t i = 0; i < BULK_MAXPKTSIZE; i++)
l2capinbuf[i] = ACLData[i];
if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if(((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_CTRL_PSM) || ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == HID_INTR_PSM)) {
if(!pBtd->connectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected) {
if(!pBtd->l2capConnectionClaimed && !PS3Connected && !PS3MoveConnected && !PS3NavigationConnected) {
if (ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if(((ACLData[12] | (ACLData[13] << 8)) == HID_CTRL_PSM) || ((ACLData[12] | (ACLData[13] << 8)) == HID_INTR_PSM)) {
pBtd->claimConnection(); // Claim that the incoming connection belongs to this service
hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
for(uint8_t i = 0; i < 30; i++)
@ -252,7 +250,9 @@ void PS3BT::ACLData(uint8_t* ACLData) {
}
}
}
if (((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000))) { //acl_handle_ok
if (((ACLData[0] | (ACLData[1] << 8)) == (hci_handle | 0x2000))) { //acl_handle_ok
for(uint8_t i = 0; i < BULK_MAXPKTSIZE; i++)
l2capinbuf[i] = ACLData[i];
if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U
if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
#ifdef DEBUG
@ -401,9 +401,10 @@ void PS3BT::ACLData(uint8_t* ACLData) {
#endif
}
}
L2CAP_task();
}
}
void PS3BT::Poll() {
void PS3BT::L2CAP_task() {
switch (l2cap_state) {
case L2CAP_EV_WAIT:
if (l2cap_connection_request_control_flag) {
@ -424,7 +425,7 @@ void PS3BT::Poll() {
#ifdef DEBUG
Notify(PSTR("\r\nHID Control Configuration Request"));
#endif
pBtd->l2cap_config_response(hci_handle,identifier, control_scid);
pBtd->l2cap_config_response(hci_handle,identifier, control_scid);
l2cap_state = L2CAP_EV_CONTROL_SUCCESS;
}
break;
@ -442,12 +443,12 @@ void PS3BT::Poll() {
#ifdef DEBUG
Notify(PSTR("\r\nHID Interrupt Incoming Connection Request"));
#endif
pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, PENDING);
pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, PENDING);
delay(1);
pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
pBtd->l2cap_connection_response(hci_handle,identifier, interrupt_dcid, interrupt_scid, SUCCESSFUL);
identifier++;
delay(1);
pBtd->l2cap_config_request(hci_handle,identifier, interrupt_scid);
pBtd->l2cap_config_request(hci_handle,identifier, interrupt_scid);
l2cap_state = L2CAP_EV_INTERRUPT_REQUEST;
}
@ -465,8 +466,8 @@ void PS3BT::Poll() {
if (l2cap_config_success_interrupt_flag) {
#ifdef DEBUG
Notify(PSTR("\r\nHID Interrupt Successfully Configured"));
#endif
if(remote_name[0] == 'M') { // First letter in Motion Controller ('M')
#endif
if(remote_name[0] == 'M') { // First letter in Motion Controller ('M')
for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed
l2capinbuf[i] = 0;
ButtonState = 0;
@ -478,55 +479,8 @@ void PS3BT::Poll() {
timer = millis();
}
break;
case L2CAP_EV_HID_ENABLE_SIXAXIS:
if(millis() - timer > 1000) { // loop 1 second before sending the command
for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed
l2capinbuf[i] = 0;
ButtonState = 0;
OldButtonState = 0;
enable_sixaxis();
for (uint8_t i = 15; i < 19; i++)
l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
l2cap_state = L2CAP_EV_HID_PS3_LED;
timer = millis();
}
break;
case L2CAP_EV_HID_PS3_LED:
if(millis() - timer > 1000) { // loop 1 second before sending the command
if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
setLedOn(LED1);
#ifdef DEBUG
Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"));
#endif
PS3Connected = true;
} else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N')
setLedOn(LED1); // This just turns LED constantly on, on the Navigation controller
#ifdef DEBUG
Notify(PSTR("\r\nNavigation Controller Enabled\r\n"));
#endif
PS3NavigationConnected = true;
} else if(remote_name[0] == 'M') { // First letter in Motion Controller ('M')
moveSetBulb(Red);
timerBulbRumble = millis();
#ifdef DEBUG
Notify(PSTR("\r\nMotion Controller Enabled\r\n"));
#endif
PS3MoveConnected = true;
}
l2cap_state = L2CAP_EV_DONE;
}
break;
case L2CAP_EV_DONE:
if (PS3MoveConnected) { //The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on
if (millis() - timerBulbRumble > 4000) { //Send at least every 4th second
HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);//The Bulb and rumble values, has to be written again and again, for it to stay turned on
timerBulbRumble = millis();
}
}
break;
/* These states are handled in Run() */
case L2CAP_EV_INTERRUPT_DISCONNECT:
if (l2cap_disconnect_response_interrupt_flag) {
@ -549,6 +503,59 @@ void PS3BT::Poll() {
l2cap_state = L2CAP_EV_WAIT;
}
break;
}
}
void PS3BT::Run() {
switch (l2cap_state) {
case L2CAP_EV_HID_ENABLE_SIXAXIS:
if(millis() - timer > 1000) { // loop 1 second before sending the command
for (uint8_t i = 0; i < BULK_MAXPKTSIZE; i++) // Reset l2cap in buffer as it sometimes read it as a button has been pressed
l2capinbuf[i] = 0;
ButtonState = 0;
OldButtonState = 0;
enable_sixaxis();
for (uint8_t i = 15; i < 19; i++)
l2capinbuf[i] = 0x7F; // Set the analog joystick values to center position
l2cap_state = L2CAP_EV_HID_PS3_LED;
timer = millis();
}
break;
case L2CAP_EV_HID_PS3_LED:
if(millis() - timer > 1000) { // loop 1 second before sending the command
if (remote_name[0] == 'P') { // First letter in PLAYSTATION(R)3 Controller ('P')
setLedOn(LED1);
#ifdef DEBUG
Notify(PSTR("\r\nDualshock 3 Controller Enabled\r\n"));
#endif
PS3Connected = true;
} else if (remote_name[0] == 'N') { // First letter in Navigation Controller ('N')
setLedOn(LED1); // This just turns LED constantly on, on the Navigation controller
#ifdef DEBUG
Notify(PSTR("\r\nNavigation Controller Enabled\r\n"));
#endif
PS3NavigationConnected = true;
} else if(remote_name[0] == 'M') { // First letter in Motion Controller ('M')
moveSetBulb(Red);
timerBulbRumble = millis();
#ifdef DEBUG
Notify(PSTR("\r\nMotion Controller Enabled\r\n"));
#endif
PS3MoveConnected = true;
}
l2cap_state = L2CAP_EV_DONE;
}
break;
case L2CAP_EV_DONE:
if (PS3MoveConnected) { //The Bulb and rumble values, has to be send at aproximatly every 5th second for it to stay on
if (millis() - timerBulbRumble > 4000) { //Send at least every 4th second
HIDMove_Command(HIDMoveBuffer, HID_BUFFERSIZE);//The Bulb and rumble values, has to be written again and again, for it to stay turned on
timerBulbRumble = millis();
}
}
break;
}
}

View file

@ -219,8 +219,8 @@ public:
// BluetoothService implementation
virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services
virtual void Poll(); // Used to run the state maschine
virtual void Release(); // Use this to reset the service
virtual void Run(); // Used to run part of the state maschine
virtual void Reset(); // Use this to reset the service
virtual void disconnect(); // Use this void to disconnect any of the controllers
/* PS3 Controller Commands */
@ -258,6 +258,8 @@ private:
/* mandatory members */
BTD *pBtd;
void L2CAP_task(); // L2CAP state machine
/* Variables filled from HCI event management */
int16_t hci_handle;
uint8_t remote_name[30]; // first 30 chars of remote name

30
SPP.cpp
View file

@ -50,17 +50,16 @@ pBtd(p) // Pointer to BTD class instance - mandatory
pBtd->btdName = name;
pBtd->btdPin = pin;
l2cap_sdp_state = L2CAP_SDP_WAIT;
l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
l2cap_event_flag = 0;
/* Set device cid for the SDP and RFCOMM channelse */
sdp_dcid[0] = 0x50; // 0x0050
sdp_dcid[1] = 0x00;
rfcomm_dcid[0] = 0x51; // 0x0051
rfcomm_dcid[1] = 0x00;
Reset();
}
void SPP::Release() {
void SPP::Reset() {
connected = false;
RFCOMMConnected = false;
SDPConnected = false;
@ -78,16 +77,18 @@ void SPP::disconnect(){
l2cap_event_flag = 0; // Reset flags
l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE;
}
void SPP::ACLData(uint8_t* l2capinbuf) {
if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if(((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) || ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM)) {
if(!pBtd->connectionClaimed && !connected && !RFCOMMConnected && !SDPConnected) {
void SPP::ACLData(uint8_t* ACLData) {
if(!pBtd->l2capConnectionClaimed && !connected && !RFCOMMConnected && !SDPConnected) {
if (ACLData[8] == L2CAP_CMD_CONNECTION_REQUEST) {
if(((ACLData[12] | (ACLData[13] << 8)) == SDP_PSM) || ((ACLData[12] | (ACLData[13] << 8)) == RFCOMM_PSM)) {
pBtd->claimConnection(); // Claim that the incoming connection belongs to this service
hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
}
}
}
if (((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000))) { // acl_handle_ok
if (((ACLData[0] | (ACLData[1] << 8)) == (hci_handle | 0x2000))) { // acl_handle_ok
for(uint8_t i = 0; i < BULK_MAXPKTSIZE; i++)
l2capinbuf[i] = ACLData[i];
if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U
if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
#ifdef DEBUG
@ -362,9 +363,11 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
PrintHex<uint8_t>(l2capinbuf[6]);
#endif
}
SDP_task();
RFCOMM_task();
}
}
void SPP::Poll() {
void SPP::Run() {
if(waitForLastCommand && (millis() - timer) > 100) { // We will only wait 100ms and see if the UIH Remote Port Negotiation Command is send, as some deviced don't send it
#ifdef DEBUG
Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"));
@ -372,9 +375,7 @@ void SPP::Poll() {
creditSent = false;
waitForLastCommand = false;
connected = true; // The RFCOMM channel is now established
}
SDP_task();
RFCOMM_task();
}
}
void SPP::SDP_task() {
switch (l2cap_sdp_state)
@ -773,7 +774,8 @@ void SPP::println(const __FlashStringHelper *ifsh) {
print(buf,size+2);
}
void SPP::println(void) {
print("\r\n");
uint8_t buf[2] = {'\r','\n'};
print(buf,2);
}
/* These must be used to print numbers */

5
SPP.h
View file

@ -99,8 +99,8 @@ public:
// BluetoothService implementation
virtual void ACLData(uint8_t* ACLData); // Used to pass acldata to the services
virtual void Poll(); // Used to run SDP_task() and RFCOMM_task()
virtual void Release(); // Use this to reset the service
virtual void Run(); // Used to establish the connection automatically
virtual void Reset(); // Use this to reset the service
virtual void disconnect(); // Used this void to disconnect the virtual serial port
bool connected;// Variable used to indicate if the connection is established
@ -141,6 +141,7 @@ private:
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 l2capinbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap in data
uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
/* L2CAP Channels */