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 // To enable serial debugging see "settings.h"
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 
63 void SPP::Reset() {
64  connected = false;
65  RFCOMMConnected = false;
66  SDPConnected = false;
67  waitForLastCommand = false;
68  l2cap_sdp_state = L2CAP_SDP_WAIT;
69  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
70  l2cap_event_flag = 0;
71  sppIndex = 0;
72 }
73 
75  connected = false;
76  // First the two L2CAP channels has to be disconencted and then the HCI connection
77  if (RFCOMMConnected)
78  pBtd->l2cap_disconnection_request(hci_handle, 0x0A, rfcomm_scid, rfcomm_dcid);
79  if (RFCOMMConnected && SDPConnected)
80  delay(1); // Add delay between commands
81  if (SDPConnected)
82  pBtd->l2cap_disconnection_request(hci_handle, 0x0B, sdp_scid, sdp_dcid);
83  l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE;
84 }
85 
86 void SPP::ACLData(uint8_t* l2capinbuf) {
87  if (!connected) {
88  if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
89  if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) {
90  pBtd->sdpConnectionClaimed = true;
91  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
92  l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state
93  } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) {
94  pBtd->rfcommConnectionClaimed = true;
95  hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
96  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state
97  }
98  }
99  }
100  if (((l2capinbuf[0] | (l2capinbuf[1] << 8)) == (hci_handle | 0x2000))) { // acl_handle_ok
101  if ((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001) { //l2cap_control - Channel ID for ACL-U
102  if (l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
103 #ifdef DEBUG_USB_HOST
104  Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
105  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
106  Notify(PSTR(" "), 0x80);
107  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
108  Notify(PSTR(" Data: "), 0x80);
109  D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
110  Notify(PSTR(" "), 0x80);
111  D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
112  Notify(PSTR(" "), 0x80);
113  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
114  Notify(PSTR(" "), 0x80);
115  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
116 #endif
117  } else if (l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
118 #ifdef EXTRADEBUG
119  Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
120  D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
121  Notify(PSTR(" "), 0x80);
122  D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
123  Notify(PSTR(" SCID: "), 0x80);
124  D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
125  Notify(PSTR(" "), 0x80);
126  D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
127  Notify(PSTR(" Identifier: "), 0x80);
128  D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
129 #endif
130  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
131  identifier = l2capinbuf[9];
132  sdp_scid[0] = l2capinbuf[14];
133  sdp_scid[1] = l2capinbuf[15];
134  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_SDP_REQUEST;
135  } else if ((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || -----
136  identifier = l2capinbuf[9];
137  rfcomm_scid[0] = l2capinbuf[14];
138  rfcomm_scid[1] = l2capinbuf[15];
139  l2cap_event_flag |= L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST;
140  }
141  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
142  if ((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
143  if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
144  //Notify(PSTR("\r\nSDP Configuration Complete"), 0x80);
145  l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_SUCCESS;
146  } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
147  //Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80);
148  l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS;
149  }
150  }
151  } else if (l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
152  if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
153  //Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
154  identifier = l2capinbuf[9];
155  l2cap_event_flag |= L2CAP_FLAG_CONFIG_SDP_REQUEST;
156  } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
157  //Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80);
158  identifier = l2capinbuf[9];
159  l2cap_event_flag |= L2CAP_FLAG_CONFIG_RFCOMM_REQUEST;
160  }
161  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
162  if (l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
163  //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80);
164  identifier = l2capinbuf[9];
165  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_SDP_REQUEST;
166  } else if (l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
167  //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80);
168  identifier = l2capinbuf[9];
169  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST;
170  }
171  } else if (l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
172  if (l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {
173  //Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80);
174  identifier = l2capinbuf[9];
175  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE;
176  } else if (l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) {
177  //Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80);
178  identifier = l2capinbuf[9];
179  l2cap_event_flag |= L2CAP_FLAG_DISCONNECT_RESPONSE;
180  }
181  } else if (l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) {
182 #ifdef DEBUG_USB_HOST
183  Notify(PSTR("\r\nInformation request"), 0x80);
184 #endif
185  identifier = l2capinbuf[9];
186  pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]);
187  }
188 #ifdef EXTRADEBUG
189  else {
190  Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
191  D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
192  }
193 #endif
194  } else if (l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP
195  if (l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) {
196  if (((l2capinbuf[16] << 8 | l2capinbuf[17]) == SERIALPORT_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == SERIALPORT_UUID)) { // Check if it's sending the full UUID, see: https://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm, we will just check the first four bytes
197  if (firstMessage) {
198  serialPortResponse1(l2capinbuf[9], l2capinbuf[10]);
199  firstMessage = false;
200  } else {
201  serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state
202  firstMessage = true;
203  }
204  } else if (((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) {
205  if (firstMessage) {
206  l2capResponse1(l2capinbuf[9], l2capinbuf[10]);
207  firstMessage = false;
208  } else {
209  l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state
210  firstMessage = true;
211  }
212  } else
213  serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported
214 #ifdef EXTRADEBUG
215  Notify(PSTR("\r\nUUID: "), 0x80);
216  uint16_t uuid;
217  if((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000) // Check if it's sending the UUID as a 128-bit UUID
218  uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]);
219  else // Short UUID
220  uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]);
221  D_PrintHex<uint16_t> (uuid, 0x80);
222 
223  Notify(PSTR("\r\nLength: "), 0x80);
224  uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];
225  D_PrintHex<uint16_t> (length, 0x80);
226  Notify(PSTR("\r\nData: "), 0x80);
227  for (uint8_t i = 0; i < length; i++) {
228  D_PrintHex<uint8_t> (l2capinbuf[13+i], 0x80);
229  Notify(PSTR(" "), 0x80);
230  }
231 #endif
232  }
233 #ifdef EXTRADEBUG
234  else {
235  Notify(PSTR("\r\nUnknown PDU: "), 0x80);
236  D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
237  }
238 #endif
239  } else if (l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM
240  rfcommChannel = l2capinbuf[8] & 0xF8;
241  rfcommDirection = l2capinbuf[8] & 0x04;
242  rfcommCommandResponse = l2capinbuf[8] & 0x02;
243  rfcommChannelType = l2capinbuf[9] & 0xEF;
244  rfcommPfBit = l2capinbuf[9] & 0x10;
245 
246  if (rfcommChannel >> 3 != 0x00)
247  rfcommChannelConnection = rfcommChannel;
248 
249 #ifdef EXTRADEBUG
250  Notify(PSTR("\r\nRFCOMM Channel: "), 0x80);
251  D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
252  Notify(PSTR(" Direction: "), 0x80);
253  D_PrintHex<uint8_t > (rfcommDirection >> 2, 0x80);
254  Notify(PSTR(" CommandResponse: "), 0x80);
255  D_PrintHex<uint8_t > (rfcommCommandResponse >> 1, 0x80);
256  Notify(PSTR(" ChannelType: "), 0x80);
257  D_PrintHex<uint8_t > (rfcommChannelType, 0x80);
258  Notify(PSTR(" PF_BIT: "), 0x80);
259  D_PrintHex<uint8_t > (rfcommPfBit, 0x80);
260 #endif
261  if (rfcommChannelType == RFCOMM_DISC) {
262 #ifdef DEBUG_USB_HOST
263  Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80);
264  D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
265 #endif
266  connected = false;
267  sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
268  }
269  if (connected) {
270  /* Read the incoming message */
271  if (rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) {
272  uint8_t length = l2capinbuf[10] >> 1; // Get length
273  uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit
274  if (checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) {
275  uint8_t i = 0;
276  for (; i < length; i++) {
277  if (rfcommAvailable + i >= sizeof (rfcommDataBuffer)) {
278 #ifdef DEBUG_USB_HOST
279  Notify(PSTR("\r\nWarning: Buffer is full!"), 0x80);
280 #endif
281  break;
282  }
283  rfcommDataBuffer[rfcommAvailable + i] = l2capinbuf[11 + i + offset];
284  }
285  rfcommAvailable += i;
286 #ifdef EXTRADEBUG
287  Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80);
288  Notify(rfcommAvailable, 0x80);
289  if (offset) {
290  Notify(PSTR(" - Credit: 0x"), 0x80);
291  D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);
292  }
293 #endif
294  }
295 #ifdef DEBUG_USB_HOST
296  else
297  Notify(PSTR("\r\nError in FCS checksum!"), 0x80);
298 #endif
299 #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth
300  for (uint8_t i = 0; i < length; i++)
301  Notifyc(l2capinbuf[i + 11 + offset], 0x80);
302 #endif
303  } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
304 #ifdef DEBUG_USB_HOST
305  Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
306 #endif
307  rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command
308  rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
309  rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
310  rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
311  rfcommbuf[4] = l2capinbuf[15]; // Priority
312  rfcommbuf[5] = l2capinbuf[16]; // Timer
313  rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB
314  rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB
315  rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
316  rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
317  sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response
318  } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
319 #ifdef DEBUG_USB_HOST
320  Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
321 #endif
322  rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response
323  rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
324  rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
325  rfcommbuf[3] = l2capinbuf[14];
326  sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
327  }
328  } else {
329  if (rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish
330 #ifdef DEBUG_USB_HOST
331  Notify(PSTR("\r\nReceived SABM Command"), 0x80);
332 #endif
333  sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
334  } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command
335 #ifdef DEBUG_USB_HOST
336  Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80);
337 #endif
338  rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response
339  rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
340  rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
341  rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
342  rfcommbuf[4] = 0x00; // Priority
343  rfcommbuf[5] = 0x00; // Timer
344  rfcommbuf[6] = BULK_MAXPKTSIZE - 14; // Max Fram Size LSB - set to the size of received data (50)
345  rfcommbuf[7] = 0x00; // Max Fram Size MSB
346  rfcommbuf[8] = 0x00; // MaxRatransm.
347  rfcommbuf[9] = 0x00; // Number of Frames
348  sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A);
349  } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
350 #ifdef DEBUG_USB_HOST
351  Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
352 #endif
353  rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response
354  rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
355  rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
356  rfcommbuf[3] = l2capinbuf[14];
357  sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
358 
359  delay(1);
360 #ifdef DEBUG_USB_HOST
361  Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80);
362 #endif
363  rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command
364  rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
365  rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
366  rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES)
367 
368  sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
369  } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response
370  if (!creditSent) {
371 #ifdef DEBUG_USB_HOST
372  Notify(PSTR("\r\nSend UIH Command with credit"), 0x80);
373 #endif
374  sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit
375  creditSent = true;
376  timer = millis();
377  waitForLastCommand = true;
378  }
379  } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit
380 #ifdef DEBUG_USB_HOST
381  Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80);
382 #endif
383  } else if (rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
384 #ifdef DEBUG_USB_HOST
385  Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
386 #endif
387  rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command
388  rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
389  rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
390  rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
391  rfcommbuf[4] = l2capinbuf[15]; // Priority
392  rfcommbuf[5] = l2capinbuf[16]; // Timer
393  rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB
394  rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB
395  rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
396  rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
397  sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response
398 #ifdef DEBUG_USB_HOST
399  Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80);
400 #endif
401  waitForLastCommand = false;
402  creditSent = false;
403  connected = true; // The RFCOMM channel is now established
404  sppIndex = 0;
405  }
406 #ifdef DEBUG_USB_HOST
407  else if (rfcommChannelType != RFCOMM_DISC) {
408  Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80);
409  D_PrintHex<uint8_t > (rfcommChannelType, 0x80);
410  Notify(PSTR(" Command: "), 0x80);
411  D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);
412  }
413 #endif
414  }
415  }
416 #ifdef EXTRADEBUG
417  else {
418  Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80);
419  D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);
420  Notify(PSTR(" "), 0x80);
421  D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);
422  }
423 #endif
424  SDP_task();
425  RFCOMM_task();
426  }
427 }
428 
429 void SPP::Run() {
430  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
431 #ifdef DEBUG_USB_HOST
432  Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80);
433 #endif
434  creditSent = false;
435  waitForLastCommand = false;
436  connected = true; // The RFCOMM channel is now established
437  sppIndex = 0;
438  }
439  send(); // Send all bytes currently in the buffer
440 }
441 
442 void SPP::SDP_task() {
443  switch (l2cap_sdp_state) {
444  case L2CAP_SDP_WAIT:
446  l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_SDP_REQUEST; // Clear flag
447 #ifdef DEBUG_USB_HOST
448  Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80);
449 #endif
450  pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, PENDING);
451  delay(1);
452  pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, SUCCESSFUL);
453  identifier++;
454  delay(1);
455  pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid);
456  l2cap_sdp_state = L2CAP_SDP_REQUEST;
457  }
458  break;
459  case L2CAP_SDP_REQUEST:
461  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_REQUEST; // Clear flag
462 #ifdef DEBUG_USB_HOST
463  Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
464 #endif
465  pBtd->l2cap_config_response(hci_handle, identifier, sdp_scid);
466  l2cap_sdp_state = L2CAP_SDP_SUCCESS;
467  }
468  break;
469  case L2CAP_SDP_SUCCESS:
471  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_SDP_SUCCESS; // Clear flag
472 #ifdef DEBUG_USB_HOST
473  Notify(PSTR("\r\nSDP Successfully Configured"), 0x80);
474 #endif
475  firstMessage = true; // Reset bool
476  SDPConnected = true;
477  l2cap_sdp_state = L2CAP_SDP_DONE;
478  }
479  break;
480  case L2CAP_SDP_DONE:
482  l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_SDP_REQUEST; // Clear flag
483  SDPConnected = false;
484 #ifdef DEBUG_USB_HOST
485  Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80);
486 #endif
487  pBtd->l2cap_disconnection_response(hci_handle, identifier, sdp_dcid, sdp_scid);
488  l2cap_sdp_state = L2CAP_SDP_WAIT;
490  l2cap_rfcomm_state = L2CAP_SDP_WAIT;
491  break;
492  case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
494 #ifdef DEBUG_USB_HOST
495  Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80);
496 #endif
497  RFCOMMConnected = false;
498  SDPConnected = false;
499  pBtd->hci_disconnect(hci_handle);
500  hci_handle = -1; // Reset handle
501  l2cap_event_flag = 0; // Reset flags
502  l2cap_sdp_state = L2CAP_SDP_WAIT;
503  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
504  }
505  break;
506  }
507 }
508 
509 void SPP::RFCOMM_task() {
510  switch (l2cap_rfcomm_state) {
511  case L2CAP_RFCOMM_WAIT:
513  l2cap_event_flag &= ~L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST; // Clear flag
514 #ifdef DEBUG_USB_HOST
515  Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80);
516 #endif
517  pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, PENDING);
518  delay(1);
519  pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL);
520  identifier++;
521  delay(1);
522  pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid);
523  l2cap_rfcomm_state = L2CAP_RFCOMM_REQUEST;
524  }
525  break;
528  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_REQUEST; // Clear flag
529 #ifdef DEBUG_USB_HOST
530  Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80);
531 #endif
532  pBtd->l2cap_config_response(hci_handle, identifier, rfcomm_scid);
533  l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS;
534  }
535  break;
538  l2cap_event_flag &= ~L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS; // Clear flag
539 #ifdef DEBUG_USB_HOST
540  Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80);
541 #endif
542  rfcommAvailable = 0; // Reset number of bytes available
543  bytesRead = 0; // Reset number of bytes received
544  RFCOMMConnected = true;
545  l2cap_rfcomm_state = L2CAP_RFCOMM_DONE;
546  }
547  break;
548  case L2CAP_RFCOMM_DONE:
550  l2cap_event_flag &= ~L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST; // Clear flag
551  RFCOMMConnected = false;
552  connected = false;
553 #ifdef DEBUG_USB_HOST
554  Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80);
555 #endif
556  pBtd->l2cap_disconnection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid);
557  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
559  l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
560  break;
561  }
562 }
563 /************************************************************/
564 /* SDP Commands */
565 
566 /************************************************************/
567 void SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs
568  pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]);
569 }
570 
571 void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs
573  l2capoutbuf[1] = transactionIDHigh;
574  l2capoutbuf[2] = transactionIDLow;
575  l2capoutbuf[3] = 0x00; // Parameter Length
576  l2capoutbuf[4] = 0x05; // Parameter Length
577  l2capoutbuf[5] = 0x00; // AttributeListsByteCount
578  l2capoutbuf[6] = 0x02; // AttributeListsByteCount
579 
580  /* Attribute ID/Value Sequence: */
581  l2capoutbuf[7] = 0x35;
582  l2capoutbuf[8] = 0x00;
583  l2capoutbuf[9] = 0x00;
584 
585  SDP_Command(l2capoutbuf, 10);
586 }
587 
588 void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
590  l2capoutbuf[1] = transactionIDHigh;
591  l2capoutbuf[2] = transactionIDLow;
592  l2capoutbuf[3] = 0x00; // Parameter Length
593  l2capoutbuf[4] = 0x2B; // Parameter Length
594  l2capoutbuf[5] = 0x00; // AttributeListsByteCount
595  l2capoutbuf[6] = 0x26; // AttributeListsByteCount
596 
597  /* Attribute ID/Value Sequence: */
598  l2capoutbuf[7] = 0x36;
599  l2capoutbuf[8] = 0x00;
600  l2capoutbuf[9] = 0x3C;
601  l2capoutbuf[10] = 0x36;
602  l2capoutbuf[11] = 0x00;
603 
604  l2capoutbuf[12] = 0x39;
605  l2capoutbuf[13] = 0x09;
606  l2capoutbuf[14] = 0x00;
607  l2capoutbuf[15] = 0x00;
608  l2capoutbuf[16] = 0x0A;
609  l2capoutbuf[17] = 0x00;
610  l2capoutbuf[18] = 0x01;
611  l2capoutbuf[19] = 0x00;
612  l2capoutbuf[20] = 0x06;
613  l2capoutbuf[21] = 0x09;
614  l2capoutbuf[22] = 0x00;
615  l2capoutbuf[23] = 0x01;
616  l2capoutbuf[24] = 0x35;
617  l2capoutbuf[25] = 0x03;
618  l2capoutbuf[26] = 0x19;
619  l2capoutbuf[27] = 0x11;
620 
621  l2capoutbuf[28] = 0x01;
622  l2capoutbuf[29] = 0x09;
623  l2capoutbuf[30] = 0x00;
624  l2capoutbuf[31] = 0x04;
625  l2capoutbuf[32] = 0x35;
626  l2capoutbuf[33] = 0x0C;
627  l2capoutbuf[34] = 0x35;
628  l2capoutbuf[35] = 0x03;
629  l2capoutbuf[36] = 0x19;
630  l2capoutbuf[37] = 0x01;
631  l2capoutbuf[38] = 0x00;
632  l2capoutbuf[39] = 0x35;
633  l2capoutbuf[40] = 0x05;
634  l2capoutbuf[41] = 0x19;
635  l2capoutbuf[42] = 0x00;
636  l2capoutbuf[43] = 0x03;
637 
638  l2capoutbuf[44] = 0x08;
639  l2capoutbuf[45] = 0x02; // Two extra bytes
640  l2capoutbuf[46] = 0x00; // 25 (0x19) more bytes to come
641  l2capoutbuf[47] = 0x19;
642 
643  SDP_Command(l2capoutbuf, 48);
644 }
645 
646 void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
648  l2capoutbuf[1] = transactionIDHigh;
649  l2capoutbuf[2] = transactionIDLow;
650  l2capoutbuf[3] = 0x00; // Parameter Length
651  l2capoutbuf[4] = 0x1C; // Parameter Length
652  l2capoutbuf[5] = 0x00; // AttributeListsByteCount
653  l2capoutbuf[6] = 0x19; // AttributeListsByteCount
654 
655  /* Attribute ID/Value Sequence: */
656  l2capoutbuf[7] = 0x01;
657  l2capoutbuf[8] = 0x09;
658  l2capoutbuf[9] = 0x00;
659  l2capoutbuf[10] = 0x06;
660  l2capoutbuf[11] = 0x35;
661 
662  l2capoutbuf[12] = 0x09;
663  l2capoutbuf[13] = 0x09;
664  l2capoutbuf[14] = 0x65;
665  l2capoutbuf[15] = 0x6E;
666  l2capoutbuf[16] = 0x09;
667  l2capoutbuf[17] = 0x00;
668  l2capoutbuf[18] = 0x6A;
669  l2capoutbuf[19] = 0x09;
670  l2capoutbuf[20] = 0x01;
671  l2capoutbuf[21] = 0x00;
672  l2capoutbuf[22] = 0x09;
673  l2capoutbuf[23] = 0x01;
674  l2capoutbuf[24] = 0x00;
675  l2capoutbuf[25] = 0x25;
676 
677  l2capoutbuf[26] = 0x05; // Name length
678  l2capoutbuf[27] = 'T';
679  l2capoutbuf[28] = 'K';
680  l2capoutbuf[29] = 'J';
681  l2capoutbuf[30] = 'S';
682  l2capoutbuf[31] = 'P';
683  l2capoutbuf[32] = 0x00; // No more data
684 
685  SDP_Command(l2capoutbuf, 33);
686 }
687 
688 void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
689  serialPortResponse1(transactionIDHigh, transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again
690 }
691 
692 void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
693  serialPortResponse2(transactionIDHigh, transactionIDLow); // Same data as serialPortResponse2
694 }
695 /************************************************************/
696 /* RFCOMM Commands */
697 
698 /************************************************************/
699 void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) {
700  pBtd->L2CAP_Command(hci_handle, data, nbytes, rfcomm_scid[0], rfcomm_scid[1]);
701 }
702 
703 void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) {
704  l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
705  l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
706  l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format)
707  uint8_t i = 0;
708  for (; i < length; i++)
709  l2capoutbuf[i + 3] = data[i];
710  l2capoutbuf[i + 3] = calcFcs(l2capoutbuf);
711 #ifdef EXTRADEBUG
712  Notify(PSTR(" - RFCOMM Data: "), 0x80);
713  for (i = 0; i < length + 4; i++) {
714  D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
715  Notify(PSTR(" "), 0x80);
716  }
717 #endif
718  RFCOMM_Command(l2capoutbuf, length + 4);
719 }
720 
721 void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) {
722  l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
723  l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
724  l2capoutbuf[2] = 0x01; // Length = 0
725  l2capoutbuf[3] = credit; // Credit
726  l2capoutbuf[4] = calcFcs(l2capoutbuf);
727 #ifdef EXTRADEBUG
728  Notify(PSTR(" - RFCOMM Credit Data: "), 0x80);
729  for (uint8_t i = 0; i < 5; i++) {
730  D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
731  Notify(PSTR(" "), 0x80);
732  }
733 #endif
734  RFCOMM_Command(l2capoutbuf, 5);
735 }
736 
737 /* CRC on 2 bytes */
738 uint8_t SPP::crc(uint8_t *data) {
739  return (pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xFF ^ data[0]]) ^ data[1]]));
740 }
741 
742 /* Calculate FCS */
743 uint8_t SPP::calcFcs(uint8_t *data) {
744  if ((data[1] & 0xEF) == RFCOMM_UIH)
745  return (0xFF - crc(data)); // FCS on 2 bytes
746  else
747  return (0xFF - pgm_read_byte(&rfcomm_crc_table[crc(data) ^ data[2]])); // FCS on 3 bytes
748 }
749 
750 /* Check FCS */
751 bool SPP::checkFcs(uint8_t *data, uint8_t fcs) {
752  uint8_t temp = crc(data);
753  if ((data[1] & 0xEF) != RFCOMM_UIH)
754  temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes
755  return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF);
756 }
757 
758 /* Serial commands */
759 size_t SPP::write(uint8_t data) {
760  return write(&data,1);
761 }
762 
763 size_t SPP::write(const uint8_t *data, size_t size) {
764  for(uint8_t i = 0; i < size; i++) {
765  if(sppIndex >= sizeof(sppOutputBuffer)/sizeof(sppOutputBuffer[0]))
766  send(); // Send the current data in the buffer
767  sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function
768  }
769  return size;
770 }
771 
772 void SPP::send() {
773  if (!connected || !sppIndex)
774  return;
775  uint8_t length; // This is the length of the string we are sending
776  uint8_t offset = 0; // This is used to keep track of where we are in the string
777 
778  l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
779  l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
780 
781  while (sppIndex) { // We will run this while loop until this variable is 0
782  if (sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer
783  length = sizeof (l2capoutbuf) - 4;
784  else
785  length = sppIndex;
786 
787  l2capoutbuf[2] = length << 1 | 1; // Length
788  uint8_t i = 0;
789  for (; i < length; i++)
790  l2capoutbuf[i + 3] = sppOutputBuffer[i + offset];
791  l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
792 
793  RFCOMM_Command(l2capoutbuf, length + 4);
794 
795  sppIndex -= length;
796  offset += length; // Increment the offset
797  }
798 }
799 
800 int SPP::available(void) {
801  return rfcommAvailable;
802 };
803 
804 void SPP::flush(void) {
805  rfcommAvailable = 0;
806 }
807 
808 int SPP::peek(void) {
809  if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer
810  return -1;
811  return rfcommDataBuffer[0];
812 }
813 
814 int SPP::read(void) {
815  if (rfcommAvailable == 0) // Don't read if there is nothing in the buffer
816  return -1;
817  uint8_t output = rfcommDataBuffer[0];
818  for (uint8_t i = 1; i < rfcommAvailable; i++)
819  rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left
820  rfcommAvailable--;
821  bytesRead++;
822  if (bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit
823  bytesRead = 0;
824  sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit
825 #ifdef EXTRADEBUG
826  Notify(PSTR("\r\nSent "), 0x80);
827  Notify((uint8_t)sizeof (rfcommDataBuffer), 0x80);
828  Notify(PSTR(" more credit"), 0x80);
829 #endif
830  }
831  return output;
832 }
virtual size_t write(uint8_t data)
Definition: SPP.cpp:759
const char * btdName
Definition: BTD.h:405
#define BT_RFCOMM_RPN_RSP
Definition: SPP.h:79
void l2cap_connection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid, uint8_t result)
Definition: BTD.cpp:1222
#define SUCCESSFUL
Definition: BTD.h:121
bool sdpConnectionClaimed
Definition: BTD.h:400
#define L2CAP_FLAG_CONFIG_SDP_REQUEST
Definition: SPP.h:39
#define RFCOMM_PSM
Definition: BTD.h:125
Definition: BTD.h:158
void l2cap_disconnection_request(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1275
#define RFCOMM_SABM
Definition: SPP.h:65
#define L2CAP_UUID
Definition: SPP.h:62
const uint8_t rfcomm_crc_table[256]
Definition: SPP.cpp:26
bool rfcommConnectionClaimed
Definition: BTD.h:402
#define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU
Definition: SPP.h:60
#define l2cap_connection_request_sdp_flag
Definition: SPP.h:48
#define L2CAP_FLAG_CONNECTION_SDP_REQUEST
Definition: SPP.h:37
#define l2cap_disconnect_response_flag
Definition: SPP.h:56
#define RFCOMM_DISC
Definition: SPP.h:69
#define L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS
Definition: SPP.h:42
#define SERIALPORT_UUID
Definition: SPP.h:61
#define L2CAP_SDP_DONE
Definition: SPP.h:27
virtual void flush(void)
Definition: SPP.cpp:804
#define L2CAP_DISCONNECT_RESPONSE
Definition: SPP.h:28
const char * btdPin
Definition: BTD.h:407
bool connected
Definition: SPP.h:111
#define L2CAP_FLAG_CONFIG_RFCOMM_REQUEST
Definition: SPP.h:40
#define L2CAP_CMD_INFORMATION_REQUEST
Definition: BTD.h:116
#define l2cap_config_request_sdp_flag
Definition: SPP.h:50
#define SDP_PSM
Definition: BTD.h:124
virtual int read(void)
Definition: SPP.cpp:814
void l2cap_disconnection_response(uint16_t handle, uint8_t rxid, uint8_t *dcid, uint8_t *scid)
Definition: BTD.cpp:1288
#define extendAddress
Definition: SPP.h:71
#define L2CAP_SDP_REQUEST
Definition: SPP.h:25
#define Notify(...)
Definition: message.h:44
#define l2cap_connection_request_rfcomm_flag
Definition: SPP.h:49
#define L2CAP_FLAG_CONFIG_SDP_SUCCESS
Definition: SPP.h:41
virtual void Run()
Definition: SPP.cpp:429
#define L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST
Definition: SPP.h:44
uint16_t hci_handle
Definition: BTD.h:412
#define Notifyc(...)
Definition: message.h:46
void hci_disconnect(uint16_t handle)
Definition: BTD.cpp:1133
virtual void Reset()
Definition: SPP.cpp:63
#define l2cap_config_success_rfcomm_flag
Definition: SPP.h:53
SPP(BTD *p, const char *name="Arduino", const char *pin="1234")
Definition: SPP.cpp:45
#define RFCOMM_UIH
Definition: SPP.h:67
virtual int available(void)
Definition: SPP.cpp:800
#define l2cap_disconnect_request_rfcomm_flag
Definition: SPP.h:55
#define L2CAP_SDP_SUCCESS
Definition: SPP.h:26
#define L2CAP_CMD_CONFIG_REQUEST
Definition: BTD.h:112
#define L2CAP_CMD_DISCONNECT_REQUEST
Definition: BTD.h:114
#define L2CAP_FLAG_DISCONNECT_SDP_REQUEST
Definition: SPP.h:43
#define L2CAP_RFCOMM_DONE
Definition: SPP.h:34
#define BULK_MAXPKTSIZE
Definition: BTD.h:33
#define BT_RFCOMM_RPN_CMD
Definition: SPP.h:78
int8_t registerServiceClass(BluetoothService *pService)
Definition: BTD.h:258
virtual void disconnect()
Definition: SPP.cpp:74
#define BT_RFCOMM_MSC_CMD
Definition: SPP.h:76
#define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU
Definition: SPP.h:59
#define L2CAP_CMD_DISCONNECT_RESPONSE
Definition: BTD.h:115
#define RFCOMM_UA
Definition: SPP.h:66
void l2cap_information_response(uint16_t handle, uint8_t rxid, uint8_t infoTypeLow, uint8_t infoTypeHigh)
Definition: BTD.cpp:1301
#define L2CAP_CMD_CONFIG_RESPONSE
Definition: BTD.h:113
#define L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST
Definition: SPP.h:38
#define L2CAP_RFCOMM_SUCCESS
Definition: SPP.h:33
#define BT_RFCOMM_PN_CMD
Definition: SPP.h:74
#define BT_RFCOMM_MSC_RSP
Definition: SPP.h:77
#define L2CAP_RFCOMM_REQUEST
Definition: SPP.h:32
#define L2CAP_SDP_WAIT
Definition: SPP.h:24
#define L2CAP_RFCOMM_WAIT
Definition: SPP.h:31
void send(void)
Definition: SPP.cpp:772
void L2CAP_Command(uint16_t handle, uint8_t *data, uint8_t nbytes, uint8_t channelLow=0x01, uint8_t channelHigh=0x00)
Definition: BTD.cpp:1181
void l2cap_config_response(uint16_t handle, uint8_t rxid, uint8_t *scid)
Definition: BTD.cpp:1256
#define PENDING
Definition: BTD.h:120
void l2cap_config_request(uint16_t handle, uint8_t rxid, uint8_t *dcid)
Definition: BTD.cpp:1239
#define l2cap_config_request_rfcomm_flag
Definition: SPP.h:51
#define L2CAP_CMD_CONNECTION_REQUEST
Definition: BTD.h:110
#define BT_RFCOMM_PN_RSP
Definition: SPP.h:75
#define l2cap_config_success_sdp_flag
Definition: SPP.h:52
#define l2cap_disconnect_request_sdp_flag
Definition: SPP.h:54
virtual void ACLData(uint8_t *ACLData)
Definition: SPP.cpp:86
virtual int peek(void)
Definition: SPP.cpp:808
#define L2CAP_FLAG_DISCONNECT_RESPONSE
Definition: SPP.h:45
#define L2CAP_CMD_COMMAND_REJECT
Definition: BTD.h:109