merge with head

This commit is contained in:
Andrew J. Kroll 2013-05-16 17:03:44 -04:00
commit f1e01dbaab
20 changed files with 330 additions and 635 deletions

49
BTD.cpp
View file

@ -145,21 +145,25 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
if (rcode) if (rcode)
goto FailSetConfDescr; goto FailSetConfDescr;
if (PID == PS3_PID || PID == PS3NAVIGATION_PID) {
#ifdef DEBUG #ifdef DEBUG
if (PID == PS3_PID || PID == PS3NAVIGATION_PID) {
if (PID == PS3_PID) if (PID == PS3_PID)
Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80); Notify(PSTR("\r\nDualshock 3 Controller Connected"), 0x80);
else // must be a navigation controller else // It must be a navigation controller
Notify(PSTR("\r\nNavigation Controller Connected"), 0x80); Notify(PSTR("\r\nNavigation Controller Connected"), 0x80);
#endif } else // It must be a Motion controller
/* Set internal Bluetooth address */
setBdaddr(my_bdaddr);
} else { // It must be a Motion controller
#ifdef DEBUG
Notify(PSTR("\r\nMotion Controller Connected"), 0x80); Notify(PSTR("\r\nMotion Controller Connected"), 0x80);
#endif #endif
setMoveBdaddr(my_bdaddr);
} 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) {
#ifdef DEBUG
Notify(PSTR("\r\nPlease plug in the dongle before trying to pair with the PS3 Controller\n\rOr set the Bluetooth address in the constructor of the PS3BT class"), 0x80);
#endif
} else {
if (PID == PS3_PID || PID == PS3NAVIGATION_PID)
setBdaddr(my_bdaddr); // Set internal Bluetooth address
else
setMoveBdaddr(my_bdaddr); // Set internal Bluetooth address
#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--) {
@ -168,17 +172,18 @@ uint8_t BTD::Init(uint8_t parent, uint8_t port, bool lowspeed) {
} }
PrintHex<uint8_t > (my_bdaddr[0], 0x80); PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif #endif
}
rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value rcode = pUsb->setConf(bAddress, epInfo[ BTD_CONTROL_PIPE ].epAddr, 0); // Reset configuration value
pUsb->setAddr(bAddress, 0, 0); // Reset address pUsb->setAddr(bAddress, 0, 0); // Reset address
Release(); // Release device Release(); // Release device
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // return return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED; // Return
} else { } else {
num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations; num_of_conf = ((USB_DEVICE_DESCRIPTOR*)buf)->bNumConfigurations;
// check if attached device is a Bluetooth dongle and fill endpoint data structure // 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 // First interface in the configuration must have Bluetooth assigned Class/Subclass/Protocol
// and 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, // And 3 endpoints - interrupt-IN, bulk-IN, bulk-OUT, not necessarily in this order
// not necessarily in this order
for (uint8_t i = 0; i < num_of_conf; i++) { 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); ConfigDescParser<USB_CLASS_WIRELESS_CTRL, WI_SUBCLASS_RF, WI_PROTOCOL_BT, CP_MASK_COMPARE_ALL> confDescrParser(this);
rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser); rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
@ -261,7 +266,7 @@ void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
//ErrorMessage<uint8_t>(PSTR("Iface Num"),iface); //ErrorMessage<uint8_t>(PSTR("Iface Num"),iface);
//ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt); //ErrorMessage<uint8_t>(PSTR("Alt.Set"),alt);
if (alt) // wrong interface - by BT spec, no alt setting if (alt) // Wrong interface - by BT spec, no alt setting
return; return;
bConfNum = conf; bConfNum = conf;
@ -271,7 +276,7 @@ void BTD::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto
index = BTD_EVENT_PIPE; index = BTD_EVENT_PIPE;
else { else {
if ((pep->bmAttributes & 0x02) == 2) // bulk endpoint found if ((pep->bmAttributes & 0x02) == 2) // Bulk endpoint found
index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE; index = ((pep->bEndpointAddress & 0x80) == 0x80) ? BTD_DATAIN_PIPE : BTD_DATAOUT_PIPE;
else else
return; return;
@ -383,7 +388,7 @@ void BTD::HCI_event_task() {
if (hcibuf[2]) { // Check that there is more than zero responses if (hcibuf[2]) { // Check that there is more than zero responses
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nNumber of responses: "), 0x80); Notify(PSTR("\r\nNumber of responses: "), 0x80);
Serial.print(hcibuf[2]); Notify(hcibuf[2], 0x80);
#endif #endif
for (uint8_t i = 0; i < hcibuf[2]; i++) { for (uint8_t i = 0; i < hcibuf[2]; i++) {
if ((hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x04 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x25 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00) || (hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x08 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x05 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00)) { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html and http://wiibrew.org/wiki/Wiimote#SDP_information if ((hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x04 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x25 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00) || (hcibuf[4 + 8 * hcibuf[2] + 3 * i] == 0x08 && hcibuf[5 + 8 * hcibuf[2] + 3 * i] == 0x05 && hcibuf[6 + 8 * hcibuf[2] + 3 * i] == 0x00)) { // See http://bluetooth-pentest.narod.ru/software/bluetooth_class_of_device-service_generator.html and http://wiibrew.org/wiki/Wiimote#SDP_information
@ -470,7 +475,7 @@ void BTD::HCI_event_task() {
} else if (btdPin != NULL) { } else if (btdPin != NULL) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80); Notify(PSTR("\r\nBluetooth pin is set too: "), 0x80);
Serial.print(btdPin); NotifyStr(btdPin, 0x80);
#endif #endif
hci_pin_code_request_reply(); hci_pin_code_request_reply();
} else { } else {
@ -600,7 +605,7 @@ void BTD::HCI_task() {
if (hci_cmd_complete) { if (hci_cmd_complete) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nThe name is set to: "), 0x80); Notify(PSTR("\r\nThe name is set to: "), 0x80);
Serial.print(btdName); NotifyStr(btdName, 0x80);
#endif #endif
hci_state = HCI_CHECK_WII_SERVICE; hci_state = HCI_CHECK_WII_SERVICE;
} }
@ -691,7 +696,7 @@ void BTD::HCI_task() {
for (uint8_t i = 0; i < 30; i++) { for (uint8_t i = 0; i < 30; i++) {
if (remote_name[i] == NULL) if (remote_name[i] == NULL)
break; break;
Serial.write(remote_name[i]); Notifyc(remote_name[i], 0x80);
} }
#endif #endif
if (strncmp((const char*)remote_name, "Nintendo", 8) == 0) { if (strncmp((const char*)remote_name, "Nintendo", 8) == 0) {
@ -1082,9 +1087,9 @@ void BTD::L2CAP_Command(uint16_t handle, uint8_t* data, uint8_t nbytes, uint8_t
Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80); Notify(PSTR("\r\nError sending L2CAP message: 0x"), 0x80);
PrintHex<uint8_t > (rcode, 0x80); PrintHex<uint8_t > (rcode, 0x80);
Notify(PSTR(" - Channel ID: "), 0x80); Notify(PSTR(" - Channel ID: "), 0x80);
Serial.print(channelHigh); PrintHex<uint8_t > (channelHigh, 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
Serial.print(channelLow); PrintHex<uint8_t > (channelLow, 0x80);
#endif #endif
} }
} }

View file

@ -16,7 +16,7 @@
*/ */
#include "PS3BT.h" #include "PS3BT.h"
#define DEBUG // Uncomment to print data for debugging //#define DEBUG // Uncomment to print data for debugging -- NO! see message.h
//#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 PS3 Controllers //#define PRINTREPORT // Uncomment to print the report send by the PS3 Controllers
@ -258,7 +258,7 @@ void PS3BT::ACLData(uint8_t* ACLData) {
#ifdef DEBUG #ifdef DEBUG
if (pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle if (pBtd->hci_version < 3) { // Check the HCI Version of the Bluetooth dongle
Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80); Notify(PSTR("\r\nYour dongle may not support reading the analog buttons, sensors and status\r\nYour HCI Version is: "), 0x80);
Serial.print(pBtd->hci_version); Notify(pBtd->hci_version, 0x80);
Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80); Notify(PSTR("\r\nBut should be at least 3\r\nThis means that it doesn't support Bluetooth Version 2.0+EDR"), 0x80);
} }
#endif #endif
@ -273,15 +273,15 @@ void PS3BT::ACLData(uint8_t* ACLData) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80); Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
PrintHex<uint8_t > (l2capinbuf[13], 0x80); PrintHex<uint8_t > (l2capinbuf[13], 0x80);
Serial.print(" "); Notify(PSTR(" "), 0x80);
PrintHex<uint8_t > (l2capinbuf[12], 0x80); PrintHex<uint8_t > (l2capinbuf[12], 0x80);
Serial.print(" Data: "); Notify(PSTR(" Data: "), 0x80);
PrintHex<uint8_t > (l2capinbuf[17], 0x80); PrintHex<uint8_t > (l2capinbuf[17], 0x80);
Serial.print(" "); Notify(PSTR(" "), 0x80);
PrintHex<uint8_t > (l2capinbuf[16], 0x80); PrintHex<uint8_t > (l2capinbuf[16], 0x80);
Serial.print(" "); Notify(PSTR(" "), 0x80);
PrintHex<uint8_t > (l2capinbuf[15], 0x80); PrintHex<uint8_t > (l2capinbuf[15], 0x80);
Serial.print(" "); Notify(PSTR(" "), 0x80);
PrintHex<uint8_t > (l2capinbuf[14], 0x80); PrintHex<uint8_t > (l2capinbuf[14], 0x80);
#endif #endif
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) { } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
@ -311,20 +311,20 @@ void PS3BT::ACLData(uint8_t* ACLData) {
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Serial.print("\r\nHID Control Configuration Complete"); //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS; l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS;
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Serial.print("\r\nHID Interrupt Configuration Complete"); //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS; l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS;
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Serial.print("\r\nHID Control Configuration Request"); //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_REQUEST; l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_REQUEST;
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Serial.print("\r\nHID Interrupt Configuration Request"); //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST; l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_REQUEST;
} }
@ -346,11 +346,11 @@ void PS3BT::ACLData(uint8_t* ACLData) {
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
//Serial.print("\r\nDisconnect Response: Control Channel"); //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE;
} else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { } else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
//Serial.print("\r\nDisconnect Response: Interrupt Channel"); //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE;
} }
@ -362,7 +362,7 @@ void PS3BT::ACLData(uint8_t* ACLData) {
} }
#endif #endif
} else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
//Serial.print("\r\nL2CAP Interrupt"); //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
if (PS3Connected || PS3MoveConnected || PS3NavigationConnected) { if (PS3Connected || PS3MoveConnected || PS3NavigationConnected) {
/* Read Report */ /* Read Report */
if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
@ -382,9 +382,9 @@ void PS3BT::ACLData(uint8_t* ACLData) {
#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send by the PS3 Controllers
for (uint8_t i = 10; i < 58; i++) { for (uint8_t i = 10; i < 58; i++) {
PrintHex<uint8_t > (l2capinbuf[i], 0x80); PrintHex<uint8_t > (l2capinbuf[i], 0x80);
Serial.print(" "); Notify(PSTR(" "), 0x80);
} }
Serial.println(); Notify(PSTR("\r\n"), 0x80);
#endif #endif
} }
} }
@ -597,7 +597,7 @@ void PS3BT::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t leftD
} }
void PS3BT::setLedRaw(uint8_t value) { void PS3BT::setLedRaw(uint8_t value) {
HIDBuffer[11] = value; HIDBuffer[11] = value << 1;
HID_Command(HIDBuffer, HID_BUFFERSIZE); HID_Command(HIDBuffer, HID_BUFFERSIZE);
} }
void PS3BT::setLedOff(LED a) { void PS3BT::setLedOff(LED a) {

View file

@ -209,7 +209,7 @@ uint8_t PS3USB::Init(uint8_t parent, uint8_t port, bool lowspeed) {
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(":"); Notify(PSTR(":"), 0x80);
} }
PrintHex<uint8_t > (my_bdaddr[0], 0x80); PrintHex<uint8_t > (my_bdaddr[0], 0x80);
#endif #endif
@ -306,9 +306,9 @@ void PS3USB::printReport() { //Uncomment "#define PRINTREPORT" to print the repo
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(" "); Notify(PSTR(" "), 0x80);
} }
Serial.println(); Notify(PSTR("\r\n"), 0x80);
#endif #endif
} }
@ -452,7 +452,7 @@ void PS3USB::setRumbleOn(uint8_t rightDuration, uint8_t rightPower, uint8_t left
} }
void PS3USB::setLedRaw(uint8_t value) { void PS3USB::setLedRaw(uint8_t value) {
writeBuf[9] = value; writeBuf[9] = value << 1;
PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE); PS3_Command(writeBuf, PS3_REPORT_BUFFER_SIZE);
} }

