1 /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
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
13 Kristian Lauszus, TKJ Electronics
14 Web : http://www.tkjelectronics.com
15 e-mail : kristianl@tkjelectronics.com
24 #define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU 0x06 // See the RFCOMM specs
25 #define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU 0x07 // See the RFCOMM specs
26 #define SERIALPORT_UUID 0x1101 // See http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm
27 #define L2CAP_UUID 0x0100
30 #define RFCOMM_SABM 0x2F
31 #define RFCOMM_UA 0x63
32 #define RFCOMM_UIH 0xEF
33 //#define RFCOMM_DM 0x0F
34 #define RFCOMM_DISC 0x43
36 #define extendAddress 0x01 // Always 1
38 // Multiplexer message types
39 #define BT_RFCOMM_PN_CMD 0x83
40 #define BT_RFCOMM_PN_RSP 0x81
41 #define BT_RFCOMM_MSC_CMD 0xE3
42 #define BT_RFCOMM_MSC_RSP 0xE1
43 #define BT_RFCOMM_RPN_CMD 0x93
44 #define BT_RFCOMM_RPN_RSP 0x91
46 #define BT_RFCOMM_TEST_CMD 0x23
47 #define BT_RFCOMM_TEST_RSP 0x21
48 #define BT_RFCOMM_FCON_CMD 0xA3
49 #define BT_RFCOMM_FCON_RSP 0xA1
50 #define BT_RFCOMM_FCOFF_CMD 0x63
51 #define BT_RFCOMM_FCOFF_RSP 0x61
52 #define BT_RFCOMM_RLS_CMD 0x53
53 #define BT_RFCOMM_RLS_RSP 0x51
54 #define BT_RFCOMM_NSC_RSP 0x11
58 * This BluetoothService class implements the Serial Port Protocol (SPP).
59 * It inherits the Arduino Stream class. This allows it to use all the standard Arduino print and stream functions.
61 class SPP : public BluetoothService, public Stream {
64 * Constructor for the SPP class.
65 * @param p Pointer to BTD class instance.
66 * @param name Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used.
67 * @param pin Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
69 SPP(BTD *p, const char *name = "Arduino", const char *pin = "0000");
71 /** @name BluetoothService implementation */
72 /** Used this to disconnect the virtual serial port. */
77 * Used to provide Boolean tests for the class.
78 * @return Return true if SPP communication is connected.
83 /** Variable used to indicate if the connection is established. */
86 /** @name Serial port profile (SPP) Print functions */
88 * Get number of bytes waiting to be read.
89 * @return Return the number of bytes ready to be read.
93 /** Send out all bytes in the buffer. */
98 * Used to read the next value in the buffer without advancing to the next one.
99 * @return Return the byte. Will return -1 if no bytes are available.
103 * Used to read the buffer.
104 * @return Return the byte. Will return -1 if no bytes are available.
108 #if defined(ARDUINO) && ARDUINO >=100
110 * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
111 * @param data The byte to write.
112 * @return Return the number of bytes written.
114 size_t write(uint8_t data);
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 * @return Return the number of bytes written.
121 size_t write(const uint8_t* data, size_t size);
122 /** Pull in write(const char *str) from Print */
126 * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
127 * @param data The byte to write.
129 void write(uint8_t data);
131 * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
132 * @param data The data array to send.
133 * @param size Size of the data.
135 void write(const uint8_t* data, size_t size);
138 /** Discard all the bytes in the buffer. */
141 * This will send all the bytes in the buffer.
142 * This is called whenever Usb.Task() is called,
143 * but can also be called via this function.
149 /** @name BluetoothService implementation */
151 * Used to pass acldata to the services.
152 * @param ACLData Incoming acldata.
154 void ACLData(uint8_t* ACLData);
155 /** Used to establish the connection automatically. */
157 /** Use this to reset the service. */
160 * Called when a device is successfully initialized.
161 * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
162 * This is useful for instance if you want to set the LEDs in a specific way.
168 /* Set true when a channel is created */
170 bool RFCOMMConnected;
172 /* Variables used by L2CAP state machines */
173 uint8_t l2cap_sdp_state;
174 uint8_t l2cap_rfcomm_state;
176 uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
177 uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
180 uint8_t sdp_scid[2]; // L2CAP source CID for SDP
181 uint8_t sdp_dcid[2]; // 0x0050
182 uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM
183 uint8_t rfcomm_dcid[2]; // 0x0051
185 /* RFCOMM Variables */
186 uint8_t rfcommChannel;
187 uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at
188 uint8_t rfcommDirection;
189 uint8_t rfcommCommandResponse;
190 uint8_t rfcommChannelType;
194 bool waitForLastCommand;
197 uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
198 uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data
200 uint8_t rfcommAvailable;
202 bool firstMessage; // Used to see if it's the first SDP request received
203 uint8_t bytesRead; // Counter to see when it's time to send more credit
206 void SDP_task(); // SDP state machine
207 void RFCOMM_task(); // RFCOMM state machine
210 void SDP_Command(uint8_t *data, uint8_t nbytes);
211 void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
212 void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
213 void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
214 void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
215 void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
217 /* RFCOMM Commands */
218 void RFCOMM_Command(uint8_t *data, uint8_t nbytes);
219 void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t *data, uint8_t length);
220 void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit);
221 uint8_t calcFcs(uint8_t *data);
222 bool checkFcs(uint8_t *data, uint8_t fcs);
223 uint8_t crc(uint8_t *data);