You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

829 lines
46 KiB

  1. /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
  2. This software may be distributed and modified under the terms of the GNU
  3. General Public License version 2 (GPL2) as published by the Free Software
  4. Foundation and appearing in the file GPL2.TXT included in the packaging of
  5. this file. Please note that GPL2 Section 2[b] requires that all works based
  6. on this software must also be made publicly available under the terms of
  7. the GPL2 ("Copyleft").
  8. Contact information
  9. -------------------
  10. Kristian Lauszus, TKJ Electronics
  11. Web : http://www.tkjelectronics.com
  12. e-mail : kristianl@tkjelectronics.com
  13. */
  14. #include "SPP.h"
  15. // To enable serial debugging see "settings.h"
  16. //#define EXTRADEBUG // Uncomment to get even more debugging data
  17. //#define PRINTREPORT // Uncomment to print the report sent to the Arduino
  18. /*
  19. * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
  20. */
  21. const uint8_t rfcomm_crc_table[256] PROGMEM = {/* reversed, 8-bit, poly=0x07 */
  22. 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
  23. 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
  24. 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
  25. 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
  26. 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
  27. 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
  28. 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
  29. 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
  30. 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
  31. 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
  32. 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
  33. 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
  34. 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
  35. 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
  36. 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
  37. 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
  38. };
  39. SPP::SPP(BTD *p, const char* name, const char* pin) :
  40. BluetoothService(p) // Pointer to BTD class instance - mandatory
  41. {
  42. pBtd->btdName = name;
  43. pBtd->btdPin = pin;
  44. /* Set device cid for the SDP and RFCOMM channelse */
  45. sdp_dcid[0] = 0x50; // 0x0050
  46. sdp_dcid[1] = 0x00;
  47. rfcomm_dcid[0] = 0x51; // 0x0051
  48. rfcomm_dcid[1] = 0x00;
  49. Reset();
  50. }
  51. void SPP::Reset() {
  52. connected = false;
  53. RFCOMMConnected = false;
  54. SDPConnected = false;
  55. waitForLastCommand = false;
  56. l2cap_sdp_state = L2CAP_SDP_WAIT;
  57. l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
  58. l2cap_event_flag = 0;
  59. sppIndex = 0;
  60. creditSent = false;
  61. }
  62. void SPP::disconnect() {
  63. connected = false;
  64. // First the two L2CAP channels has to be disconnected and then the HCI connection
  65. if(RFCOMMConnected)
  66. pBtd->l2cap_disconnection_request(hci_handle, ++identifier, rfcomm_scid, rfcomm_dcid);
  67. if(RFCOMMConnected && SDPConnected)
  68. delay(1); // Add delay between commands
  69. if(SDPConnected)
  70. pBtd->l2cap_disconnection_request(hci_handle, ++identifier, sdp_scid, sdp_dcid);
  71. l2cap_sdp_state = L2CAP_DISCONNECT_RESPONSE;
  72. }
  73. void SPP::ACLData(uint8_t* l2capinbuf) {
  74. if(!connected) {
  75. if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
  76. if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == SDP_PSM && !pBtd->sdpConnectionClaimed) {
  77. pBtd->sdpConnectionClaimed = true;
  78. hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
  79. l2cap_sdp_state = L2CAP_SDP_WAIT; // Reset state
  80. } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM && !pBtd->rfcommConnectionClaimed) {
  81. pBtd->rfcommConnectionClaimed = true;
  82. hci_handle = pBtd->hci_handle; // Store the HCI Handle for the connection
  83. l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT; // Reset state
  84. }
  85. }
  86. }
  87. if(checkHciHandle(l2capinbuf, hci_handle)) { // acl_handle_ok
  88. if((l2capinbuf[6] | (l2capinbuf[7] << 8)) == 0x0001U) { // l2cap_control - Channel ID for ACL-U
  89. if(l2capinbuf[8] == L2CAP_CMD_COMMAND_REJECT) {
  90. #ifdef DEBUG_USB_HOST
  91. Notify(PSTR("\r\nL2CAP Command Rejected - Reason: "), 0x80);
  92. D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
  93. Notify(PSTR(" "), 0x80);
  94. D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
  95. Notify(PSTR(" Data: "), 0x80);
  96. D_PrintHex<uint8_t > (l2capinbuf[17], 0x80);
  97. Notify(PSTR(" "), 0x80);
  98. D_PrintHex<uint8_t > (l2capinbuf[16], 0x80);
  99. Notify(PSTR(" "), 0x80);
  100. D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
  101. Notify(PSTR(" "), 0x80);
  102. D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
  103. #endif
  104. } else if(l2capinbuf[8] == L2CAP_CMD_CONNECTION_REQUEST) {
  105. #ifdef EXTRADEBUG
  106. Notify(PSTR("\r\nL2CAP Connection Request - PSM: "), 0x80);
  107. D_PrintHex<uint8_t > (l2capinbuf[13], 0x80);
  108. Notify(PSTR(" "), 0x80);
  109. D_PrintHex<uint8_t > (l2capinbuf[12], 0x80);
  110. Notify(PSTR(" SCID: "), 0x80);
  111. D_PrintHex<uint8_t > (l2capinbuf[15], 0x80);
  112. Notify(PSTR(" "), 0x80);
  113. D_PrintHex<uint8_t > (l2capinbuf[14], 0x80);
  114. Notify(PSTR(" Identifier: "), 0x80);
  115. D_PrintHex<uint8_t > (l2capinbuf[9], 0x80);
  116. #endif
  117. 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
  118. identifier = l2capinbuf[9];
  119. sdp_scid[0] = l2capinbuf[14];
  120. sdp_scid[1] = l2capinbuf[15];
  121. l2cap_set_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST);
  122. } else if((l2capinbuf[12] | (l2capinbuf[13] << 8)) == RFCOMM_PSM) { // ----- || -----
  123. identifier = l2capinbuf[9];
  124. rfcomm_scid[0] = l2capinbuf[14];
  125. rfcomm_scid[1] = l2capinbuf[15];
  126. l2cap_set_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST);
  127. }
  128. } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_RESPONSE) {
  129. if((l2capinbuf[16] | (l2capinbuf[17] << 8)) == 0x0000) { // Success
  130. if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
  131. //Notify(PSTR("\r\nSDP Configuration Complete"), 0x80);
  132. l2cap_set_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS);
  133. } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
  134. //Notify(PSTR("\r\nRFCOMM Configuration Complete"), 0x80);
  135. l2cap_set_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS);
  136. }
  137. }
  138. } else if(l2capinbuf[8] == L2CAP_CMD_CONFIG_REQUEST) {
  139. if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
  140. //Notify(PSTR("\r\nSDP Configuration Request"), 0x80);
  141. pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], sdp_scid);
  142. } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
  143. //Notify(PSTR("\r\nRFCOMM Configuration Request"), 0x80);
  144. pBtd->l2cap_config_response(hci_handle, l2capinbuf[9], rfcomm_scid);
  145. }
  146. } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_REQUEST) {
  147. if(l2capinbuf[12] == sdp_dcid[0] && l2capinbuf[13] == sdp_dcid[1]) {
  148. //Notify(PSTR("\r\nDisconnect Request: SDP Channel"), 0x80);
  149. identifier = l2capinbuf[9];
  150. l2cap_set_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST);
  151. } else if(l2capinbuf[12] == rfcomm_dcid[0] && l2capinbuf[13] == rfcomm_dcid[1]) {
  152. //Notify(PSTR("\r\nDisconnect Request: RFCOMM Channel"), 0x80);
  153. identifier = l2capinbuf[9];
  154. l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST);
  155. }
  156. } else if(l2capinbuf[8] == L2CAP_CMD_DISCONNECT_RESPONSE) {
  157. if(l2capinbuf[12] == sdp_scid[0] && l2capinbuf[13] == sdp_scid[1]) {
  158. //Notify(PSTR("\r\nDisconnect Response: SDP Channel"), 0x80);
  159. identifier = l2capinbuf[9];
  160. l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);
  161. } else if(l2capinbuf[12] == rfcomm_scid[0] && l2capinbuf[13] == rfcomm_scid[1]) {
  162. //Notify(PSTR("\r\nDisconnect Response: RFCOMM Channel"), 0x80);
  163. identifier = l2capinbuf[9];
  164. l2cap_set_flag(L2CAP_FLAG_DISCONNECT_RESPONSE);
  165. }
  166. } else if(l2capinbuf[8] == L2CAP_CMD_INFORMATION_REQUEST) {
  167. #ifdef DEBUG_USB_HOST
  168. Notify(PSTR("\r\nInformation request"), 0x80);
  169. #endif
  170. identifier = l2capinbuf[9];
  171. pBtd->l2cap_information_response(hci_handle, identifier, l2capinbuf[12], l2capinbuf[13]);
  172. }
  173. #ifdef EXTRADEBUG
  174. else {
  175. Notify(PSTR("\r\nL2CAP Unknown Signaling Command: "), 0x80);
  176. D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
  177. }
  178. #endif
  179. } else if(l2capinbuf[6] == sdp_dcid[0] && l2capinbuf[7] == sdp_dcid[1]) { // SDP
  180. if(l2capinbuf[8] == SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU) {
  181. 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
  182. if(firstMessage) {
  183. serialPortResponse1(l2capinbuf[9], l2capinbuf[10]);
  184. firstMessage = false;
  185. } else {
  186. serialPortResponse2(l2capinbuf[9], l2capinbuf[10]); // Serialport continuation state
  187. firstMessage = true;
  188. }
  189. } else if(((l2capinbuf[16] << 8 | l2capinbuf[17]) == L2CAP_UUID) || ((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000 && (l2capinbuf[18] << 8 | l2capinbuf[19]) == L2CAP_UUID)) {
  190. if(firstMessage) {
  191. l2capResponse1(l2capinbuf[9], l2capinbuf[10]);
  192. firstMessage = false;
  193. } else {
  194. l2capResponse2(l2capinbuf[9], l2capinbuf[10]); // L2CAP continuation state
  195. firstMessage = true;
  196. }
  197. } else
  198. serviceNotSupported(l2capinbuf[9], l2capinbuf[10]); // The service is not supported
  199. #ifdef EXTRADEBUG
  200. Notify(PSTR("\r\nUUID: "), 0x80);
  201. uint16_t uuid;
  202. if((l2capinbuf[16] << 8 | l2capinbuf[17]) == 0x0000) // Check if it's sending the UUID as a 128-bit UUID
  203. uuid = (l2capinbuf[18] << 8 | l2capinbuf[19]);
  204. else // Short UUID
  205. uuid = (l2capinbuf[16] << 8 | l2capinbuf[17]);
  206. D_PrintHex<uint16_t > (uuid, 0x80);
  207. Notify(PSTR("\r\nLength: "), 0x80);
  208. uint16_t length = l2capinbuf[11] << 8 | l2capinbuf[12];
  209. D_PrintHex<uint16_t > (length, 0x80);
  210. Notify(PSTR("\r\nData: "), 0x80);
  211. for(uint8_t i = 0; i < length; i++) {
  212. D_PrintHex<uint8_t > (l2capinbuf[13 + i], 0x80);
  213. Notify(PSTR(" "), 0x80);
  214. }
  215. #endif
  216. }
  217. #ifdef EXTRADEBUG
  218. else {
  219. Notify(PSTR("\r\nUnknown PDU: "), 0x80);
  220. D_PrintHex<uint8_t > (l2capinbuf[8], 0x80);
  221. }
  222. #endif
  223. } else if(l2capinbuf[6] == rfcomm_dcid[0] && l2capinbuf[7] == rfcomm_dcid[1]) { // RFCOMM
  224. rfcommChannel = l2capinbuf[8] & 0xF8;
  225. rfcommDirection = l2capinbuf[8] & 0x04;
  226. rfcommCommandResponse = l2capinbuf[8] & 0x02;
  227. rfcommChannelType = l2capinbuf[9] & 0xEF;
  228. rfcommPfBit = l2capinbuf[9] & 0x10;
  229. if(rfcommChannel >> 3 != 0x00)
  230. rfcommChannelConnection = rfcommChannel;
  231. #ifdef EXTRADEBUG
  232. Notify(PSTR("\r\nRFCOMM Channel: "), 0x80);
  233. D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
  234. Notify(PSTR(" Direction: "), 0x80);
  235. D_PrintHex<uint8_t > (rfcommDirection >> 2, 0x80);
  236. Notify(PSTR(" CommandResponse: "), 0x80);
  237. D_PrintHex<uint8_t > (rfcommCommandResponse >> 1, 0x80);
  238. Notify(PSTR(" ChannelType: "), 0x80);
  239. D_PrintHex<uint8_t > (rfcommChannelType, 0x80);
  240. Notify(PSTR(" PF_BIT: "), 0x80);
  241. D_PrintHex<uint8_t > (rfcommPfBit, 0x80);
  242. #endif
  243. if(rfcommChannelType == RFCOMM_DISC) {
  244. #ifdef DEBUG_USB_HOST
  245. Notify(PSTR("\r\nReceived Disconnect RFCOMM Command on channel: "), 0x80);
  246. D_PrintHex<uint8_t > (rfcommChannel >> 3, 0x80);
  247. #endif
  248. connected = false;
  249. sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
  250. }
  251. if(connected) {
  252. /* Read the incoming message */
  253. if(rfcommChannelType == RFCOMM_UIH && rfcommChannel == rfcommChannelConnection) {
  254. uint8_t length = l2capinbuf[10] >> 1; // Get length
  255. uint8_t offset = l2capinbuf[4] - length - 4; // Check if there is credit
  256. if(checkFcs(&l2capinbuf[8], l2capinbuf[11 + length + offset])) {
  257. uint8_t i = 0;
  258. for(; i < length; i++) {
  259. if(rfcommAvailable + i >= sizeof (rfcommDataBuffer)) {
  260. #ifdef DEBUG_USB_HOST
  261. Notify(PSTR("\r\nWarning: Buffer is full!"), 0x80);
  262. #endif
  263. break;
  264. }
  265. rfcommDataBuffer[rfcommAvailable + i] = l2capinbuf[11 + i + offset];
  266. }
  267. rfcommAvailable += i;
  268. #ifdef EXTRADEBUG
  269. Notify(PSTR("\r\nRFCOMM Data Available: "), 0x80);
  270. Notify(rfcommAvailable, 0x80);
  271. if(offset) {
  272. Notify(PSTR(" - Credit: 0x"), 0x80);
  273. D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);
  274. }
  275. #endif
  276. }
  277. #ifdef DEBUG_USB_HOST
  278. else
  279. Notify(PSTR("\r\nError in FCS checksum!"), 0x80);
  280. #endif
  281. #ifdef PRINTREPORT // Uncomment "#define PRINTREPORT" to print the report send to the Arduino via Bluetooth
  282. for(uint8_t i = 0; i < length; i++)
  283. Notifyc(l2capinbuf[i + 11 + offset], 0x80);
  284. #endif
  285. } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
  286. #ifdef DEBUG_USB_HOST
  287. Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
  288. #endif
  289. rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command
  290. rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
  291. rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
  292. rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
  293. rfcommbuf[4] = l2capinbuf[15]; // Priority
  294. rfcommbuf[5] = l2capinbuf[16]; // Timer
  295. rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB
  296. rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB
  297. rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
  298. rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
  299. sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response
  300. } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
  301. #ifdef DEBUG_USB_HOST
  302. Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
  303. #endif
  304. rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response
  305. rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
  306. rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
  307. rfcommbuf[3] = l2capinbuf[14];
  308. sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
  309. }
  310. } else {
  311. if(rfcommChannelType == RFCOMM_SABM) { // SABM Command - this is sent twice: once for channel 0 and then for the channel to establish
  312. #ifdef DEBUG_USB_HOST
  313. Notify(PSTR("\r\nReceived SABM Command"), 0x80);
  314. #endif
  315. sendRfcomm(rfcommChannel, rfcommDirection, rfcommCommandResponse, RFCOMM_UA, rfcommPfBit, rfcommbuf, 0x00); // UA Command
  316. } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_PN_CMD) { // UIH Parameter Negotiation Command
  317. #ifdef DEBUG_USB_HOST
  318. Notify(PSTR("\r\nReceived UIH Parameter Negotiation Command"), 0x80);
  319. #endif
  320. rfcommbuf[0] = BT_RFCOMM_PN_RSP; // UIH Parameter Negotiation Response
  321. rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
  322. rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
  323. rfcommbuf[3] = 0xE0; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
  324. rfcommbuf[4] = 0x00; // Priority
  325. rfcommbuf[5] = 0x00; // Timer
  326. rfcommbuf[6] = BULK_MAXPKTSIZE - 14; // Max Fram Size LSB - set to the size of received data (50)
  327. rfcommbuf[7] = 0x00; // Max Fram Size MSB
  328. rfcommbuf[8] = 0x00; // MaxRatransm.
  329. rfcommbuf[9] = 0x00; // Number of Frames
  330. sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A);
  331. } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_CMD) { // UIH Modem Status Command
  332. #ifdef DEBUG_USB_HOST
  333. Notify(PSTR("\r\nSend UIH Modem Status Response"), 0x80);
  334. #endif
  335. rfcommbuf[0] = BT_RFCOMM_MSC_RSP; // UIH Modem Status Response
  336. rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
  337. rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
  338. rfcommbuf[3] = l2capinbuf[14];
  339. sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
  340. delay(1);
  341. #ifdef DEBUG_USB_HOST
  342. Notify(PSTR("\r\nSend UIH Modem Status Command"), 0x80);
  343. #endif
  344. rfcommbuf[0] = BT_RFCOMM_MSC_CMD; // UIH Modem Status Command
  345. rfcommbuf[1] = 2 << 1 | 1; // Length and shiftet like so: length << 1 | 1
  346. rfcommbuf[2] = l2capinbuf[13]; // Channel: (1 << 0) | (1 << 1) | (0 << 2) | (channel << 3)
  347. rfcommbuf[3] = 0x8D; // Can receive frames (YES), Ready to Communicate (YES), Ready to Receive (YES), Incomig Call (NO), Data is Value (YES)
  348. sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x04);
  349. } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_MSC_RSP) { // UIH Modem Status Response
  350. if(!creditSent) {
  351. #ifdef DEBUG_USB_HOST
  352. Notify(PSTR("\r\nSend UIH Command with credit"), 0x80);
  353. #endif
  354. sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send credit
  355. creditSent = true;
  356. timer = millis();
  357. waitForLastCommand = true;
  358. }
  359. } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[10] == 0x01) { // UIH Command with credit
  360. #ifdef DEBUG_USB_HOST
  361. Notify(PSTR("\r\nReceived UIH Command with credit"), 0x80);
  362. #endif
  363. } else if(rfcommChannelType == RFCOMM_UIH && l2capinbuf[11] == BT_RFCOMM_RPN_CMD) { // UIH Remote Port Negotiation Command
  364. #ifdef DEBUG_USB_HOST
  365. Notify(PSTR("\r\nReceived UIH Remote Port Negotiation Command"), 0x80);
  366. #endif
  367. rfcommbuf[0] = BT_RFCOMM_RPN_RSP; // Command
  368. rfcommbuf[1] = l2capinbuf[12]; // Length and shiftet like so: length << 1 | 1
  369. rfcommbuf[2] = l2capinbuf[13]; // Channel: channel << 1 | 1
  370. rfcommbuf[3] = l2capinbuf[14]; // Pre difined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
  371. rfcommbuf[4] = l2capinbuf[15]; // Priority
  372. rfcommbuf[5] = l2capinbuf[16]; // Timer
  373. rfcommbuf[6] = l2capinbuf[17]; // Max Fram Size LSB
  374. rfcommbuf[7] = l2capinbuf[18]; // Max Fram Size MSB
  375. rfcommbuf[8] = l2capinbuf[19]; // MaxRatransm.
  376. rfcommbuf[9] = l2capinbuf[20]; // Number of Frames
  377. sendRfcomm(rfcommChannel, rfcommDirection, 0, RFCOMM_UIH, rfcommPfBit, rfcommbuf, 0x0A); // UIH Remote Port Negotiation Response
  378. #ifdef DEBUG_USB_HOST
  379. Notify(PSTR("\r\nRFCOMM Connection is now established\r\n"), 0x80);
  380. #endif
  381. onInit();
  382. }
  383. #ifdef EXTRADEBUG
  384. else if(rfcommChannelType != RFCOMM_DISC) {
  385. Notify(PSTR("\r\nUnsupported RFCOMM Data - ChannelType: "), 0x80);
  386. D_PrintHex<uint8_t > (rfcommChannelType, 0x80);
  387. Notify(PSTR(" Command: "), 0x80);
  388. D_PrintHex<uint8_t > (l2capinbuf[11], 0x80);
  389. }
  390. #endif
  391. }
  392. }
  393. #ifdef EXTRADEBUG
  394. else {
  395. Notify(PSTR("\r\nUnsupported L2CAP Data - Channel ID: "), 0x80);
  396. D_PrintHex<uint8_t > (l2capinbuf[7], 0x80);
  397. Notify(PSTR(" "), 0x80);
  398. D_PrintHex<uint8_t > (l2capinbuf[6], 0x80);
  399. }
  400. #endif
  401. SDP_task();
  402. RFCOMM_task();
  403. }
  404. }
  405. void SPP::Run() {
  406. 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
  407. #ifdef DEBUG_USB_HOST
  408. Notify(PSTR("\r\nRFCOMM Connection is now established - Automatic\r\n"), 0x80);
  409. #endif
  410. onInit();
  411. }
  412. send(); // Send all bytes currently in the buffer
  413. }
  414. void SPP::onInit() {
  415. creditSent = false;
  416. waitForLastCommand = false;
  417. connected = true; // The RFCOMM channel is now established
  418. sppIndex = 0;
  419. if(pFuncOnInit)
  420. pFuncOnInit(); // Call the user function
  421. };
  422. void SPP::SDP_task() {
  423. switch(l2cap_sdp_state) {
  424. case L2CAP_SDP_WAIT:
  425. if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST)) {
  426. l2cap_clear_flag(L2CAP_FLAG_CONNECTION_SDP_REQUEST); // Clear flag
  427. #ifdef DEBUG_USB_HOST
  428. Notify(PSTR("\r\nSDP Incoming Connection Request"), 0x80);
  429. #endif
  430. pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, PENDING);
  431. delay(1);
  432. pBtd->l2cap_connection_response(hci_handle, identifier, sdp_dcid, sdp_scid, SUCCESSFUL);
  433. identifier++;
  434. delay(1);
  435. pBtd->l2cap_config_request(hci_handle, identifier, sdp_scid);
  436. l2cap_sdp_state = L2CAP_SDP_SUCCESS;
  437. } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST)) {
  438. l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_SDP_REQUEST); // Clear flag
  439. SDPConnected = false;
  440. #ifdef DEBUG_USB_HOST
  441. Notify(PSTR("\r\nDisconnected SDP Channel"), 0x80);
  442. #endif
  443. pBtd->l2cap_disconnection_response(hci_handle, identifier, sdp_dcid, sdp_scid);
  444. }
  445. break;
  446. case L2CAP_SDP_SUCCESS:
  447. if(l2cap_check_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS)) {
  448. l2cap_clear_flag(L2CAP_FLAG_CONFIG_SDP_SUCCESS); // Clear flag
  449. #ifdef DEBUG_USB_HOST
  450. Notify(PSTR("\r\nSDP Successfully Configured"), 0x80);
  451. #endif
  452. firstMessage = true; // Reset bool
  453. SDPConnected = true;
  454. l2cap_sdp_state = L2CAP_SDP_WAIT;
  455. }
  456. break;
  457. case L2CAP_DISCONNECT_RESPONSE: // This is for both disconnection response from the RFCOMM and SDP channel if they were connected
  458. if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RESPONSE)) {
  459. #ifdef DEBUG_USB_HOST
  460. Notify(PSTR("\r\nDisconnected L2CAP Connection"), 0x80);
  461. #endif
  462. pBtd->hci_disconnect(hci_handle);
  463. hci_handle = -1; // Reset handle
  464. Reset();
  465. }
  466. break;
  467. }
  468. }
  469. void SPP::RFCOMM_task() {
  470. switch(l2cap_rfcomm_state) {
  471. case L2CAP_RFCOMM_WAIT:
  472. if(l2cap_check_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST)) {
  473. l2cap_clear_flag(L2CAP_FLAG_CONNECTION_RFCOMM_REQUEST); // Clear flag
  474. #ifdef DEBUG_USB_HOST
  475. Notify(PSTR("\r\nRFCOMM Incoming Connection Request"), 0x80);
  476. #endif
  477. pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, PENDING);
  478. delay(1);
  479. pBtd->l2cap_connection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid, SUCCESSFUL);
  480. identifier++;
  481. delay(1);
  482. pBtd->l2cap_config_request(hci_handle, identifier, rfcomm_scid);
  483. l2cap_rfcomm_state = L2CAP_RFCOMM_SUCCESS;
  484. } else if(l2cap_check_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST)) {
  485. l2cap_clear_flag(L2CAP_FLAG_DISCONNECT_RFCOMM_REQUEST); // Clear flag
  486. RFCOMMConnected = false;
  487. connected = false;
  488. #ifdef DEBUG_USB_HOST
  489. Notify(PSTR("\r\nDisconnected RFCOMM Channel"), 0x80);
  490. #endif
  491. pBtd->l2cap_disconnection_response(hci_handle, identifier, rfcomm_dcid, rfcomm_scid);
  492. }
  493. break;
  494. case L2CAP_RFCOMM_SUCCESS:
  495. if(l2cap_check_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS)) {
  496. l2cap_clear_flag(L2CAP_FLAG_CONFIG_RFCOMM_SUCCESS); // Clear flag
  497. #ifdef DEBUG_USB_HOST
  498. Notify(PSTR("\r\nRFCOMM Successfully Configured"), 0x80);
  499. #endif
  500. rfcommAvailable = 0; // Reset number of bytes available
  501. bytesRead = 0; // Reset number of bytes received
  502. RFCOMMConnected = true;
  503. l2cap_rfcomm_state = L2CAP_RFCOMM_WAIT;
  504. }
  505. break;
  506. }
  507. }
  508. /************************************************************/
  509. /* SDP Commands */
  510. /************************************************************/
  511. void SPP::SDP_Command(uint8_t* data, uint8_t nbytes) { // See page 223 in the Bluetooth specs
  512. pBtd->L2CAP_Command(hci_handle, data, nbytes, sdp_scid[0], sdp_scid[1]);
  513. }
  514. void SPP::serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow) { // See page 235 in the Bluetooth specs
  515. l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;
  516. l2capoutbuf[1] = transactionIDHigh;
  517. l2capoutbuf[2] = transactionIDLow;
  518. l2capoutbuf[3] = 0x00; // MSB Parameter Length
  519. l2capoutbuf[4] = 0x05; // LSB Parameter Length = 5
  520. l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
  521. l2capoutbuf[6] = 0x02; // LSB AttributeListsByteCount = 2
  522. /* Attribute ID/Value Sequence: */
  523. l2capoutbuf[7] = 0x35; // Data element sequence - length in next byte
  524. l2capoutbuf[8] = 0x00; // Length = 0
  525. l2capoutbuf[9] = 0x00; // No continuation state
  526. SDP_Command(l2capoutbuf, 10);
  527. }
  528. void SPP::serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
  529. l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;
  530. l2capoutbuf[1] = transactionIDHigh;
  531. l2capoutbuf[2] = transactionIDLow;
  532. l2capoutbuf[3] = 0x00; // MSB Parameter Length
  533. l2capoutbuf[4] = 0x2B; // LSB Parameter Length = 43
  534. l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
  535. l2capoutbuf[6] = 0x26; // LSB AttributeListsByteCount = 38
  536. /* Attribute ID/Value Sequence: */
  537. l2capoutbuf[7] = 0x36; // Data element sequence - length in next two bytes
  538. l2capoutbuf[8] = 0x00; // MSB Length
  539. l2capoutbuf[9] = 0x3C; // LSB Length = 60
  540. l2capoutbuf[10] = 0x36; // Data element sequence - length in next two bytes
  541. l2capoutbuf[11] = 0x00; // MSB Length
  542. l2capoutbuf[12] = 0x39; // LSB Length = 57
  543. l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes
  544. l2capoutbuf[14] = 0x00; // MSB ServiceRecordHandle
  545. l2capoutbuf[15] = 0x00; // LSB ServiceRecordHandle
  546. l2capoutbuf[16] = 0x0A; // Unsigned int - length 4 bytes
  547. l2capoutbuf[17] = 0x00; // ServiceRecordHandle value - TODO: Is this related to HCI_Handle?
  548. l2capoutbuf[18] = 0x01;
  549. l2capoutbuf[19] = 0x00;
  550. l2capoutbuf[20] = 0x06;
  551. l2capoutbuf[21] = 0x09; // Unsigned Integer - length 2 bytes
  552. l2capoutbuf[22] = 0x00; // MSB ServiceClassIDList
  553. l2capoutbuf[23] = 0x01; // LSB ServiceClassIDList
  554. l2capoutbuf[24] = 0x35; // Data element sequence - length in next byte
  555. l2capoutbuf[25] = 0x03; // Length = 3
  556. l2capoutbuf[26] = 0x19; // UUID (universally unique identifier) - length = 2 bytes
  557. l2capoutbuf[27] = 0x11; // MSB SerialPort
  558. l2capoutbuf[28] = 0x01; // LSB SerialPort
  559. l2capoutbuf[29] = 0x09; // Unsigned Integer - length 2 bytes
  560. l2capoutbuf[30] = 0x00; // MSB ProtocolDescriptorList
  561. l2capoutbuf[31] = 0x04; // LSB ProtocolDescriptorList
  562. l2capoutbuf[32] = 0x35; // Data element sequence - length in next byte
  563. l2capoutbuf[33] = 0x0C; // Length = 12
  564. l2capoutbuf[34] = 0x35; // Data element sequence - length in next byte
  565. l2capoutbuf[35] = 0x03; // Length = 3
  566. l2capoutbuf[36] = 0x19; // UUID (universally unique identifier) - length = 2 bytes
  567. l2capoutbuf[37] = 0x01; // MSB L2CAP
  568. l2capoutbuf[38] = 0x00; // LSB L2CAP
  569. l2capoutbuf[39] = 0x35; // Data element sequence - length in next byte
  570. l2capoutbuf[40] = 0x05; // Length = 5
  571. l2capoutbuf[41] = 0x19; // UUID (universally unique identifier) - length = 2 bytes
  572. l2capoutbuf[42] = 0x00; // MSB RFCOMM
  573. l2capoutbuf[43] = 0x03; // LSB RFCOMM
  574. l2capoutbuf[44] = 0x08; // Unsigned Integer - length 1 byte
  575. l2capoutbuf[45] = 0x02; // ContinuationState - Two more bytes
  576. l2capoutbuf[46] = 0x00; // MSB length
  577. l2capoutbuf[47] = 0x19; // LSB length = 25 more bytes to come
  578. SDP_Command(l2capoutbuf, 48);
  579. }
  580. void SPP::serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
  581. l2capoutbuf[0] = SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU;
  582. l2capoutbuf[1] = transactionIDHigh;
  583. l2capoutbuf[2] = transactionIDLow;
  584. l2capoutbuf[3] = 0x00; // MSB Parameter Length
  585. l2capoutbuf[4] = 0x1C; // LSB Parameter Length = 28
  586. l2capoutbuf[5] = 0x00; // MSB AttributeListsByteCount
  587. l2capoutbuf[6] = 0x19; // LSB AttributeListsByteCount = 25
  588. /* Attribute ID/Value Sequence: */
  589. l2capoutbuf[7] = 0x01; // Channel 1 - TODO: Try different values, so multiple servers can be used at once
  590. l2capoutbuf[8] = 0x09; // Unsigned Integer - length 2 bytes
  591. l2capoutbuf[9] = 0x00; // MSB LanguageBaseAttributeIDList
  592. l2capoutbuf[10] = 0x06; // LSB LanguageBaseAttributeIDList
  593. l2capoutbuf[11] = 0x35; // Data element sequence - length in next byte
  594. l2capoutbuf[12] = 0x09; // Length = 9
  595. // Identifier representing the natural language = en = English - see: "ISO 639:1988"
  596. l2capoutbuf[13] = 0x09; // Unsigned Integer - length 2 bytes
  597. l2capoutbuf[14] = 0x65; // 'e'
  598. l2capoutbuf[15] = 0x6E; // 'n'
  599. // "The second element of each triplet contains an identifier that specifies a character encoding used for the language"
  600. // Encoding is set to 106 (UTF-8) - see: http://www.iana.org/assignments/character-sets/character-sets.xhtml
  601. l2capoutbuf[16] = 0x09; // Unsigned Integer - length 2 bytes
  602. l2capoutbuf[17] = 0x00; // MSB of character encoding
  603. l2capoutbuf[18] = 0x6A; // LSB of character encoding (106)
  604. // Attribute ID that serves as the base attribute ID for the natural language in the service record
  605. // "To facilitate the retrieval of human-readable universal attributes in a principal language, the base attribute ID value for the primary language supported by a service record shall be 0x0100"
  606. l2capoutbuf[19] = 0x09; // Unsigned Integer - length 2 bytes
  607. l2capoutbuf[20] = 0x01;
  608. l2capoutbuf[21] = 0x00;
  609. l2capoutbuf[22] = 0x09; // Unsigned Integer - length 2 bytes
  610. l2capoutbuf[23] = 0x01; // MSB ServiceDescription
  611. l2capoutbuf[24] = 0x00; // LSB ServiceDescription
  612. l2capoutbuf[25] = 0x25; // Text string - length in next byte
  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 continuation state
  620. SDP_Command(l2capoutbuf, 33);
  621. }
  622. void SPP::l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
  623. serialPortResponse1(transactionIDHigh, transactionIDLow); // These has to send all the supported functions, since it only supports virtual serialport it just sends the message again
  624. }
  625. void SPP::l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow) {
  626. serialPortResponse2(transactionIDHigh, transactionIDLow); // Same data as serialPortResponse2
  627. }
  628. /************************************************************/
  629. /* RFCOMM Commands */
  630. /************************************************************/
  631. void SPP::RFCOMM_Command(uint8_t* data, uint8_t nbytes) {
  632. pBtd->L2CAP_Command(hci_handle, data, nbytes, rfcomm_scid[0], rfcomm_scid[1]);
  633. }
  634. void SPP::sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t* data, uint8_t length) {
  635. l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
  636. l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
  637. l2capoutbuf[2] = length << 1 | 0x01; // Length and format (always 0x01 bytes format)
  638. uint8_t i = 0;
  639. for(; i < length; i++)
  640. l2capoutbuf[i + 3] = data[i];
  641. l2capoutbuf[i + 3] = calcFcs(l2capoutbuf);
  642. #ifdef EXTRADEBUG
  643. Notify(PSTR(" - RFCOMM Data: "), 0x80);
  644. for(i = 0; i < length + 4; i++) {
  645. D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
  646. Notify(PSTR(" "), 0x80);
  647. }
  648. #endif
  649. RFCOMM_Command(l2capoutbuf, length + 4);
  650. }
  651. void SPP::sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit) {
  652. l2capoutbuf[0] = channel | direction | CR | extendAddress; // RFCOMM Address
  653. l2capoutbuf[1] = channelType | pfBit; // RFCOMM Control
  654. l2capoutbuf[2] = 0x01; // Length = 0
  655. l2capoutbuf[3] = credit; // Credit
  656. l2capoutbuf[4] = calcFcs(l2capoutbuf);
  657. #ifdef EXTRADEBUG
  658. Notify(PSTR(" - RFCOMM Credit Data: "), 0x80);
  659. for(uint8_t i = 0; i < 5; i++) {
  660. D_PrintHex<uint8_t > (l2capoutbuf[i], 0x80);
  661. Notify(PSTR(" "), 0x80);
  662. }
  663. #endif
  664. RFCOMM_Command(l2capoutbuf, 5);
  665. }
  666. /* CRC on 2 bytes */
  667. uint8_t SPP::crc(uint8_t *data) {
  668. return (pgm_read_byte(&rfcomm_crc_table[pgm_read_byte(&rfcomm_crc_table[0xFF ^ data[0]]) ^ data[1]]));
  669. }
  670. /* Calculate FCS */
  671. uint8_t SPP::calcFcs(uint8_t *data) {
  672. uint8_t temp = crc(data);
  673. if((data[1] & 0xEF) == RFCOMM_UIH)
  674. return (0xFF - temp); // FCS on 2 bytes
  675. else
  676. return (0xFF - pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]])); // FCS on 3 bytes
  677. }
  678. /* Check FCS */
  679. bool SPP::checkFcs(uint8_t *data, uint8_t fcs) {
  680. uint8_t temp = crc(data);
  681. if((data[1] & 0xEF) != RFCOMM_UIH)
  682. temp = pgm_read_byte(&rfcomm_crc_table[temp ^ data[2]]); // FCS on 3 bytes
  683. return (pgm_read_byte(&rfcomm_crc_table[temp ^ fcs]) == 0xCF);
  684. }
  685. /* Serial commands */
  686. #if defined(ARDUINO) && ARDUINO >=100
  687. size_t SPP::write(uint8_t data) {
  688. return write(&data, 1);
  689. }
  690. #else
  691. void SPP::write(uint8_t data) {
  692. write(&data, 1);
  693. }
  694. #endif
  695. #if defined(ARDUINO) && ARDUINO >=100
  696. size_t SPP::write(const uint8_t *data, size_t size) {
  697. #else
  698. void SPP::write(const uint8_t *data, size_t size) {
  699. #endif
  700. for(uint8_t i = 0; i < size; i++) {
  701. if(sppIndex >= sizeof (sppOutputBuffer) / sizeof (sppOutputBuffer[0]))
  702. send(); // Send the current data in the buffer
  703. sppOutputBuffer[sppIndex++] = data[i]; // All the bytes are put into a buffer and then send using the send() function
  704. }
  705. #if defined(ARDUINO) && ARDUINO >=100
  706. return size;
  707. #endif
  708. }
  709. void SPP::send() {
  710. if(!connected || !sppIndex)
  711. return;
  712. uint8_t length; // This is the length of the string we are sending
  713. uint8_t offset = 0; // This is used to keep track of where we are in the string
  714. l2capoutbuf[0] = rfcommChannelConnection | 0 | 0 | extendAddress; // RFCOMM Address
  715. l2capoutbuf[1] = RFCOMM_UIH; // RFCOMM Control
  716. while(sppIndex) { // We will run this while loop until this variable is 0
  717. if(sppIndex > (sizeof (l2capoutbuf) - 4)) // Check if the string is larger than the outgoing buffer
  718. length = sizeof (l2capoutbuf) - 4;
  719. else
  720. length = sppIndex;
  721. l2capoutbuf[2] = length << 1 | 1; // Length
  722. uint8_t i = 0;
  723. for(; i < length; i++)
  724. l2capoutbuf[i + 3] = sppOutputBuffer[i + offset];
  725. l2capoutbuf[i + 3] = calcFcs(l2capoutbuf); // Calculate checksum
  726. RFCOMM_Command(l2capoutbuf, length + 4);
  727. sppIndex -= length;
  728. offset += length; // Increment the offset
  729. }
  730. }
  731. int SPP::available(void) {
  732. return rfcommAvailable;
  733. };
  734. void SPP::discard(void) {
  735. rfcommAvailable = 0;
  736. }
  737. int SPP::peek(void) {
  738. if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer
  739. return -1;
  740. return rfcommDataBuffer[0];
  741. }
  742. int SPP::read(void) {
  743. if(rfcommAvailable == 0) // Don't read if there is nothing in the buffer
  744. return -1;
  745. uint8_t output = rfcommDataBuffer[0];
  746. for(uint8_t i = 1; i < rfcommAvailable; i++)
  747. rfcommDataBuffer[i - 1] = rfcommDataBuffer[i]; // Shift the buffer one left
  748. rfcommAvailable--;
  749. bytesRead++;
  750. if(bytesRead > (sizeof (rfcommDataBuffer) - 5)) { // We will send the command just before it runs out of credit
  751. bytesRead = 0;
  752. sendRfcommCredit(rfcommChannelConnection, rfcommDirection, 0, RFCOMM_UIH, 0x10, sizeof (rfcommDataBuffer)); // Send more credit
  753. #ifdef EXTRADEBUG
  754. Notify(PSTR("\r\nSent "), 0x80);
  755. Notify((uint8_t)sizeof (rfcommDataBuffer), 0x80);
  756. Notify(PSTR(" more credit"), 0x80);
  757. #endif
  758. }
  759. return output;
  760. }