View file

@ -18,10 +18,13 @@ For more information about the hardware see the [Hardware Manual](http://www.cir
# Developed By # Developed By
* <b>Oleg Mazurov, Circuits@Home</b> - <mazurov@circuitsathome.com> * __Oleg Mazurov, Circuits@Home__ - <mazurov@circuitsathome.com>
* Developer of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries * __Alexei Glushchenko, Circuits@Home__ - <alex-gl@mail.ru>
* <b>Kristian Lauszus, TKJ Electronics</b> - <kristianl@tkjelectronics.com> * Developers of the USB Core, HID, FTDI, ADK, ACM, and PL2303 libraries
* __Kristian Lauszus, TKJ Electronics__ - <kristianl@tkjelectronics.com>
* Developer of the BTD, SPP, PS3, Wii, and Xbox libraries * Developer of the BTD, SPP, PS3, Wii, and Xbox libraries
* __Andrew Kroll__ - <xxxajk@gmail.com>
* Major contributor to mass storage code
# How to include the library # How to include the library

287
SPP.cpp
View file

@ -67,6 +67,7 @@ void SPP::Reset() {
l2cap_sdp_state = L2CAP_SDP_WAIT; l2cap_sdp_state = L2CAP_SDP_WAIT;
l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
l2cap_event_flag = 0; l2cap_event_flag = 0;
sppIndex = 0;
} }
void SPP::disconnect() { void SPP::disconnect() {
@ -139,20 +140,20 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
//Serial.print("\r\nSDP Configuration Complete"); //Notify(PSTR("\r\nSDP Configuration Complete"), 0x80);
l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_SUCCESS; l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_SUCCESS;
} else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
//Serial.print("\r\nRFCOMM Configuration Complete"); //Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80);
l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS;
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) { if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
//Serial.print("\r\nSDP Configuration Request"); //Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_REQUEST; l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_REQUEST;
} else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) { } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
//Serial.print("\r\nRFCOMM Configuration Request"); //Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_REQUEST;
} }
@ -168,11 +169,11 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
if (l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) { if (l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {
//Serial.print("\r\nDisconnect Response: SDP Channel"); //Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE;
} else if (l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) { } else if (l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) {
//Serial.print("\r\nDisconnect Response: RFCOMM Channel"); //Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE;
} }
@ -207,7 +208,8 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state
firstMessage = true; firstMessage = true;
} }
} else { } else
serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nUUID: "), 0x80); Notify(PSTR("\r\nUUID: "), 0x80);
uint16_t uuid; uint16_t uuid;
@ -226,8 +228,6 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
#endif #endif
serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported
}
} }
} else if (l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM } else if (l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM
rfcommChannel = l2capinbuf[8] & 0xF8; rfcommChannel = l2capinbuf[8] & 0xF8;
@ -241,20 +241,20 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nRFCOMM Channel: "), 0x80); Notify(PSTR("\r\nRFCOMM Channel: "), 0x80);
Serial.print(rfcommChannel >> 3, HEX); PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
Notify(PSTR(" Direction: "), 0x80); Notify(PSTR(" Direction: "), 0x80);
Serial.print(rfcommDirection >> 2, HEX); PrintHex<uint8_t > (rfcommDirection >> 2, 0x80);
Notify(PSTR(" CommandResponse: "), 0x80); Notify(PSTR(" CommandResponse: "), 0x80);
Serial.print(rfcommCommandResponse >> 1, HEX); PrintHex<uint8_t > (rfcommCommandResponse >> 1, 0x80);
Notify(PSTR(" ChannelType: "), 0x80); Notify(PSTR(" ChannelType: "), 0x80);
Serial.print(rfcommChannelType, HEX); PrintHex<uint8_t > (rfcommChannelType, 0x80);
Notify(PSTR(" PF_BIT: "), 0x80); Notify(PSTR(" PF_BIT: "), 0x80);
Serial.print(rfcommPfBit, HEX); PrintHex<uint8_t > (rfcommPfBit, 0x80);
#endif #endif
if (rfcommChannelType == RFCOMM_DISC) { if (rfcommChannelType == RFCOMM_DISC) {
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80); Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80);
Serial.print(rfcommChannel >> 3, HEX); PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
#endif #endif
connected = false; connected = false;
sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
@ -271,15 +271,15 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
} }
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80); Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80);
Serial.print(rfcommAvailable); Notify(rfcommAvailable, 0x80);
if (offset) { if (offset) {
Notify(PSTR(" - Credit: 0x"), 0x80); Notify(PSTR(" - Credit: 0x"), 0x80);
Serial.print(l2capinbuf[11], HEX); PrintHex<uint8_t > (l2capinbuf[11], 0x80);
} }
#endif #endif
#ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth
for (uint8_t i = 0; i < length; i++) for (uint8_t i = 0; i < length; i++)
Serial.write(l2capinbuf[i + 11 + offset]); Notifyc(l2capinbuf[i + 11 + offset], 0x80);
#endif #endif
} else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
#ifdef DEBUG #ifdef DEBUG
@ -382,6 +382,7 @@ void SPP::ACLData(uint8_t* l2capinbuf) {
waitForLastCommand = false; waitForLastCommand = false;
creditSent = false; creditSent = false;
connected = true; // The RFCOMM channel is now established connected = true; // The RFCOMM channel is now established
sppIndex = 0;
} }
#ifdef DEBUG #ifdef DEBUG
else if (rfcommChannelType != RFCOMM_DISC) { else if (rfcommChannelType != RFCOMM_DISC) {
@ -414,7 +415,9 @@ void SPP::Run() {
creditSent = false; creditSent = false;
waitForLastCommand = false; waitForLastCommand = false;
connected = true; // The RFCOMM channel is now established connected = true; // The RFCOMM channel is now established
sppIndex = 0;
} }
send(); // Send all bytes currently in the buffer
} }
void SPP::SDP_task() { void SPP::SDP_task() {
@ -681,7 +684,7 @@ void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) {
void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) { void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) {
l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
l2capoutbuf[2] = length << 1 | 0x01; // Length and format (allways 0x01 bytes format) l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format)
uint8_t i = 0; uint8_t i = 0;
for (; i < length; i++) for (; i < length; i++)
l2capoutbuf[i + 3] = data[i]; l2capoutbuf[i + 3] = data[i];
@ -689,7 +692,7 @@ void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t cha
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR(" - RFCOMM Data: "), 0x80); Notify(PSTR(" - RFCOMM Data: "), 0x80);
for (i = 0; i < length + 4; i++) { for (i = 0; i < length + 4; i++) {
Serial.print(l2capoutbuf[i], HEX); PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
#endif #endif
@ -705,7 +708,7 @@ void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR(" - RFCOMM Credit Data: "), 0x80); Notify(PSTR(" - RFCOMM Credit Data: "), 0x80);
for (uint8_t i = 0; i < 5; i++) { for (uint8_t i = 0; i < 5; i++) {
Serial.print(l2capoutbuf[i], HEX); PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
Notify(PSTR(" "), 0x80); Notify(PSTR(" "), 0x80);
} }
#endif #endif
@ -726,66 +729,21 @@ uint8_t SPP::calcFcs(uint8_t *data) {
} }
/* Serial commands */ /* Serial commands */
void SPP::print(const String &str) { size_t SPP::write(uint8_t data) {
if (!connected) return write(&data,1);
return;
int16_t stringLength = str.length(); // This will be used to store the characters that still needs to be sent
uint8_t length; // This is the length of the string we are sending
uint8_t offset = 0; // This is used to keep track of where we are in the string
l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
do {
if (stringLength > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger that the outgoing puffer
length = sizeof (l2capoutbuf) - 4;
else
length = stringLength;
l2capoutbuf[2] = length << 1 | 1; // Length
uint8_t i = 0;
for (; i < length; i++)
l2capoutbuf[i + 3] = str[i + offset];
l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
RFCOMM_Command(l2capoutbuf, length + 4);
stringLength -= length;
offset += length; // Increment the offset
} while (stringLength); // We will run this loop until this variable is less than 0
} }
void SPP::print(const char* str) { size_t SPP::write(const uint8_t* data, size_t size) {
if (!connected) for(uint8_t i = 0; i < size; i++) {
return; if(sppIndex >= sizeof(sppOutputBuffer)/sizeof(sppOutputBuffer[0]))
int16_t stringLength = strlen(str); // This will be used to store the characters that still needs to be sent send(); // Send the current data in the buffer
uint8_t length; // This is the length of the string we are sending sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function
uint8_t offset = 0; // This is used to keep track of where we are in the string }
return size;
l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
do {
if (stringLength > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger that the outgoing puffer
length = sizeof (l2capoutbuf) - 4;
else
length = stringLength;
l2capoutbuf[2] = length << 1 | 1; // Length
uint8_t i = 0;
for (; i < length; i++)
l2capoutbuf[i + 3] = str[i + offset];
l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
RFCOMM_Command(l2capoutbuf, length + 4);
stringLength -= length;
offset += length; // Increment the offset
} while (stringLength); // We will run this loop until this variable is less than 0
} }
void SPP::print(uint8_t* array, int16_t stringLength) { void SPP::send() {
if (!connected) if (!connected || !sppIndex)
return; return;
uint8_t length; // This is the length of the string we are sending uint8_t length; // This is the length of the string we are sending
uint8_t offset = 0; // This is used to keep track of where we are in the string uint8_t offset = 0; // This is used to keep track of where we are in the string
@ -793,177 +751,42 @@ void SPP::print(uint8_t* array, int16_t stringLength) {
l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
do { while (sppIndex) { // We will run this while loop until this variable is 0
if (stringLength > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger that the outgoing puffer if (sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer
length = sizeof (l2capoutbuf) - 4; length = sizeof (l2capoutbuf) - 4;
else else
length = stringLength; length = sppIndex;
l2capoutbuf[2] = length << 1 | 1; // Length l2capoutbuf[2] = length << 1 | 1; // Length
uint8_t i = 0; uint8_t i = 0;
for (; i < length; i++) for (; i < length; i++)
l2capoutbuf[i + 3] = array[i + offset]; l2capoutbuf[i + 3] = sppOutputBuffer[i + offset];
l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
RFCOMM_Command(l2capoutbuf, length + 4); RFCOMM_Command(l2capoutbuf, length + 4);
stringLength -= length; sppIndex -= length;
offset += length; // Increment the offset offset += length; // Increment the offset
} while (stringLength); // We will run this loop until this variable is less than 0
}
void SPP::println(const String &str) {
String output = str + "\r\n";
print(output);
}
void SPP::println(const char* str) {
char output[strlen(str) + 3];
strcpy(output, str);
strcat(output, "\r\n");
print(output);
}
void SPP::println(uint8_t data) {
uint8_t buf[3] = {data, '\r', '\n'};
print(buf, 3);
}
void SPP::println(uint8_t* array, uint8_t length) {
uint8_t buf[length + 2];
memcpy(buf, array, length);
buf[length] = '\r';
buf[length + 1] = '\n';
print(buf, length + 2);
}
void SPP::printFlashString(const __FlashStringHelper *ifsh, bool newline) {
const char PROGMEM *p = (const char PROGMEM *)ifsh;
uint8_t size = 0;
while (1) { // Calculate the size of the string
uint8_t c = pgm_read_byte(p + size);
if (c == 0)
break;
size++;
}
uint8_t buf[size + 2]; // Add two extra in case it needs to print a newline and carriage return
for (uint8_t i = 0; i < size; i++)
buf[i] = pgm_read_byte(p++);
if (newline) {
buf[size] = '\r';
buf[size + 1] = '\n';
print(buf, size + 2);
} else
print(buf, size);
}
void SPP::println(void) {
uint8_t buf[2] = {'\r', '\n'};
print(buf, 2);
}
/* These must be used to print numbers */
void SPP::printNumber(uint32_t n) {
char output[11];
intToString(n, output);
print(output);
}
void SPP::printNumberln(uint32_t n) {
char output[13];
intToString(n, output);
strcat(output, "\r\n");
print(output);
}
void SPP::printNumber(int32_t n) {
char output[12];
intToString(n, output);
print(output);
}
void SPP::printNumberln(int32_t n) {
char output[14];
intToString(n, output);
strcat(output, "\r\n");
print(output);
}
void SPP::intToString(int32_t input, char* output) {
if (input < 0) {
char buf[11];
intToString((uint32_t)(input*-1), buf);
strcpy(output, "-");
strcat(output, buf);
} else
intToString((uint32_t)input, output);
}
void SPP::intToString(uint32_t input, char* output) {
uint32_t temp = input;
uint8_t digits = 0;
while (temp) {
temp /= 10;
digits++;
}
if (digits == 0)
strcpy(output, "0");
else {
for (uint8_t i = 1; i <= digits; i++) {
output[digits - i] = input % 10 + '0'; // Get number and convert to ASCII Character
input /= 10;
}
output[digits] = '\0'; // Add null character
} }
} }
void SPP::printNumber(double n, uint8_t digits) { int SPP::available(void) {
char output[13 + digits]; return rfcommAvailable;
doubleToString(n, output, digits); };
print(output);
void SPP::flush(void) {
rfcommAvailable = 0;
} }
void SPP::printNumberln(double n, uint8_t digits) { int SPP::peek(void) {
char output[15 + digits];
doubleToString(n, output, digits);
strcat(output, "\r\n");
print(output);
}
void SPP::doubleToString(double input, char* output, uint8_t digits) {
char buffer[13 + digits];
if (input < 0) {
strcpy(output, "-");
input = -input;
} else
strcpy(output, "");
// Round correctly
double rounding = 0.5;
for (uint8_t i = 0; i < digits; i++)
rounding /= 10.0;
input += rounding;
uint32_t intpart = (uint32_t)input;
intToString(intpart, buffer); // Convert to string
strcat(output, buffer);
strcat(output, ".");
double fractpart = (input - (double)intpart);
fractpart *= pow(10, digits);
for (uint8_t i = 1; i < digits; i++) { // Put zeros in front of number
if (fractpart < pow(10, digits - i)) {
strcat(output, "0");
}
}
intToString((uint32_t)fractpart, buffer); // Convert to string
strcat(output, buffer);
}
uint8_t SPP::read() {
if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer
return 0; return -1;
return rfcommDataBuffer[0];
}
int SPP::read(void) {
if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer
return -1;
uint8_t output = rfcommDataBuffer[0]; uint8_t output = rfcommDataBuffer[0];
for (uint8_t i = 1; i < rfcommAvailable; i++) for (uint8_t i = 1; i < rfcommAvailable; i++)
rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left
@ -974,7 +797,7 @@ uint8_t SPP::read() {
sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit
#ifdef EXTRADEBUG #ifdef EXTRADEBUG
Notify(PSTR("\r\nSent "), 0x80); Notify(PSTR("\r\nSent "), 0x80);
Serial.print(sizeof (rfcommDataBuffer)); Notify((uint8_t)sizeof (rfcommDataBuffer), 0x80);
Notify(PSTR(" more credit"), 0x80); Notify(PSTR(" more credit"), 0x80);
#endif #endif
} }

260
SPP.h
View file

@ -68,7 +68,7 @@
//#define RFCOMM_DM 0x0F //#define RFCOMM_DM 0x0F
#define RFCOMM_DISC 0x43 #define RFCOMM_DISC 0x43
#define extendAddress 0x01 // Allways 1 #define extendAddress 0x01 // Always 1
// Multiplexer message types // Multiplexer message types
#define BT_RFCOMM_PN_CMD 0x83 #define BT_RFCOMM_PN_CMD 0x83
@ -90,7 +90,7 @@
*/ */
/** 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 Stream {
public: public:
/** /**
* Constructor for the SPP class. * Constructor for the SPP class.
@ -100,6 +100,16 @@ public:
*/ */
SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234"); SPP(BTD *p, const char* name = "Arduino", const char* pin = "1234");
/**
* Used to provide Boolean tests for the class.
* @return Return true if SPP communication is connected.
*/
operator bool() {
return connected;
}
/** Variable used to indicate if the connection is established. */
bool connected;
/** @name BluetoothService implementation */ /** @name BluetoothService implementation */
/** /**
* Used to pass acldata to the services. * Used to pass acldata to the services.
@ -114,221 +124,45 @@ public:
virtual void disconnect(); virtual void disconnect();
/**@}*/ /**@}*/
/** Variable used to indicate if the connection is established. */
bool connected;
/** @name Serial port profile (SPP) Print functions */ /** @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);
/**
* Used to send single bytes.
* @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);
/**
* Used to send arrays.
* @param array Array to send.
* @param length Number of bytes to send.
*/
void print(uint8_t* array, int16_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. */
void println(void);
/**
* Used to print unsigned integers.
* @param n Unsigned integer to send.
*/
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.
* @param n Unsigned integer to send.
*/
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. * Get number of bytes waiting to be read.
* @return Return the number of bytes ready to be read. * @return Return the number of bytes ready to be read.
*/ */
uint8_t available() { virtual int available(void);
return rfcommAvailable; /** Discard all the bytes in the buffer. */
}; virtual void flush(void);
/**
* Used to read the next value in the buffer without advancing to the next one.
* @return Return the byte. Will return -1 if no bytes are available.
*/
virtual int peek(void);
/** /**
* Used to read the buffer. * Used to read the buffer.
* @return Return the byte. Will return 0 if no byte is available. * @return Return the byte. Will return -1 if no bytes are available.
*/ */
uint8_t read(); virtual int read(void);
/**
/** Discard all the bytes in the buffer. */ * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
void flush() { * @param data The byte to write.
rfcommAvailable = 0; * @return Return the number of bytes written.
}; */
virtual size_t write(uint8_t data);
/**
* Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
* @param data The data array to send.
* @param size Size of the data.
* @return Return the number of bytes written.
*/
virtual size_t write(const uint8_t* data, size_t size);
/** Pull in write(const char *str) from Print */
using Print::write;
/**
* This will send all the bytes in the buffer.
* This is called whenever Usb.Task() is called,
* but can also be called via this function.
*/
void send(void);
/**@}*/ /**@}*/
private: private:
@ -341,10 +175,10 @@ private:
uint16_t hci_handle; // The HCI Handle for the connection uint16_t hci_handle; // The HCI Handle for the connection
/* Variables used by L2CAP state maschines */ /* Variables used by L2CAP state machines */
uint8_t l2cap_sdp_state; uint8_t l2cap_sdp_state;
uint8_t l2cap_rfcomm_state; uint8_t l2cap_rfcomm_state;
uint16_t l2cap_event_flag; // l2cap flags of received bluetooth events uint16_t l2cap_event_flag; // l2cap flags of received Bluetooth events
uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
@ -358,7 +192,7 @@ private:
/* RFCOMM Variables */ /* RFCOMM Variables */
uint8_t rfcommChannel; uint8_t rfcommChannel;
uint8_t rfcommChannelConnection; // This is the channel the SPP chanel will be running at uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at
uint8_t rfcommDirection; uint8_t rfcommDirection;
uint8_t rfcommCommandResponse; uint8_t rfcommCommandResponse;
uint8_t rfcommChannelType; uint8_t rfcommChannelType;
@ -369,6 +203,8 @@ private:
bool creditSent; bool creditSent;
uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data
uint8_t sppIndex;
uint8_t rfcommAvailable; uint8_t rfcommAvailable;
bool firstMessage; // Used to see if it's the first SDP request received bool firstMessage; // Used to see if it's the first SDP request received

40
Wii.cpp
View file

@ -161,13 +161,13 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) { } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_RESPONSE) {
if (((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success if (((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) && ((l2capinbuf[18] | (l2capinbuf[19] << 8)) == SUCCESSFUL)) { // Success
if (l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { // Success if (l2capinbuf[14] == control_dcid[0] && l2capinbuf[15] == control_dcid[1]) { // Success
//Serial.print("\r\nHID Control Connection Complete"); //Notify(PSTR("\r\nHID Control Connection Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
control_scid[0] = l2capinbuf[12]; control_scid[0] = l2capinbuf[12];
control_scid[1] = l2capinbuf[13]; control_scid[1] = l2capinbuf[13];
l2cap_event_flag |= L2CAP_FLAG_CONTROL_CONNECTED; l2cap_event_flag |= L2CAP_FLAG_CONTROL_CONNECTED;
} else if (l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) { } else if (l2capinbuf[14] == interrupt_dcid[0] && l2capinbuf[15] == interrupt_dcid[1]) {
//Serial.print("\r\nHID Interrupt Connection Complete"); //Notify(PSTR("\r\nHID Interrupt Connection Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
interrupt_scid[0] = l2capinbuf[12]; interrupt_scid[0] = l2capinbuf[12];
interrupt_scid[1] = l2capinbuf[13]; interrupt_scid[1] = l2capinbuf[13];
@ -201,21 +201,21 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) { } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Serial.print("\r\nHID Control Configuration Complete"); //Notify(PSTR("\r\nHID Control Configuration Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS; l2cap_event_flag |= L2CAP_FLAG_CONFIG_CONTROL_SUCCESS;
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Serial.print("\r\nHID Interrupt Configuration Complete"); //Notify(PSTR("\r\nHID Interrupt Configuration Complete"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS; l2cap_event_flag |= L2CAP_FLAG_CONFIG_INTERRUPT_SUCCESS;
} }
} }
} else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) { } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) { if (l2capinbuf[12] == control_dcid[0] && l2capinbuf[13] == control_dcid[1]) {
//Serial.print("\r\nHID Control Configuration Request"); //Notify(PSTR("\r\nHID Control Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], control_scid);
} else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) { } else if (l2capinbuf[12] == interrupt_dcid[0] && l2capinbuf[13] == interrupt_dcid[1]) {
//Serial.print("\r\nHID Interrupt Configuration Request"); //Notify(PSTR("\r\nHID Interrupt Configuration Request"), 0x80);
pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid); pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], interrupt_scid);
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) { } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
@ -236,11 +236,11 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} }
} else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) { } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) { if (l2capinbuf[12] == control_scid[0] && l2capinbuf[13] == control_scid[1]) {
//Serial.print("\r\nDisconnect Response: Control Channel"); //Notify(PSTR("\r\nDisconnect Response: Control Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_CONTROL_RESPONSE;
} else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) { } else if (l2capinbuf[12] == interrupt_scid[0] && l2capinbuf[13] == interrupt_scid[1]) {
//Serial.print("\r\nDisconnect Response: Interrupt Channel"); //Notify(PSTR("\r\nDisconnect Response: Interrupt Channel"), 0x80);
identifier = l2capinbuf[9]; identifier = l2capinbuf[9];
l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE; l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_INTERRUPT_RESPONSE;
} }
@ -253,7 +253,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
} }
#endif #endif
} else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt } else if (l2capinbuf[6] == interrupt_dcid[0] && l2capinbuf[7] == interrupt_dcid[1]) { // l2cap_interrupt
//Serial.print("\r\nL2CAP Interrupt"); //Notify(PSTR("\r\nL2CAP Interrupt"), 0x80);
if (wiimoteConnected) { if (wiimoteConnected) {
if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT if (l2capinbuf[8] == 0xA1) { // HID_THDR_DATA_INPUT
if ((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons if ((l2capinbuf[9] >= 0x20 && l2capinbuf[9] <= 0x22) || (l2capinbuf[9] >= 0x30 && l2capinbuf[9] <= 0x37) || l2capinbuf[9] == 0x3e || l2capinbuf[9] == 0x3f) { // These reports include the buttons
@ -481,18 +481,18 @@ void WII::ACLData(uint8_t* l2capinbuf) {
timer = micros(); timer = micros();
/* /*
// Uncomment these lines to tune the gyro scale variabels // Uncomment these lines to tune the gyro scale variabels
Serial.print("\r\ngyroYaw: "); Notify(PSTR("\r\ngyroYaw: "), 0x80);
Serial.print(gyroYaw); Notify(gyroYaw, 0x80);
Serial.print("\tgyroRoll: "); Notify(PSTR("\tgyroRoll: "), 0x80);
Serial.print(gyroRoll); Notify(gyroRoll, 0x80);
Serial.print("\tgyroPitch: "); Notify(PSTR("\tgyroPitch: "), 0x80);
Serial.print(gyroPitch); Notify(gyroPitch, 0x80);
*/ */
/* /*
Serial.print("\twiimoteRoll: "); Notify(PSTR("\twiimoteRoll: "), 0x80);
Serial.print(wiimoteRoll); Notify(wiimoteRoll, 0x80);
Serial.print("\twiimotePitch: "); Notify(PSTR("\twiimotePitch: "), 0x80);
Serial.print(wiimotePitch); Notify(wiimotePitch, 0x80);
*/ */
} else { } else {
if ((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values if ((micros() - timer) > 1000000) { // Loop for 1 sec before resetting the values
@ -567,7 +567,7 @@ void WII::ACLData(uint8_t* l2capinbuf) {
#ifdef DEBUG #ifdef DEBUG
default: default:
Notify(PSTR("\r\nUnknown Report type: "), 0x80); Notify(PSTR("\r\nUnknown Report type: "), 0x80);
Serial.print(l2capinbuf[9], HEX); PrintHex<uint8_t > (l2capinbuf[9], 0x80);
break; break;
#endif #endif
} }

5
Wii.h
View file

@ -131,6 +131,11 @@ public:
/**@}*/ /**@}*/
/** @name Wii Controller functions */ /** @name Wii Controller functions */
/** Call this to start the paring sequence with a controller */
void pair(void) {
if(pBtd)
pBtd->pairWithWiimote();
}
/** /**
* 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.

View file

@ -286,7 +286,7 @@ uint8_t XBOXRECV::Poll() {
if (bufferSize > 0) { // The number of received bytes 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); PrintHex<uint16_t > (bufferSize, 0x80);
Notify(PSTR("\r\n"), 0x80); Notify(PSTR("\r\n"), 0x80);
#endif #endif
readReport(i); readReport(i);
@ -306,7 +306,7 @@ void XBOXRECV::readReport(uint8_t controller) {
Xbox360Connected[controller] = readBuf[1]; Xbox360Connected[controller] = readBuf[1];
#ifdef DEBUG #ifdef DEBUG
Notify(PSTR("Controller "), 0x80); Notify(PSTR("Controller "), 0x80);
Serial.print(controller); Notify(controller, 0x80);
#endif #endif
if (Xbox360Connected[controller]) { if (Xbox360Connected[controller]) {
#ifdef DEBUG #ifdef DEBUG
@ -333,7 +333,7 @@ void XBOXRECV::readReport(uint8_t controller) {
case 3: led = LED4; case 3: led = LED4;
break; break;
} }
setLedOn(controller, led); setLedOn(led, controller);
} }
#ifdef DEBUG #ifdef DEBUG
else else
@ -379,25 +379,25 @@ void XBOXRECV::printReport(uint8_t controller, uint8_t nBytes) { //Uncomment "#d
if (readBuf == NULL) if (readBuf == NULL)
return; return;
Notify(PSTR("Controller "), 0x80); Notify(PSTR("Controller "), 0x80);
Serial.print(controller); Notify(controller, 0x80);
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(" "); Notify(PSTR(" "), 0x80);
} }
Serial.println(); Notify(PSTR("\r\n"), 0x80);
#endif #endif
} }
uint8_t XBOXRECV::getButtonPress(uint8_t controller, Button b) { uint8_t XBOXRECV::getButtonPress(Button b, uint8_t controller) {
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 (bool)(ButtonState[controller] & ((uint32_t)pgm_read_word(&XBOXBUTTONS[(uint8_t)b]) << 16));
} }
bool XBOXRECV::getButtonClick(uint8_t controller, Button b) { bool XBOXRECV::getButtonClick(Button b, uint8_t controller) {
if (b == L2) { if (b == L2) {
if (L2Clicked[controller]) { if (L2Clicked[controller]) {
L2Clicked[controller] = false; L2Clicked[controller] = false;
@ -417,7 +417,7 @@ bool XBOXRECV::getButtonClick(uint8_t controller, Button b) {
return click; return click;
} }
int16_t XBOXRECV::getAnalogHat(uint8_t controller, AnalogHat a) { int16_t XBOXRECV::getAnalogHat(AnalogHat a, uint8_t controller) {
return hatValue[controller][a]; return hatValue[controller][a];
} }
@ -470,7 +470,7 @@ void XBOXRECV::XboxCommand(uint8_t controller, uint8_t* data, uint16_t nbytes) {
#endif #endif
} }
void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) { void XBOXRECV::setLedRaw(uint8_t value, uint8_t controller) {
writeBuf[0] = 0x00; writeBuf[0] = 0x00;
writeBuf[1] = 0x00; writeBuf[1] = 0x00;
writeBuf[2] = 0x08; writeBuf[2] = 0x08;
@ -479,16 +479,16 @@ void XBOXRECV::setLedRaw(uint8_t controller, uint8_t value) {
XboxCommand(controller, writeBuf, 4); XboxCommand(controller, writeBuf, 4);
} }
void XBOXRECV::setLedOn(uint8_t controller, LED led) { void XBOXRECV::setLedOn(LED led, uint8_t controller) {
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(LED led, uint8_t controller) {
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(LEDMode ledMode, uint8_t controller) { // This function is used to do some speciel LED stuff the controller supports
setLedRaw(controller, (uint8_t)ledMode); setLedRaw(controller, (uint8_t)ledMode);
} }
@ -518,7 +518,7 @@ void XBOXRECV::checkStatus() {
} }
} }
void XBOXRECV::setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue) { void XBOXRECV::setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller) {
writeBuf[0] = 0x00; writeBuf[0] = 0x00;
writeBuf[1] = 0x01; writeBuf[1] = 0x01;
writeBuf[2] = 0x0f; writeBuf[2] = 0x0f;

View file

@ -113,93 +113,93 @@ public:
* *
* So you instance if you need to increase a variable once you would use getButtonClick(uint8_t controller, Button b), * 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). * 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. * @param b ::Button to read.
* @param controller The controller to read from. Default to 0.
* @return getButtonClick(uint8_t controller, Button b) will return a bool, but getButtonPress(uint8_t controller, Button b) * @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. * will return a byte if reading ::L2 or ::R2.
*/ */
uint8_t getButtonPress(uint8_t controller, Button b); uint8_t getButtonPress(Button b, uint8_t controller = 0);
bool getButtonClick(uint8_t controller, Button b); bool getButtonClick(Button b, uint8_t controller = 0);
/**@}*/ /**@}*/
/** @name Xbox Controller functions */ /** @name Xbox Controller functions */
/** /**
* Return the analog value from the joysticks on the controller. * Return the analog value from the joysticks on the controller.
* @param controller The controller to read from.
* @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY. * @param a Either ::LeftHatX, ::LeftHatY, ::RightHatX or ::RightHatY.
* @param controller The controller to read from. Default to 0.
* @return Returns a signed 16-bit integer. * @return Returns a signed 16-bit integer.
*/ */
int16_t getAnalogHat(uint8_t controller, AnalogHat a); int16_t getAnalogHat(AnalogHat a, uint8_t controller = 0);
/** /**
* Turn rumble off and all the LEDs on the specific controller. * Turn rumble off and all the LEDs on the specific controller.
* @param controller The controller to write to. * @param controller The controller to write to. Default to 0.
*/ */
void setAllOff(uint8_t controller) { void setAllOff(uint8_t controller = 0) {
setRumbleOn(controller, 0, 0); setRumbleOn(0, 0, controller);
setLedOff(controller); setLedOff(controller);
}; };
/** /**
* Turn rumble off the specific controller. * Turn rumble off the specific controller.
* @param controller The controller to write to. * @param controller The controller to write to. Default to 0.
*/ */
void setRumbleOff(uint8_t controller) { void setRumbleOff(uint8_t controller = 0) {
setRumbleOn(controller, 0, 0); setRumbleOn(0, 0, controller);
}; };
/** /**
* Turn rumble on. * Turn rumble on.
* @param controller The controller to write to.
* @param lValue Left motor (big weight) inside the controller. * @param lValue Left motor (big weight) inside the controller.
* @param rValue Right motor (small weight) inside the controller. * @param rValue Right motor (small weight) inside the controller.
* @param controller The controller to write to. Default to 0.
*/ */
void setRumbleOn(uint8_t controller, uint8_t lValue, uint8_t rValue); void setRumbleOn(uint8_t lValue, uint8_t rValue, uint8_t controller = 0);
/** /**
* Set LED value. Without using the ::LED or ::LEDMode enum. * Set LED value. Without using the ::LED or ::LEDMode enum.
* @param controller The controller to write to.
* @param value See: * @param value See:
* setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l), * setLedOff(uint8_t controller), setLedOn(uint8_t controller, LED l),
* setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm). * setLedBlink(uint8_t controller, LED l), and setLedMode(uint8_t controller, LEDMode lm).
* @param controller The controller to write to. Default to 0.
*/ */
void setLedRaw(uint8_t controller, uint8_t value); void setLedRaw(uint8_t value, uint8_t controller = 0);
/** /**
* Turn all LEDs off the specific controller. * Turn all LEDs off the specific controller.
* @param controller The controller to write to. * @param controller The controller to write to. Default to 0.
*/ */
void setLedOff(uint8_t controller) { void setLedOff(uint8_t controller = 0) {
setLedRaw(controller, 0); setLedRaw(0, controller);
}; };
/** /**
* Turn on a LED by using the ::LED enum. * 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. * @param l ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
* @param controller The controller to write to. Default to 0.
*/ */
void setLedOn(uint8_t controller, LED l); void setLedOn(LED l, uint8_t controller = 0);
/** /**
* Turn on a LED by using the ::LED enum. * 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. * @param l ::ALL, ::LED1, ::LED2, ::LED3 and ::LED4 is supported by the Xbox controller.
* @param controller The controller to write to. Default to 0.
*/ */
void setLedBlink(uint8_t controller, LED l); void setLedBlink(LED l, uint8_t controller = 0);
/** /**
* Used to set special LED modes supported by the Xbox controller. * Used to set special LED modes supported by the Xbox controller.
* @param controller The controller to write to.
* @param lm See ::LEDMode. * @param lm See ::LEDMode.
* @param controller The controller to write to. Default to 0.
*/ */
void setLedMode(uint8_t controller, LEDMode lm); void setLedMode(LEDMode lm, uint8_t controller = 0);
/** /**
* Used to get the battery level from the controller. * Used to get the battery level from the controller.
* @param controller The controller to read from. * @param controller The controller to read from. Default to 0.
* @return Returns the battery level as an integer in the range of 0-3. * @return Returns the battery level as an integer in the range of 0-3.
*/ */
uint8_t getBatteryLevel(uint8_t controller); uint8_t getBatteryLevel(uint8_t controller = 0);
/** /**
* Used to check if a button has changed. * Used to check if a button has changed.
* @param controller The controller to read from. * @param controller The controller to read from. Default to 0.
* @return True if a button has changed. * @return True if a button has changed.
*/ */
bool buttonChanged(uint8_t controller); bool buttonChanged(uint8_t controller = 0);
/**@}*/ /**@}*/
/** True if a wireless receiver is connected. */ /** True if a wireless receiver is connected. */

View file

@ -268,9 +268,9 @@ void XBOXUSB::printReport() { //Uncomment "#define PRINTREPORT" to print the rep
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(" "); Notify(PSTR(" "), 0x80);
} }
Serial.println(); Notify(PSTR("\r\n"), 0x80);
#endif #endif
} }

View file

@ -21,7 +21,7 @@ PS3BT PS3(&Btd); // This will just create the instance
//PS3BT PS3(&Btd,0x00,0x15,0x83,0x3D,0x0A,0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch //PS3BT PS3(&Btd,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 firstMessage = true; boolean firstMessage = true;
String output = ""; // We will store the data in this string so we doesn't overflow the dongle String output = ""; // We will store the data in this string
void setup() { void setup() {
Serial.begin(115200); // This wil lprint the debugging from the libraries Serial.begin(115200); // This wil lprint the debugging from the libraries
@ -33,7 +33,7 @@ void setup() {
output.reserve(200); // Reserve 200 bytes for the output string output.reserve(200); // Reserve 200 bytes for the output string
} }
void loop() { void loop() {
Usb.Task(); Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well
if(SerialBT.connected) { if(SerialBT.connected) {
if(firstMessage) { if(firstMessage) {
@ -41,7 +41,7 @@ void loop() {
SerialBT.println(F("Hello from Arduino")); // Send welcome message SerialBT.println(F("Hello from Arduino")); // Send welcome message
} }
if(Serial.available()) if(Serial.available())
SerialBT.print(Serial.read()); SerialBT.write(Serial.read());
if(SerialBT.available()) if(SerialBT.available())
Serial.write(SerialBT.read()); Serial.write(SerialBT.read());
} }

View file

@ -22,14 +22,15 @@ void setup() {
Serial.print(F("\r\nSPP Bluetooth Library Started")); Serial.print(F("\r\nSPP Bluetooth Library Started"));
} }
void loop() { void loop() {
Usb.Task(); Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well
if(SerialBT.connected) { if(SerialBT.connected) {
if(firstMessage) { if(firstMessage) {
firstMessage = false; firstMessage = false;
SerialBT.println(F("Hello from Arduino")); // Send welcome message SerialBT.println(F("Hello from Arduino")); // Send welcome message
} }
if(Serial.available()) if(Serial.available())
SerialBT.print(Serial.read()); SerialBT.write(Serial.read());
if(SerialBT.available()) if(SerialBT.available())
Serial.write(SerialBT.read()); Serial.write(SerialBT.read());
} }

View file

@ -34,7 +34,8 @@ void setup() {
Serial.print(F("\r\nSPP Bluetooth Library Started")); Serial.print(F("\r\nSPP Bluetooth Library Started"));
} }
void loop() { void loop() {
Usb.Task(); Usb.Task(); // The SPP data is actually not send until this is called, one could call SerialBT.send() directly as well
for(uint8_t i=0;i<length;i++) { for(uint8_t i=0;i<length;i++) {
if(SerialBT[i]->connected) { if(SerialBT[i]->connected) {
if(firstMessage[i]) { if(firstMessage[i]) {
@ -61,7 +62,7 @@ void loop() {
if(SerialBT[id]->connected) { // Check if a device is actually connected if(SerialBT[id]->connected) { // Check if a device is actually connected
for(uint8_t i2 = 0; i2 < i-1; i2++) // Don't include the first character for(uint8_t i2 = 0; i2 < i-1; i2++) // Don't include the first character
buffer[i2] = buffer[i2+1]; buffer[i2] = buffer[i2+1];
SerialBT[id]->println(buffer,i-1); // Send the data SerialBT[id]->write(buffer,i-1); // Send the data
} }
} }
} }

View file

@ -68,7 +68,7 @@ void KbdRptParser::OnKeyPressed(uint8_t key)
USB Usb; USB Usb;
//USBHub Hub(&Usb); //USBHub Hub(&Usb);
HIDBoot<HID_PROTOCOL_KEYBOARD> Keyboard(&Usb); HIDBoot<HID_PROTOCOL_KEYBOARD> HidKeyboard(&Usb);
uint32_t next_time; uint32_t next_time;
@ -86,7 +86,7 @@ void setup()
next_time = millis() + 5000; next_time = millis() + 5000;
Keyboard.SetReportParser(0, (HIDReportParser*)&Prs); HidKeyboard.SetReportParser(0, (HIDReportParser*)&Prs);
} }
void loop() void loop()

View file

@ -58,7 +58,7 @@ void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi)
USB Usb; USB Usb;
USBHub Hub(&Usb); USBHub Hub(&Usb);
HIDBoot<HID_PROTOCOL_MOUSE> Mouse(&Usb); HIDBoot<HID_PROTOCOL_MOUSE> HidMouse(&Usb);
uint32_t next_time; uint32_t next_time;
@ -76,7 +76,7 @@ void setup()
next_time = millis() + 5000; next_time = millis() + 5000;
Mouse.SetReportParser(0,(HIDReportParser*)&Prs); HidMouse.SetReportParser(0,(HIDReportParser*)&Prs);
} }
void loop() void loop()

View file

@ -22,86 +22,86 @@ void loop() {
if(Xbox.XboxReceiverConnected) { if(Xbox.XboxReceiverConnected) {
for(uint8_t i=0;i<4;i++) { for(uint8_t i=0;i<4;i++) {
if(Xbox.Xbox360Connected[i]) { if(Xbox.Xbox360Connected[i]) {
if(Xbox.getButtonPress(i,L2) || Xbox.getButtonPress(i,R2)) { if(Xbox.getButtonPress(L2,i) || Xbox.getButtonPress(R2,i)) {
Serial.print("L2: "); Serial.print("L2: ");
Serial.print(Xbox.getButtonPress(i,L2)); Serial.print(Xbox.getButtonPress(L2,i));
Serial.print("\tR2: "); Serial.print("\tR2: ");
Serial.println(Xbox.getButtonPress(i,R2)); Serial.println(Xbox.getButtonPress(R2,i));
Xbox.setRumbleOn(i,Xbox.getButtonPress(i,L2),Xbox.getButtonPress(i,R2)); Xbox.setRumbleOn(Xbox.getButtonPress(L2,i),Xbox.getButtonPress(R2,i));
} }
if(Xbox.getAnalogHat(i,LeftHatX) > 7500 || Xbox.getAnalogHat(i,LeftHatX) < -7500 || Xbox.getAnalogHat(i,LeftHatY) > 7500 || Xbox.getAnalogHat(i,LeftHatY) < -7500 || Xbox.getAnalogHat(i,RightHatX) > 7500 || Xbox.getAnalogHat(i,RightHatX) < -7500 || Xbox.getAnalogHat(i,RightHatY) > 7500 || Xbox.getAnalogHat(i,RightHatY) < -7500) { if(Xbox.getAnalogHat(LeftHatX,i) > 7500 || Xbox.getAnalogHat(LeftHatX,i) < -7500 || Xbox.getAnalogHat(LeftHatY,i) > 7500 || Xbox.getAnalogHat(LeftHatY,i) < -7500 || Xbox.getAnalogHat(RightHatX,i) > 7500 || Xbox.getAnalogHat(RightHatX,i) < -7500 || Xbox.getAnalogHat(RightHatY,i) > 7500 || Xbox.getAnalogHat(RightHatY,i) < -7500) {
if(Xbox.getAnalogHat(i,LeftHatX) > 7500 || Xbox.getAnalogHat(i,LeftHatX) < -7500) { if(Xbox.getAnalogHat(LeftHatX,i) > 7500 || Xbox.getAnalogHat(LeftHatX,i) < -7500) {
Serial.print(F("LeftHatX: ")); Serial.print(F("LeftHatX: "));
Serial.print(Xbox.getAnalogHat(i,LeftHatX)); Serial.print(Xbox.getAnalogHat(LeftHatX,i));
Serial.print("\t"); Serial.print("\t");
} }
if(Xbox.getAnalogHat(i,LeftHatY) > 7500 || Xbox.getAnalogHat(i,LeftHatY) < -7500) { if(Xbox.getAnalogHat(LeftHatY,i) > 7500 || Xbox.getAnalogHat(LeftHatY,i) < -7500) {
Serial.print(F("LeftHatY: ")); Serial.print(F("LeftHatY: "));
Serial.print(Xbox.getAnalogHat(i,LeftHatY)); Serial.print(Xbox.getAnalogHat(LeftHatY,i));
Serial.print("\t"); Serial.print("\t");
} }
if(Xbox.getAnalogHat(i,RightHatX) > 7500 || Xbox.getAnalogHat(i,RightHatX) < -7500) { if(Xbox.getAnalogHat(RightHatX,i) > 7500 || Xbox.getAnalogHat(RightHatX,i) < -7500) {
Serial.print(F("RightHatX: ")); Serial.print(F("RightHatX: "));
Serial.print(Xbox.getAnalogHat(i,RightHatX)); Serial.print(Xbox.getAnalogHat(RightHatX,i));
Serial.print("\t"); Serial.print("\t");
} }
if(Xbox.getAnalogHat(i,RightHatY) > 7500 || Xbox.getAnalogHat(i,RightHatY) < -7500) { if(Xbox.getAnalogHat(RightHatY,i) > 7500 || Xbox.getAnalogHat(RightHatY,i) < -7500) {
Serial.print(F("RightHatY: ")); Serial.print(F("RightHatY: "));
Serial.print(Xbox.getAnalogHat(i,RightHatY)); Serial.print(Xbox.getAnalogHat(RightHatY,i));
} }
Serial.println(); Serial.println();
} }
if(Xbox.getButtonClick(i,UP)) { if(Xbox.getButtonClick(UP,i)) {
Xbox.setLedOn(i,LED1); Xbox.setLedOn(LED1,i);
Serial.println(F("Up")); Serial.println(F("Up"));
} }
if(Xbox.getButtonClick(i,DOWN)) { if(Xbox.getButtonClick(DOWN,i)) {
Xbox.setLedOn(i,LED4); Xbox.setLedOn(LED4,i);
Serial.println(F("Down")); Serial.println(F("Down"));
} }
if(Xbox.getButtonClick(i,LEFT)) { if(Xbox.getButtonClick(LEFT,i)) {
Xbox.setLedOn(i,LED3); Xbox.setLedOn(LED3,i);
Serial.println(F("Left")); Serial.println(F("Left"));
} }
if(Xbox.getButtonClick(i,RIGHT)) { if(Xbox.getButtonClick(RIGHT,i)) {
Xbox.setLedOn(i,LED2); Xbox.setLedOn(LED2,i);
Serial.println(F("Right")); Serial.println(F("Right"));
} }
if(Xbox.getButtonClick(i,START)) { if(Xbox.getButtonClick(START,i)) {
Xbox.setLedMode(i,ALTERNATING); Xbox.setLedMode(ALTERNATING,i);
Serial.println(F("Start")); Serial.println(F("Start"));
} }
if(Xbox.getButtonClick(i,BACK)) { if(Xbox.getButtonClick(BACK,i)) {
Xbox.setLedBlink(i,ALL); Xbox.setLedBlink(ALL,i);
Serial.println(F("Back")); Serial.println(F("Back"));
} }
if(Xbox.getButtonClick(i,L3)) if(Xbox.getButtonClick(L3,i))
Serial.println(F("L3")); Serial.println(F("L3"));
if(Xbox.getButtonClick(i,R3)) if(Xbox.getButtonClick(R3,i))
Serial.println(F("R3")); Serial.println(F("R3"));
if(Xbox.getButtonClick(i,L1)) if(Xbox.getButtonClick(L1,i))
Serial.println(F("L1")); Serial.println(F("L1"));
if(Xbox.getButtonClick(i,R1)) if(Xbox.getButtonClick(R1,i))
Serial.println(F("R1")); Serial.println(F("R1"));
if(Xbox.getButtonClick(i,XBOX)) { if(Xbox.getButtonClick(XBOX,i)) {
Xbox.setLedMode(i,ROTATING); Xbox.setLedMode(ROTATING,i);
Serial.print(F("Xbox (Battery: ")); Serial.print(F("Xbox (Battery: "));
Serial.print(Xbox.getBatteryLevel(i)); Serial.print(Xbox.getBatteryLevel(i)); // The battery level in the range 0-3
Serial.println(F("%)")); Serial.println(F(")"));
} }
if(Xbox.getButtonClick(i,SYNC)) if(Xbox.getButtonClick(SYNC,i))
Serial.println(F("Sync")); Serial.println(F("Sync"));
if(Xbox.getButtonClick(i,A)) if(Xbox.getButtonClick(A,i))
Serial.println(F("A")); Serial.println(F("A"));
if(Xbox.getButtonClick(i,B)) if(Xbox.getButtonClick(B,i))
Serial.println(F("B")); Serial.println(F("B"));
if(Xbox.getButtonClick(i,X)) if(Xbox.getButtonClick(X,i))
Serial.println(F("X")); Serial.println(F("X"));
if(Xbox.getButtonClick(i,Y)) if(Xbox.getButtonClick(Y,i))
Serial.println(F("Y")); Serial.println(F("Y"));
} }
} }

View file

@ -159,7 +159,7 @@ public:
virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
protected: protected:
uint8_t HandleLockingKeys(HID* hid, uint8_t key); virtual uint8_t HandleLockingKeys(HID* hid, uint8_t key);
virtual void OnKeyDown(uint8_t mod, uint8_t key) { virtual void OnKeyDown(uint8_t mod, uint8_t key) {
}; };
@ -450,6 +450,7 @@ void HIDBoot<BOOT_PROTOCOL>::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t
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;
epInfo[index].bmNakPower = USB_NAK_NOWAIT;
bNumEP++; bNumEP++;
} }

View file

@ -47,6 +47,22 @@ void E_NotifyStr(char const * msg, int lvl) {
while (c = *msg++) E_Notifyc(c, lvl); while (c = *msg++) E_Notifyc(c, lvl);
} }
void E_Notify(uint8_t b, int lvl) {
if (UsbDEBUGlvl < lvl) return;
#if defined(ARDUINO) && ARDUINO >=100
Serial.print(b);
#else
Serial.print(b, DEC);
#endif
Serial.flush();
}
void E_Notify(double d, int lvl) {
if (UsbDEBUGlvl < lvl) return;
Serial.print(d);
Serial.flush();
}
#ifdef DEBUG #ifdef DEBUG
void NotifyFailGetDevDescr(void) { void NotifyFailGetDevDescr(void) {
Notify(PSTR("\r\ngetDevDescr"), 0x80); Notify(PSTR("\r\ngetDevDescr"), 0x80);

View file

@ -27,11 +27,14 @@ extern int UsbDEBUGlvl;
#include "printhex.h" #include "printhex.h"
void E_Notify(char const * msg, int lvl); void E_Notify(char const * msg, int lvl);
void E_Notify(uint8_t b, int lvl);
void E_NotifyStr(char const * msg, int lvl); void E_NotifyStr(char const * msg, int lvl);
void E_Notifyc(char c, int lvl);
#ifdef DEBUG #ifdef DEBUG
#define Notify E_Notify #define Notify E_Notify
#define NotifyStr E_NotifyStr #define NotifyStr E_NotifyStr
#define Notifyc E_Notifyc
void NotifyFailGetDevDescr(uint8_t reason); void NotifyFailGetDevDescr(uint8_t reason);
void NotifyFailSetDevTblEntry(uint8_t reason); void NotifyFailSetDevTblEntry(uint8_t reason);
void NotifyFailGetConfDescr(uint8_t reason); void NotifyFailGetConfDescr(uint8_t reason);
@ -44,6 +47,7 @@ void NotifyFail(uint8_t rcode);
#else #else
#define Notify(...) ((void)0) #define Notify(...) ((void)0)
#define NotifyStr(...) ((void)0) #define NotifyStr(...) ((void)0)
#define Notifyc(...) ((void)0)
#define NotifyFailGetDevDescr(...) ((void)0) #define NotifyFailGetDevDescr(...) ((void)0)
#define NotifyFailSetDevTblEntry(...) ((void)0) #define NotifyFailSetDevTblEntry(...) ((void)0)
#define NotifyFailGetConfDescr(...) ((void)0) #define NotifyFailGetConfDescr(...) ((void)0)