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.

225 lines
8.2 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. #ifndef _spp_h_
  15. #define _spp_h_
  16. #include "BTD.h"
  17. /* Used for SDP */
  18. #define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU 0x06 // See the RFCOMM specs
  19. #define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU 0x07 // See the RFCOMM specs
  20. #define SERIALPORT_UUID 0x1101 // See http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm
  21. #define L2CAP_UUID 0x0100
  22. /* Used for RFCOMM */
  23. #define RFCOMM_SABM 0x2F
  24. #define RFCOMM_UA 0x63
  25. #define RFCOMM_UIH 0xEF
  26. //#define RFCOMM_DM 0x0F
  27. #define RFCOMM_DISC 0x43
  28. #define extendAddress 0x01 // Always 1
  29. // Multiplexer message types
  30. #define BT_RFCOMM_PN_CMD 0x83
  31. #define BT_RFCOMM_PN_RSP 0x81
  32. #define BT_RFCOMM_MSC_CMD 0xE3
  33. #define BT_RFCOMM_MSC_RSP 0xE1
  34. #define BT_RFCOMM_RPN_CMD 0x93
  35. #define BT_RFCOMM_RPN_RSP 0x91
  36. /*
  37. #define BT_RFCOMM_TEST_CMD 0x23
  38. #define BT_RFCOMM_TEST_RSP 0x21
  39. #define BT_RFCOMM_FCON_CMD 0xA3
  40. #define BT_RFCOMM_FCON_RSP 0xA1
  41. #define BT_RFCOMM_FCOFF_CMD 0x63
  42. #define BT_RFCOMM_FCOFF_RSP 0x61
  43. #define BT_RFCOMM_RLS_CMD 0x53
  44. #define BT_RFCOMM_RLS_RSP 0x51
  45. #define BT_RFCOMM_NSC_RSP 0x11
  46. */
  47. /**
  48. * This BluetoothService class implements the Serial Port Protocol (SPP).
  49. * It inherits the Arduino Stream class. This allows it to use all the standard Arduino print and stream functions.
  50. */
  51. class SPP : public BluetoothService, public Stream {
  52. public:
  53. /**
  54. * Constructor for the SPP class.
  55. * @param p Pointer to BTD class instance.
  56. * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used.
  57. * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
  58. */
  59. SPP(BTD *p, const char *name = "Arduino", const char *pin = "0000");
  60. /** @name BluetoothService implementation */
  61. /** Used this to disconnect the virtual serial port. */
  62. void disconnect();
  63. /**@}*/
  64. /**
  65. * Used to provide Boolean tests for the class.
  66. * @return Return true if SPP communication is connected.
  67. */
  68. operator bool() {
  69. return connected;
  70. }
  71. /** Variable used to indicate if the connection is established. */
  72. bool connected;
  73. /** @name Serial port profile (SPP) Print functions */
  74. /**
  75. * Get number of bytes waiting to be read.
  76. * @return Return the number of bytes ready to be read.
  77. */
  78. int available(void);
  79. /** Send out all bytes in the buffer. */
  80. void flush(void) {
  81. send();
  82. };
  83. /**
  84. * Used to read the next value in the buffer without advancing to the next one.
  85. * @return Return the byte. Will return -1 if no bytes are available.
  86. */
  87. int peek(void);
  88. /**
  89. * Used to read the buffer.
  90. * @return Return the byte. Will return -1 if no bytes are available.
  91. */
  92. int read(void);
  93. #if defined(ARDUINO) && ARDUINO >=100
  94. /**
  95. * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
  96. * @param data The byte to write.
  97. * @return Return the number of bytes written.
  98. */
  99. size_t write(uint8_t data);
  100. /**
  101. * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
  102. * @param data The data array to send.
  103. * @param size Size of the data.
  104. * @return Return the number of bytes written.
  105. */
  106. size_t write(const uint8_t* data, size_t size);
  107. /** Pull in write(const char *str) from Print */
  108. using Print::write;
  109. #else
  110. /**
  111. * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
  112. * @param data The byte to write.
  113. */
  114. void write(uint8_t data);
  115. /**
  116. * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
  117. * @param data The data array to send.
  118. * @param size Size of the data.
  119. */
  120. void write(const uint8_t* data, size_t size);
  121. #endif
  122. /** Discard all the bytes in the buffer. */
  123. void discard(void);
  124. /**
  125. * This will send all the bytes in the buffer.
  126. * This is called whenever Usb.Task() is called,
  127. * but can also be called via this function.
  128. */
  129. void send(void);
  130. /**@}*/
  131. protected:
  132. /** @name BluetoothService implementation */
  133. /**
  134. * Used to pass acldata to the services.
  135. * @param ACLData Incoming acldata.
  136. */
  137. void ACLData(uint8_t* ACLData);
  138. /** Used to establish the connection automatically. */
  139. void Run();
  140. /** Use this to reset the service. */
  141. void Reset();
  142. /**
  143. * Called when a device is successfully initialized.
  144. * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
  145. * This is useful for instance if you want to set the LEDs in a specific way.
  146. */
  147. void onInit();
  148. /**@}*/
  149. private:
  150. /* Set true when a channel is created */
  151. bool SDPConnected;
  152. bool RFCOMMConnected;
  153. /* Variables used by L2CAP state machines */
  154. uint8_t l2cap_sdp_state;
  155. uint8_t l2cap_rfcomm_state;
  156. uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
  157. uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
  158. /* L2CAP Channels */
  159. uint8_t sdp_scid[2]; // L2CAP source CID for SDP
  160. uint8_t sdp_dcid[2]; // 0x0050
  161. uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM
  162. uint8_t rfcomm_dcid[2]; // 0x0051
  163. /* RFCOMM Variables */
  164. uint8_t rfcommChannel;
  165. uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at
  166. uint8_t rfcommDirection;
  167. uint8_t rfcommCommandResponse;
  168. uint8_t rfcommChannelType;
  169. uint8_t rfcommPfBit;
  170. uint32_t timer;
  171. bool waitForLastCommand;
  172. bool creditSent;
  173. uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
  174. uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data
  175. uint8_t sppIndex;
  176. uint8_t rfcommAvailable;
  177. bool firstMessage; // Used to see if it's the first SDP request received
  178. uint8_t bytesRead; // Counter to see when it's time to send more credit
  179. /* State machines */
  180. void SDP_task(); // SDP state machine
  181. void RFCOMM_task(); // RFCOMM state machine
  182. /* SDP Commands */
  183. void SDP_Command(uint8_t *data, uint8_t nbytes);
  184. void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
  185. void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
  186. void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
  187. void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
  188. void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
  189. /* RFCOMM Commands */
  190. void RFCOMM_Command(uint8_t *data, uint8_t nbytes);
  191. void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t *data, uint8_t length);
  192. void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit);
  193. uint8_t calcFcs(uint8_t *data);
  194. bool checkFcs(uint8_t *data, uint8_t fcs);
  195. uint8_t crc(uint8_t *data);
  196. };
  197. #endif