USB_Host_Shield_2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
SPP.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
2 
3  This software may be distributed and modified under the terms of the GNU
4  General Public License version 2 (GPL2) as published by the Free Software
5  Foundation and appearing in the file GPL2.TXT included in the packaging of
6  this file. Please note that GPL2 Section 2[b] requires that all works based
7  on this software must also be made publicly available under the terms of
8  the GPL2 ("Copyleft").
9 
10  Contact information
11  -------------------
12 
13  Kristian Lauszus, TKJ Electronics
14  Web : http://www.tkjelectronics.com
15  e-mail : kristianl@tkjelectronics.com
16  */
17 
18 #include "SPP.h"
19 #define DEBUG // Uncomment to print data for debugging
20 //#define EXTRADEBUG // Uncomment to get even more debugging data
21 //#define PRINTREPORT // Uncomment to print the report sent to the Arduino
22 
23 /*
24  * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
25  */
26 const uint8_t rfcomm_crc_table[256] PROGMEM = { /* reversed, 8-bit, poly=0x07 */
27  0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
28  0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
29  0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
30  0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
31  0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
32  0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
33  0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
34  0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
35  0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
36  0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
37  0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
38  0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
39  0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
40  0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
41  0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
42  0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
43 };
44 
45 SPP::SPP(BTD *p, const char* name, const char* pin):
46 pBtd(p) // Pointer to BTD class instance - mandatory
47 {
48  if (pBtd)
49  pBtd->registerServiceClass(this); // Register it as a Bluetooth service
50 
51  pBtd->btdName = name;
52  pBtd->btdPin = pin;
53 
54  /* Set device cid for the SDP and RFCOMM channelse */
55  sdp_dcid[0] = 0x50; // 0x0050
56  sdp_dcid[1] = 0x00;
57  rfcomm_dcid[0] = 0x51; // 0x0051
58  rfcomm_dcid[1] = 0x00;
59 
60  Reset();
61 }
62 void SPP::Reset() {
63  connected = false;
64  RFCOMMConnected = false;
65  SDPConnected = false;
66  l2cap_sdp_state = L2CAP_SDP_WAIT;
67  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
68  l2cap_event_flag = 0;
69 }
71  connected = false;
72  // First the two L2CAP channels has to be disconencted and then the HCI connection
73  if(RFCOMMConnected)
74  pBtd->l2cap_disconnection_request(hci_handle,0x0A, rfcomm_scid, rfcomm_dcid);
75  if(RFCOMMConnected && SDPConnected)
76  delay(1); // Add delay between commands
77  if(SDPConnected)
78  pBtd->l2cap_disconnection_request(hci_handle,0x0B, sdp_scid, sdp_dcid);
79  l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE;
80 }
81 void SPP::ACLData(uint8_t* l2capinbuf) {
82  if(!connected) {
83  if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
84  if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) {
85  pBtd->sdpConnectionClaimed = true;
86  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
87  l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state
88  } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) {
89  pBtd->rfcommConnectionClaimed = true;
90  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
91  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state
92  }
93  }
94  }
95  if (((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000))) { // acl_handle_ok
96  if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U
97  if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
98 #ifdef DEBUG
99  Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "));
100  PrintHex<uint8_t>(l2capinbuf[13]);
101  Notify(PSTR(" "));
102  PrintHex<uint8_t>(l2capinbuf[12]);
103  Notify(PSTR(" Data: "));
104  PrintHex<uint8_t>(l2capinbuf[17]);
105  Notify(PSTR(" "));
106  PrintHex<uint8_t>(l2capinbuf[16]);
107  Notify(PSTR(" "));
108  PrintHex<uint8_t>(l2capinbuf[15]);
109  Notify(PSTR(" "));
110  PrintHex<uint8_t>(l2capinbuf[14]);
111 #endif
112  } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
113 #ifdef EXTRADEBUG
114  Notify(PSTR("\r\nL2CAP Connection Request - PSM: "));
115  PrintHex<uint8_t>(l2capinbuf[13]);
116  Notify(PSTR(" "));
117  PrintHex<uint8_t>(l2capinbuf[12]);
118  Notify(PSTR(" SCID: "));
119  PrintHex<uint8_t>(l2capinbuf[15]);
120  Notify(PSTR(" "));
121  PrintHex<uint8_t>(l2capinbuf[14]);
122  Notify(PSTR(" Identifier: "));
123  PrintHex<uint8_t>(l2capinbuf[9]);
124 #endif
125  if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM) { // It doesn't matter if it receives another reqeust, since it waits for the channel to disconnect in the L2CAP_SDP_DONE state, and the l2cap_event_flag will be cleared if so
126  identifier = l2capinbuf[9];
127  sdp_scid[0] = l2capinbuf[14];
128  sdp_scid[1] = l2capinbuf[15];
129  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_SDP_REQUEST;
130  } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || -----
131  identifier = l2capinbuf[9];
132  rfcomm_scid[0] = l2capinbuf[14];
133  rfcomm_scid[1] = l2capinbuf[15];
134  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST;
135  }
136  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
137  if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
138  if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
139  //Serial.print("\r\nSDP Configuration Complete");
140  l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_SUCCESS;
141  }
142  else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
143  //Serial.print("\r\nRFCOMM Configuration Complete");
144  l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS;
145  }
146  }
147  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
148  if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
149  //Serial.print("\r\nSDP Configuration Request");
150  identifier = l2capinbuf[9];
151  l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_REQUEST;
152  }
153  else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
154  //Serial.print("\r\nRFCOMM Configuration Request");
155  identifier = l2capinbuf[9];
156  l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_REQUEST;
157  }
158  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
159  if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
160  //Notify(PSTR("\r\nDisconnect Request: SDP Channel"));
161  identifier = l2capinbuf[9];
162  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_SDP_REQUEST;
163  } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
164  //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"));
165  identifier = l2capinbuf[9];
166  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST;
167  }
168  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
169  if (l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {
170  //Serial.print("\r\nDisconnect Response: SDP Channel");
171  identifier = l2capinbuf[9];
172  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE;
173  } else if (l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) {
174  //Serial.print("\r\nDisconnect Response: RFCOMM Channel");
175  identifier = l2capinbuf[9];
176  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE;
177  }
178  } else if (l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) {
179 #ifdef DEBUG
180  Notify(PSTR("\r\nInformation request"));
181 #endif
182  identifier = l2capinbuf[9];
183  pBtd->l2cap_information_response(hci_handle,identifier,l2capinbuf[12],l2capinbuf[13]);
184  }
185 #ifdef EXTRADEBUG
186  else {
187  Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "));
188  PrintHex<uint8_t>(l2capinbuf[8]);
189  }
190 #endif
191  } else if (l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP
192  if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) {
193  /*
194  Serial.print("\r\nUUID: 0x");
195  Serial.print(l2capinbuf[16],HEX);
196  Serial.print(" ");
197  Serial.print(l2capinbuf[17],HEX);
198  */
199  if ((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) {
200  if(firstMessage) {
201  serialPortResponse1(l2capinbuf[9],l2capinbuf[10]);
202  firstMessage = false;
203  } else {
204  serialPortResponse2(l2capinbuf[9],l2capinbuf[10]); // Serialport continuation state
205  firstMessage = true;
206  }
207  } else if ((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) {
208  if(firstMessage) {
209  l2capResponse1(l2capinbuf[9],l2capinbuf[10]);
210  firstMessage = false;
211  } else {
212  l2capResponse2(l2capinbuf[9],l2capinbuf[10]); // L2CAP continuation state
213  firstMessage = true;
214  }
215  } else
216  serviceNotSupported(l2capinbuf[9],l2capinbuf[10]); // The service is not supported
217  }
218  } else if (l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM
219  rfcommChannel = l2capinbuf[8] & 0xF8;
220  rfcommDirection = l2capinbuf[8] & 0x04;
221  rfcommCommandResponse = l2capinbuf[8] & 0x02;
222  rfcommChannelType = l2capinbuf[9] & 0xEF;
223  rfcommPfBit = l2capinbuf[9] & 0x10;
224 
225  if(rfcommChannel>>3 != 0x00)
226  rfcommChannelConnection = rfcommChannel;
227 
228 #ifdef EXTRADEBUG
229  Notify(PSTR("\r\nRFCOMM Channel: "));
230  Serial.print(rfcommChannel>>3,HEX);
231  Notify(PSTR(" Direction: "));
232  Serial.print(rfcommDirection>>2,HEX);
233  Notify(PSTR(" CommandResponse: "));
234  Serial.print(rfcommCommandResponse>>1,HEX);
235  Notify(PSTR(" ChannelType: "));
236  Serial.print(rfcommChannelType,HEX);
237  Notify(PSTR(" PF_BIT: "));
238  Serial.print(rfcommPfBit,HEX);
239 #endif
240  if (rfcommChannelType == RFCOMM_DISC) {
241 #ifdef DEBUG
242  Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "));
243  Serial.print(rfcommChannel>>3,HEX);
244 #endif
245  connected = false;
246  sendRfcomm(rfcommChannel,rfcommDirection,rfcommCommandResponse,RFCOMM_UA,rfcommPfBit,rfcommbuf,0x00); // UA Command
247  }
248  if(connected) {
249  /* Read the incoming message */
250  if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) {
251  uint8_t length = l2capinbuf[10] >> 1; // Get length
252  uint8_t offset = l2capinbuf[4]-length-4; // See if there is credit
253  if(rfcommAvailable + length <= sizeof(rfcommDataBuffer)) { // Don't add data to buffer if it would be full
254  for(uint8_t i = 0; i < length; i++)
255  rfcommDataBuffer[rfcommAvailable+i] = l2capinbuf[11+i+offset];
256  rfcommAvailable += length;
257  }
258 #ifdef EXTRADEBUG
259  Notify(PSTR("\r\nRFCOMM Data Available: "));
260  Serial.print(rfcommAvailable);
261  if (offset) {
262  Notify(PSTR(" - Credit: 0x"));
263  Serial.print(l2capinbuf[11],HEX);
264  }
265 #endif
266 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth
267  for(uint8_t i = 0; i < length; i++)
268  Serial.write(l2capinbuf[i+11+offset]);
269 #endif
270  }
271  } else {
272  if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish
273 #ifdef DEBUG
274  Notify(PSTR("\r\nReceived SABM Command"));
275 #endif
276  sendRfcomm(rfcommChannel,rfcommDirection,rfcommCommandResponse,RFCOMM_UA,rfcommPfBit,rfcommbuf,0x00); // UA Command
277  } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command
278 #ifdef DEBUG
279  Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"));
280 #endif
281  rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response
282  rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
283  rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
284  rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
285  rfcommbuf[4] = 0x00; // Priority
286  rfcommbuf[5] = 0x00; // Timer
287  rfcommbuf[6] = 0x40; // Max Fram Size LSB - we will just set this to 64
288  rfcommbuf[7] = 0x00; // Max Fram Size MSB
289  rfcommbuf[8] = 0x00; // MaxRatransm.
290  rfcommbuf[9] = 0x00; // Number of Frames
291  sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A);
292  } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
293 #ifdef DEBUG
294  Notify(PSTR("\r\nSend UIH Modem Status Response"));
295 #endif
296  rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response
297  rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
298  rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
299  rfcommbuf[3] = l2capinbuf[14];
300  sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x04);
301 
302  delay(1);
303 #ifdef DEBUG
304  Notify(PSTR("\r\nSend UIH Modem Status Command"));
305 #endif
306  rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command
307  rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
308  rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
309  rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES)
310 
311  sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x04);
312  } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response
313  if(!creditSent) {
314 #ifdef DEBUG
315  Notify(PSTR("\r\nSend UIH Command with credit"));
316 #endif
317  sendRfcommCredit(rfcommChannelConnection,rfcommDirection,0,RFCOMM_UIH,0x10,sizeof(rfcommDataBuffer)); // Send credit
318  creditSent = true;
319  timer = millis();
320  waitForLastCommand = true;
321  }
322  } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit
323 #ifdef DEBUG
324  Notify(PSTR("\r\nReceived UIH Command with credit"));
325 #endif
326  } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
327 #ifdef DEBUG
328  Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"));
329 #endif
330  rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command
331  rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
332  rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
333  rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
334  rfcommbuf[4] = l2capinbuf[15]; // Priority
335  rfcommbuf[5] = l2capinbuf[16]; // Timer
336  rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB
337  rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB
338  rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
339  rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
340  sendRfcomm(rfcommChannel,rfcommDirection,0,RFCOMM_UIH,rfcommPfBit,rfcommbuf,0x0A); // UIH Remote Port Negotiation Response
341 #ifdef DEBUG
342  Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"));
343 #endif
344  waitForLastCommand = false;
345  creditSent = false;
346  connected = true; // The RFCOMM channel is now established
347  }
348 #ifdef DEBUG
349  else if(rfcommChannelType != RFCOMM_DISC) {
350  Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "));
351  PrintHex<uint8_t>(rfcommChannelType);
352  Notify(PSTR(" Command: "));
353  PrintHex<uint8_t>(l2capinbuf[11]);
354  }
355 #endif
356  }
357  }
358 #ifdef EXTRADEBUG
359  else {
360  Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "));
361  PrintHex<uint8_t>(l2capinbuf[7]);
362  Notify(PSTR(" "));
363  PrintHex<uint8_t>(l2capinbuf[6]);
364  }
365 #endif
366  SDP_task();
367  RFCOMM_task();
368  }
369 }
370 void SPP::Run() {
371  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
372 #ifdef DEBUG
373  Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"));
374 #endif
375  creditSent = false;
376  waitForLastCommand = false;
377  connected = true; // The RFCOMM channel is now established
378  }
379 }
380 void SPP::SDP_task() {
381  switch (l2cap_sdp_state)
382  {
383  case L2CAP_SDP_WAIT:
385  l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_SDP_REQUEST; // Clear flag
386 #ifdef DEBUG
387  Notify(PSTR("\r\nSDP Incoming Connection Request"));
388 #endif
389  pBtd->l2cap_connection_response(hci_handle,identifier, sdp_dcid, sdp_scid, PENDING);
390  delay(1);
391  pBtd->l2cap_connection_response(hci_handle,identifier, sdp_dcid, sdp_scid, SUCCESSFUL);
392  identifier++;
393  delay(1);
394  pBtd->l2cap_config_request(hci_handle,identifier, sdp_scid);
395  l2cap_sdp_state = L2CAP_SDP_REQUEST;
396  }
397  break;
398  case L2CAP_SDP_REQUEST:
400  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_REQUEST; // Clear flag
401 #ifdef DEBUG
402  Notify(PSTR("\r\nSDP Configuration Request"));
403 #endif
404  pBtd->l2cap_config_response(hci_handle,identifier, sdp_scid);
405  l2cap_sdp_state = L2CAP_SDP_SUCCESS;
406  }
407  break;
408  case L2CAP_SDP_SUCCESS:
410  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_SUCCESS; // Clear flag
411 #ifdef DEBUG
412  Notify(PSTR("\r\nSDP Successfully Configured"));
413 #endif
414  firstMessage = true; // Reset bool
415  SDPConnected = true;
416  l2cap_sdp_state = L2CAP_SDP_DONE;
417  }
418  break;
419  case L2CAP_SDP_DONE:
421  l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_SDP_REQUEST; // Clear flag
422  SDPConnected = false;
423 #ifdef DEBUG
424  Notify(PSTR("\r\nDisconnected SDP Channel"));
425 #endif
426  pBtd->l2cap_disconnection_response(hci_handle,identifier,sdp_dcid,sdp_scid);
427  l2cap_sdp_state = L2CAP_SDP_WAIT;
429  l2cap_rfcomm_state = L2CAP_SDP_WAIT;
430  break;
431  case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
433 #ifdef DEBUG
434  Notify(PSTR("\r\nDisconnected L2CAP Connection"));
435 #endif
436  RFCOMMConnected = false;
437  SDPConnected = false;
438  pBtd->hci_disconnect(hci_handle);
439  hci_handle = -1; // Reset handle
440  l2cap_event_flag = 0; // Reset flags
441  l2cap_sdp_state = L2CAP_SDP_WAIT;
442  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
443  }
444  break;
445  }
446 }
447 void SPP::RFCOMM_task()
448 {
449  switch (l2cap_rfcomm_state)
450  {
451  case L2CAP_RFCOMM_WAIT:
453  l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST; // Clear flag
454 #ifdef DEBUG
455  Notify(PSTR("\r\nRFCOMM Incoming Connection Request"));
456 #endif
457  pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, PENDING);
458  delay(1);
459  pBtd->l2cap_connection_response(hci_handle,identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL);
460  identifier++;
461  delay(1);
462  pBtd->l2cap_config_request(hci_handle,identifier, rfcomm_scid);
463  l2cap_rfcomm_state = L2CAP_RFCOMM_REQUEST;
464  }
465  break;
468  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; // Clear flag
469 #ifdef DEBUG
470  Notify(PSTR("\r\nRFCOMM Configuration Request"));
471 #endif
472  pBtd->l2cap_config_response(hci_handle,identifier, rfcomm_scid);
473  l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS;
474  }
475  break;
478  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; // Clear flag
479 #ifdef DEBUG
480  Notify(PSTR("\r\nRFCOMM Successfully Configured"));
481 #endif
482  rfcommAvailable = 0; // Reset number of bytes available
483  bytesRead = 0; // Reset number of bytes received
484  RFCOMMConnected = true;
485  l2cap_rfcomm_state = L2CAP_RFCOMM_DONE;
486  }
487  break;
488  case L2CAP_RFCOMM_DONE:
490  l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; // Clear flag
491  RFCOMMConnected = false;
492  connected = false;
493 #ifdef DEBUG
494  Notify(PSTR("\r\nDisconnected RFCOMM Channel"));
495 #endif
496  pBtd->l2cap_disconnection_response(hci_handle,identifier,rfcomm_dcid,rfcomm_scid);
497  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
499  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
500  break;
501  }
502 }
503 /************************************************************/
504 /* SDP Commands */
505 /************************************************************/
506 void SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs
507  pBtd->L2CAP_Command(hci_handle,data,nbytes,sdp_scid[0],sdp_scid[1]);
508 }
509 void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs
511  l2capoutbuf[1] = transactionIDHigh;
512  l2capoutbuf[2] = transactionIDLow;
513  l2capoutbuf[3] = 0x00; // Parameter Length
514  l2capoutbuf[4] = 0x05; // Parameter Length
515  l2capoutbuf[5] = 0x00; // AttributeListsByteCount
516  l2capoutbuf[6] = 0x02; // AttributeListsByteCount
517 
518  /* Attribute ID/Value Sequence: */
519  l2capoutbuf[7] = 0x35;
520  l2capoutbuf[8] = 0x00;
521  l2capoutbuf[9] = 0x00;
522 
523  SDP_Command(l2capoutbuf,10);
524 }
525 void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
527  l2capoutbuf[1] = transactionIDHigh;
528  l2capoutbuf[2] = transactionIDLow;
529  l2capoutbuf[3] = 0x00; // Parameter Length
530  l2capoutbuf[4] = 0x2B; // Parameter Length
531  l2capoutbuf[5] = 0x00; // AttributeListsByteCount
532  l2capoutbuf[6] = 0x26; // AttributeListsByteCount
533 
534  /* Attribute ID/Value Sequence: */
535  l2capoutbuf[7] = 0x36;
536  l2capoutbuf[8] = 0x00;
537  l2capoutbuf[9] = 0x3C;
538  l2capoutbuf[10] = 0x36;
539  l2capoutbuf[11] = 0x00;
540 
541  l2capoutbuf[12] = 0x39;
542  l2capoutbuf[13] = 0x09;
543  l2capoutbuf[14] = 0x00;
544  l2capoutbuf[15] = 0x00;
545  l2capoutbuf[16] = 0x0A;
546  l2capoutbuf[17] = 0x00;
547  l2capoutbuf[18] = 0x01;
548  l2capoutbuf[19] = 0x00;
549  l2capoutbuf[20] = 0x06;
550  l2capoutbuf[21] = 0x09;
551  l2capoutbuf[22] = 0x00;
552  l2capoutbuf[23] = 0x01;
553  l2capoutbuf[24] = 0x35;
554  l2capoutbuf[25] = 0x03;
555  l2capoutbuf[26] = 0x19;
556  l2capoutbuf[27] = 0x11;
557 
558  l2capoutbuf[28] = 0x01;
559  l2capoutbuf[29] = 0x09;
560  l2capoutbuf[30] = 0x00;
561  l2capoutbuf[31] = 0x04;
562  l2capoutbuf[32] = 0x35;
563  l2capoutbuf[33] = 0x0C;
564  l2capoutbuf[34] = 0x35;
565  l2capoutbuf[35] = 0x03;
566  l2capoutbuf[36] = 0x19;
567  l2capoutbuf[37] = 0x01;
568  l2capoutbuf[38] = 0x00;
569  l2capoutbuf[39] = 0x35;
570  l2capoutbuf[40] = 0x05;
571  l2capoutbuf[41] = 0x19;
572  l2capoutbuf[42] = 0x00;
573  l2capoutbuf[43] = 0x03;
574 
575  l2capoutbuf[44] = 0x08;
576  l2capoutbuf[45] = 0x02; // Two extra bytes
577  l2capoutbuf[46] = 0x00; // 25 (0x19) more bytes to come
578  l2capoutbuf[47] = 0x19;
579 
580  SDP_Command(l2capoutbuf,48);
581 }
582 void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
584  l2capoutbuf[1] = transactionIDHigh;
585  l2capoutbuf[2] = transactionIDLow;
586  l2capoutbuf[3] = 0x00; // Parameter Length
587  l2capoutbuf[4] = 0x1C; // Parameter Length
588  l2capoutbuf[5] = 0x00; // AttributeListsByteCount
589  l2capoutbuf[6] = 0x19; // AttributeListsByteCount
590 
591  /* Attribute ID/Value Sequence: */
592  l2capoutbuf[7] = 0x01;
593  l2capoutbuf[8] = 0x09;
594  l2capoutbuf[9] = 0x00;
595  l2capoutbuf[10] = 0x06;
596  l2capoutbuf[11] = 0x35;
597 
598  l2capoutbuf[12] = 0x09;
599  l2capoutbuf[13] = 0x09;
600  l2capoutbuf[14] = 0x65;
601  l2capoutbuf[15] = 0x6E;
602  l2capoutbuf[16] = 0x09;
603  l2capoutbuf[17] = 0x00;
604  l2capoutbuf[18] = 0x6A;
605  l2capoutbuf[19] = 0x09;
606  l2capoutbuf[20] = 0x01;
607  l2capoutbuf[21] = 0x00;
608  l2capoutbuf[22] = 0x09;
609  l2capoutbuf[23] = 0x01;
610  l2capoutbuf[24] = 0x00;
611  l2capoutbuf[25] = 0x25;
612 
613  l2capoutbuf[26] = 0x05; // Name length
614  l2capoutbuf[27] = 'T';
615  l2capoutbuf[28] = 'K';
616  l2capoutbuf[29] = 'J';
617  l2capoutbuf[30] = 'S';
618  l2capoutbuf[31] = 'P';
619  l2capoutbuf[32] = 0x00; // No more data
620 
621  SDP_Command(l2capoutbuf,33);
622 }
623 void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
624  serialPortResponse1(transactionIDHigh,transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again
625 }
626 void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
627  serialPortResponse2(transactionIDHigh,transactionIDLow); // Same data as serialPortResponse2
628 }
629 /************************************************************/
630 /* RFCOMM Commands */
631 /************************************************************/
632 void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) {
633  if ((millis() - printTimer) < 10)// Check if is has been more than 10ms since last command
634  delay((uint32_t)(10 - (millis() - printTimer))); // There have to be a delay between commands
635  pBtd->L2CAP_Command(hci_handle,data,nbytes,rfcomm_scid[0],rfcomm_scid[1]);
636  printTimer = millis();
637 }
638 
639 void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) {
640  l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
641  l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
642  l2capoutbuf[2] = length << 1 | 0x01; // Length and format (allways 0x01 bytes format)
643  uint8_t i = 0;
644  for(; i < length; i++)
645  l2capoutbuf[i+3] = data[i];
646  l2capoutbuf[i+3] = calcFcs(l2capoutbuf);
647 #ifdef EXTRADEBUG
648  Notify(PSTR(" - RFCOMM Data: "));
649  for(i = 0; i < length+4; i++) {
650  Serial.print(l2capoutbuf[i],HEX);
651  Notify(PSTR(" "));
652  }
653 #endif
654  RFCOMM_Command(l2capoutbuf,length+4);
655 }
656 
657 void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) {
658  l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
659  l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
660  l2capoutbuf[2] = 0x01; // Length = 0
661  l2capoutbuf[3] = credit; // Credit
662  l2capoutbuf[4] = calcFcs(l2capoutbuf);
663 #ifdef EXTRADEBUG
664  Notify(PSTR(" - RFCOMM Credit Data: "));
665  for(uint8_t i = 0; i < 5; i++) {
666  Serial.print(l2capoutbuf[i],HEX);
667  Notify(PSTR(" "));
668  }
669 #endif
670  RFCOMM_Command(l2capoutbuf,5);
671 }
672 
673 /* CRC on 2 bytes */
674 uint8_t SPP::__crc(uint8_t* data) {
675  return(pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xff ^ data[0]]) ^ data[1]]));
676 }
677 
678 /* Calculate FCS - we never actually check if the host sends correct FCS to the Arduino */
679 uint8_t SPP::calcFcs(uint8_t *data) {
680  if((data[1] & 0xEF) == RFCOMM_UIH)
681  return (0xff - __crc(data)); // FCS on 2 bytes
682  else
683  return (0xff - pgm_read_byte(&rfcomm_crc_table[__crc(data) ^ data[2]])); // FCS on 3 bytes
684 }
685 
686 /* Serial commands */
687 void SPP::print(const String &str) {
688  if(!connected)
689  return;
690  uint8_t length = str.length();
691  if(length > (sizeof(l2capoutbuf)-4))
692  length = sizeof(l2capoutbuf)-4;
693  l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address
694  l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
695  l2capoutbuf[2] = length << 1 | 1; // Length
696  uint8_t i = 0;
697  for(; i < length; i++)
698  l2capoutbuf[i+3] = str[i];
699  l2capoutbuf[i+3] = calcFcs(l2capoutbuf);
700 
701  RFCOMM_Command(l2capoutbuf,length+4);
702 }
703 void SPP::print(const char* str) {
704  if(!connected)
705  return;
706  uint8_t length = strlen(str);
707  if(length > (sizeof(l2capoutbuf)-4))
708  length = sizeof(l2capoutbuf)-4;
709  l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address
710  l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
711  l2capoutbuf[2] = length << 1 | 1; // Length
712  uint8_t i = 0;
713  for(; i < length; i++)
714  l2capoutbuf[i+3] = str[i];
715  l2capoutbuf[i+3] = calcFcs(l2capoutbuf);
716 
717  RFCOMM_Command(l2capoutbuf,length+4);
718 }
719 void SPP::print(uint8_t data) {
720  print(&data,1);
721 }
722 void SPP::print(uint8_t* array, uint8_t length) {
723  if(!connected)
724  return;
725  if(length > (sizeof(l2capoutbuf)-4))
726  length = sizeof(l2capoutbuf)-4;
727  l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress;; // RFCOMM Address
728  l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
729  l2capoutbuf[2] = length << 1 | 1; // Length
730  uint8_t i = 0;
731  for(; i < length; i++)
732  l2capoutbuf[i+3] = array[i];
733  l2capoutbuf[i+3] = calcFcs(l2capoutbuf);
734 
735  RFCOMM_Command(l2capoutbuf,length+4);
736 }
737 void SPP::print(const __FlashStringHelper *ifsh) {
738  const char PROGMEM *p = (const char PROGMEM *)ifsh;
739  size_t size = 0;
740  while (1) { // Calculate the size of the string
741  uint8_t c = pgm_read_byte(p+size);
742  if (c == 0)
743  break;
744  size++;
745  }
746  uint8_t buf[size];
747 
748  for(uint8_t i = 0; i < size; i++)
749  buf[i] = pgm_read_byte(p++);
750 
751  print(buf,size);
752 }
753 void SPP::println(const String &str) {
754  String output = str + "\r\n";
755  print(output);
756 }
757 void SPP::println(const char* str) {
758  char output[strlen(str)+3];
759  strcpy(output,str);
760  strcat(output,"\r\n");
761  print(output);
762 }
763 void SPP::println(uint8_t data) {
764  uint8_t buf[3] = {data, '\r', '\n'};
765  print(buf,3);
766 }
767 void SPP::println(uint8_t* array, uint8_t length) {
768  uint8_t buf[length+2];
769  memcpy(buf,array,length);
770  buf[length] = '\r';
771  buf[length+1] = '\n';
772  print(buf,length+2);
773 }
774 void SPP::println(const __FlashStringHelper *ifsh) {
775  const char PROGMEM *p = (const char PROGMEM *)ifsh;
776  size_t size = 0;
777  while (1) { // Calculate the size of the string
778  uint8_t c = pgm_read_byte(p+size);
779  if (c == 0)
780  break;
781  size++;
782  }
783  uint8_t buf[size+2];
784 
785  for(uint8_t i = 0; i < size; i++)
786  buf[i] = pgm_read_byte(p++);
787 
788  buf[size] = '\r';
789  buf[size+1] = '\n';
790  print(buf,size+2);
791 }
792 void SPP::println(void) {
793  uint8_t buf[2] = {'\r','\n'};
794  print(buf,2);
795 }
796 
797 /* These must be used to print numbers */
798 void SPP::printNumber(int32_t n) {
799  bool negative = false;
800  if(n < 0) {
801  negative = true;
802  n = -n;
803  }
804  uint32_t temp = n;
805  uint8_t digits = 0;
806  while (temp) {
807  temp /= 10;
808  digits++;
809  }
810  if(digits == 0)
811  print("0");
812  else {
813  uint8_t buf[digits+1]; // Add one extra in case it is negative
814  for(uint8_t i = 1; i < digits+1; i++) {
815  if(negative)
816  buf[digits-i+1] = n%10 + '0'; // Get number and convert to ASCII Character
817  else
818  buf[digits-i] = n%10 + '0'; // Get number and convert to ASCII Character
819  n /= 10;
820  }
821  if(negative) {
822  buf[0] = '-';
823  print(buf,digits+1);
824  } else
825  print(buf,digits);
826  }
827 }
828 void SPP::printNumberln(int32_t n) {
829  bool negative = false;
830  if(n < 0) {
831  negative = true;
832  n = -n;
833  }
834  uint32_t temp = n;
835  uint8_t digits = 0;
836  while (temp) {
837  temp /= 10;
838  digits++;
839  }
840  if(digits == 0)
841  print("0\r\n");
842  else {
843  uint8_t buf[digits+3]; // Add one extra in case it is negative
844  for(uint8_t i = 1; i < digits+1; i++) {
845  if(negative)
846  buf[digits-i+1] = n%10 + '0'; // Get number and convert to ASCII Character
847  else
848  buf[digits-i] = n%10 + '0'; // Get number and convert to ASCII Character
849  n /= 10;
850  }
851  if(negative) {
852  buf[0] = '-';
853  buf[digits+1] = '\r';
854  buf[digits+2] = '\n';
855  print(buf,digits+3);
856  } else {
857  buf[digits] = '\r';
858  buf[digits+1] = '\n';
859  print(buf,digits+2);
860  }
861  }
862 }
863 void SPP::printNumber(double n, uint8_t digits) {
864  char output[10];
865  doubleToString(n,output,digits);
866  print(output);
867 }
868 void SPP::printNumberln(double n, uint8_t digits) {
869  char buf[10];
870  char output[12];
871  doubleToString(n,buf,digits);
872  strcpy(output,buf);
873  strcat(output,"\r\n");
874  print(output);
875 }
876 void SPP::doubleToString(double input, char* output, uint8_t digits) {
877  char buffer[10];
878  if(input < 0) {
879  strcpy(output,"-");
880  input = -input;
881  }
882  else
883  strcpy(output,"");
884 
885  // Round correctly
886  double rounding = 0.5;
887  for (uint8_t i=0; i<digits; i++)
888  rounding /= 10.0;
889  input += rounding;
890 
891  unsigned long intpart = (unsigned long)input;
892  itoa(intpart,buffer,10); // Convert to string
893  strcat(output,buffer);
894  strcat(output,".");
895  double fractpart = (input-(double)intpart);
896  fractpart *= pow(10,digits);
897  for(uint8_t i=1;i<digits;i++) { // Put zeroes in front of number
898  if(fractpart < pow(10,digits-i)) {
899  strcat(output,"0");
900  }
901  }
902  itoa((unsigned long)fractpart,buffer,10); // Convert to string
903  strcat(output,buffer);
904 }
905 
906 uint8_t SPP::read() {
907  if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer
908  return 0;
909  uint8_t output = rfcommDataBuffer[0];
910  for(uint8_t i = 1; i < rfcommAvailable; i++)
911  rfcommDataBuffer[i-1] = rfcommDataBuffer[i]; // Shift the buffer one left
912  rfcommAvailable--;
913  bytesRead++;
914  if(bytesRead > (sizeof(rfcommDataBuffer)-5)) { // We will send the command just before it runs out of credit
915  bytesRead = 0;
916  sendRfcommCredit(rfcommChannelConnection,rfcommDirection,0,RFCOMM_UIH,0x10,sizeof(rfcommDataBuffer)); // Send more credit
917 #ifdef EXTRADEBUG
918  Notify(PSTR("\r\nSent "));
919  Serial.print(sizeof(rfcommDataBuffer));
920  Notify(PSTR(" more credit"));
921 #endif
922  }
923  return output;
924 }