225 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (C) 2012 Kristian Lauszus, TKJ Electronics. All rights reserved.
 | |
| 
 | |
|  This software may be distributed and modified under the terms of the GNU
 | |
|  General Public License version 2 (GPL2) as published by the Free Software
 | |
|  Foundation and appearing in the file GPL2.TXT included in the packaging of
 | |
|  this file. Please note that GPL2 Section 2[b] requires that all works based
 | |
|  on this software must also be made publicly available under the terms of
 | |
|  the GPL2 ("Copyleft").
 | |
| 
 | |
|  Contact information
 | |
|  -------------------
 | |
| 
 | |
|  Kristian Lauszus, TKJ Electronics
 | |
|  Web      :  http://www.tkjelectronics.com
 | |
|  e-mail   :  kristianl@tkjelectronics.com
 | |
|  */
 | |
| 
 | |
| #ifndef _spp_h_
 | |
| #define _spp_h_
 | |
| 
 | |
| #include "BTD.h"
 | |
| 
 | |
| /* Used for SDP */
 | |
| #define SDP_SERVICE_SEARCH_ATTRIBUTE_REQUEST_PDU    0x06 // See the RFCOMM specs
 | |
| #define SDP_SERVICE_SEARCH_ATTRIBUTE_RESPONSE_PDU   0x07 // See the RFCOMM specs
 | |
| #define SERIALPORT_UUID     0x1101 // See http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm
 | |
| #define L2CAP_UUID          0x0100
 | |
| 
 | |
| /* Used for RFCOMM */
 | |
| #define RFCOMM_SABM     0x2F
 | |
| #define RFCOMM_UA       0x63
 | |
| #define RFCOMM_UIH      0xEF
 | |
| //#define RFCOMM_DM       0x0F
 | |
| #define RFCOMM_DISC     0x43
 | |
| 
 | |
| #define extendAddress   0x01 // Always 1
 | |
| 
 | |
| // Multiplexer message types
 | |
| #define BT_RFCOMM_PN_CMD     0x83
 | |
| #define BT_RFCOMM_PN_RSP     0x81
 | |
| #define BT_RFCOMM_MSC_CMD    0xE3
 | |
| #define BT_RFCOMM_MSC_RSP    0xE1
 | |
| #define BT_RFCOMM_RPN_CMD    0x93
 | |
| #define BT_RFCOMM_RPN_RSP    0x91
 | |
| /*
 | |
| #define BT_RFCOMM_TEST_CMD   0x23
 | |
| #define BT_RFCOMM_TEST_RSP   0x21
 | |
| #define BT_RFCOMM_FCON_CMD   0xA3
 | |
| #define BT_RFCOMM_FCON_RSP   0xA1
 | |
| #define BT_RFCOMM_FCOFF_CMD  0x63
 | |
| #define BT_RFCOMM_FCOFF_RSP  0x61
 | |
| #define BT_RFCOMM_RLS_CMD    0x53
 | |
| #define BT_RFCOMM_RLS_RSP    0x51
 | |
| #define BT_RFCOMM_NSC_RSP    0x11
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * This BluetoothService class implements the Serial Port Protocol (SPP).
 | |
|  * It inherits the Arduino Stream class. This allows it to use all the standard Arduino print and stream functions.
 | |
|  */
 | |
