mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-11-04 07:12:33 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			226 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			226 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
 |