| class SPP : public BluetoothService, public Stream {
 | |
| public:
 | |
|         /**
 | |
|          * Constructor for the SPP class.
 | |
|          * @param  p   Pointer to BTD class instance.
 | |
|          * @param  name   Set the name to BTD#btdName. If argument is omitted, then "Arduino" will be used.
 | |
|          * @param  pin   Write the pin to BTD#btdPin. If argument is omitted, then "0000" will be used.
 | |
|          */
 | |
|         SPP(BTD *p, const char *name = "Arduino", const char *pin = "0000");
 | |
| 
 | |
|         /** @name BluetoothService implementation */
 | |
|         /** Used this to disconnect the virtual serial port. */
 | |
|         void disconnect();
 | |
|         /**@}*/
 | |
| 
 | |
|         /**
 | |
|          * Used to provide Boolean tests for the class.
 | |
|          * @return Return true if SPP communication is connected.
 | |
|          */
 | |
|         operator bool() {
 | |
|                 return connected;
 | |
|         }
 | |
|         /** Variable used to indicate if the connection is established. */
 | |
|         bool connected;
 | |
| 
 | |
|         /** @name Serial port profile (SPP) Print functions */
 | |
|         /**
 | |
|          * Get number of bytes waiting to be read.
 | |
|          * @return Return the number of bytes ready to be read.
 | |
|          */
 | |
|         int available(void);
 | |
| 
 | |
|         /** Send out all bytes in the buffer. */
 | |
|         void flush(void) {
 | |
|                 send();
 | |
|         };
 | |
|         /**
 | |
|          * Used to read the next value in the buffer without advancing to the next one.
 | |
|          * @return Return the byte. Will return -1 if no bytes are available.
 | |
|          */
 | |
|         int peek(void);
 | |
|         /**
 | |
|          * Used to read the buffer.
 | |
|          * @return Return the byte. Will return -1 if no bytes are available.
 | |
|          */
 | |
|         int read(void);
 | |
| 
 | |
| #if defined(ARDUINO) && ARDUINO >=100
 | |
|         /**
 | |
|          * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
 | |
|          * @param  data The byte to write.
 | |
|          * @return      Return the number of bytes written.
 | |
|          */
 | |
|         size_t write(uint8_t data);
 | |
|         /**
 | |
|          * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
 | |
|          * @param  data The data array to send.
 | |
|          * @param  size Size of the data.
 | |
|          * @return      Return the number of bytes written.
 | |
|          */
 | |
|         size_t write(const uint8_t* data, size_t size);
 | |
|         /** Pull in write(const char *str) from Print */
 | |
|         using Print::write;
 | |
| #else
 | |
|         /**
 | |
|          * Writes the byte to send to a buffer. The message is send when either send() or after Usb.Task() is called.
 | |
|          * @param  data The byte to write.
 | |
|          */
 | |
|         void write(uint8_t data);
 | |
|         /**
 | |
|          * Writes the bytes to send to a buffer. The message is send when either send() or after Usb.Task() is called.
 | |
|          * @param data The data array to send.
 | |
|          * @param size Size of the data.
 | |
|          */
 | |
|         void write(const uint8_t* data, size_t size);
 | |
| #endif
 | |
| 
 | |
|         /** Discard all the bytes in the buffer. */
 | |
|         void discard(void);
 | |
|         /**
 | |
|          * This will send all the bytes in the buffer.
 | |
|          * This is called whenever Usb.Task() is called,
 | |
|          * but can also be called via this function.
 | |
|          */
 | |
|         void send(void);
 | |
|         /**@}*/
 | |
| 
 | |
| protected:
 | |
|         /** @name BluetoothService implementation */
 | |
|         /**
 | |
|          * Used to pass acldata to the services.
 | |
|          * @param ACLData Incoming acldata.
 | |
|          */
 | |
|         void ACLData(uint8_t* ACLData);
 | |
|         /** Used to establish the connection automatically. */
 | |
|         void Run();
 | |
|         /** Use this to reset the service. */
 | |
|         void Reset();
 | |
|         /**
 | |
|          * Called when a device is successfully initialized.
 | |
|          * Use attachOnInit(void (*funcOnInit)(void)) to call your own function.
 | |
|          * This is useful for instance if you want to set the LEDs in a specific way.
 | |
|          */
 | |
|         void onInit();
 | |
|         /**@}*/
 | |
| 
 | |
| private:
 | |
|         /* Set true when a channel is created */
 | |
|         bool SDPConnected;
 | |
|         bool RFCOMMConnected;
 | |
| 
 | |
|         /* Variables used by L2CAP state machines */
 | |
|         uint8_t l2cap_sdp_state;
 | |
|         uint8_t l2cap_rfcomm_state;
 | |
| 
 | |
|         uint8_t l2capoutbuf[BULK_MAXPKTSIZE]; // General purpose buffer for l2cap out data
 | |
|         uint8_t rfcommbuf[10]; // Buffer for RFCOMM Commands
 | |
| 
 | |
|         /* L2CAP Channels */
 | |
|         uint8_t sdp_scid[2]; // L2CAP source CID for SDP
 | |
|         uint8_t sdp_dcid[2]; // 0x0050
 | |
|         uint8_t rfcomm_scid[2]; // L2CAP source CID for RFCOMM
 | |
|         uint8_t rfcomm_dcid[2]; // 0x0051
 | |
| 
 | |
|         /* RFCOMM Variables */
 | |
|         uint8_t rfcommChannel;
 | |
|         uint8_t rfcommChannelConnection; // This is the channel the SPP channel will be running at
 | |
|         uint8_t rfcommDirection;
 | |
|         uint8_t rfcommCommandResponse;
 | |
|         uint8_t rfcommChannelType;
 | |
|         uint8_t rfcommPfBit;
 | |
| 
 | |
|         uint32_t timer;
 | |
|         bool waitForLastCommand;
 | |
|         bool creditSent;
 | |
| 
 | |
|         uint8_t rfcommDataBuffer[100]; // Create a 100 sized buffer for incoming data
 | |
|         uint8_t sppOutputBuffer[100]; // Create a 100 sized buffer for outgoing SPP data
 | |
|         uint8_t sppIndex;
 | |
|         uint8_t rfcommAvailable;
 | |
| 
 | |
|         bool firstMessage; // Used to see if it's the first SDP request received
 | |
|         uint8_t bytesRead; // Counter to see when it's time to send more credit
 | |
| 
 | |
|         /* State machines */
 | |
|         void SDP_task(); // SDP state machine
 | |
|         void RFCOMM_task(); // RFCOMM state machine
 | |
| 
 | |
|         /* SDP Commands */
 | |
|         void SDP_Command(uint8_t *data, uint8_t nbytes);
 | |
|         void serviceNotSupported(uint8_t transactionIDHigh, uint8_t transactionIDLow);
 | |
|         void serialPortResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
 | |
|         void serialPortResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
 | |
|         void l2capResponse1(uint8_t transactionIDHigh, uint8_t transactionIDLow);
 | |
|         void l2capResponse2(uint8_t transactionIDHigh, uint8_t transactionIDLow);
 | |
| 
 | |
|         /* RFCOMM Commands */
 | |
|         void RFCOMM_Command(uint8_t *data, uint8_t nbytes);
 | |
|         void sendRfcomm(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t *data, uint8_t length);
 | |
|         void sendRfcommCredit(uint8_t channel, uint8_t direction, uint8_t CR, uint8_t channelType, uint8_t pfBit, uint8_t credit);
 | |
|         uint8_t calcFcs(uint8_t *data);
 | |
|         bool checkFcs(uint8_t *data, uint8_t fcs);
 | |
|         uint8_t crc(uint8_t *data);
 | |
| };
 | |
| #endif
 | 
