Bluetooth support for MBED with $2 Bluetooth dongles. Includes a USB host and built in support for bluetooth HID devices such as mice, keyboards and wii controllers.

Dependencies:   mbed

Committer:
meathome
Date:
Tue Mar 01 12:00:17 2011 +0000
Revision:
0:a1f905acca78

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
meathome 0:a1f905acca78 1 /*
meathome 0:a1f905acca78 2 Copyright (c) 2010 Peter Barrett
meathome 0:a1f905acca78 3
meathome 0:a1f905acca78 4 Permission is hereby granted, free of charge, to any person obtaining a copy
meathome 0:a1f905acca78 5 of this software and associated documentation files (the "Software"), to deal
meathome 0:a1f905acca78 6 in the Software without restriction, including without limitation the rights
meathome 0:a1f905acca78 7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
meathome 0:a1f905acca78 8 copies of the Software, and to permit persons to whom the Software is
meathome 0:a1f905acca78 9 furnished to do so, subject to the following conditions:
meathome 0:a1f905acca78 10
meathome 0:a1f905acca78 11 The above copyright notice and this permission notice shall be included in
meathome 0:a1f905acca78 12 all copies or substantial portions of the Software.
meathome 0:a1f905acca78 13
meathome 0:a1f905acca78 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
meathome 0:a1f905acca78 15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
meathome 0:a1f905acca78 16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
meathome 0:a1f905acca78 17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
meathome 0:a1f905acca78 18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
meathome 0:a1f905acca78 19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
meathome 0:a1f905acca78 20 THE SOFTWARE.
meathome 0:a1f905acca78 21 */
meathome 0:a1f905acca78 22
meathome 0:a1f905acca78 23 #ifndef HCI_H_INCLUDED
meathome 0:a1f905acca78 24 #define HCI_H_INCLUDED
meathome 0:a1f905acca78 25
meathome 0:a1f905acca78 26 #include "Socket.h"
meathome 0:a1f905acca78 27
meathome 0:a1f905acca78 28 #pragma pack(1)
meathome 0:a1f905acca78 29
meathome 0:a1f905acca78 30 #define ERR_HCI_DEVICE_NOT_FOUND -300
meathome 0:a1f905acca78 31
meathome 0:a1f905acca78 32 class HCI;
meathome 0:a1f905acca78 33 class HCITransport;
meathome 0:a1f905acca78 34 class BTDevice;
meathome 0:a1f905acca78 35
meathome 0:a1f905acca78 36 typedef struct
meathome 0:a1f905acca78 37 {
meathome 0:a1f905acca78 38 u8 addr[6];
meathome 0:a1f905acca78 39 } BD_ADDR;
meathome 0:a1f905acca78 40
meathome 0:a1f905acca78 41 typedef struct
meathome 0:a1f905acca78 42 {
meathome 0:a1f905acca78 43 BD_ADDR bdaddr;
meathome 0:a1f905acca78 44 u8 pscan_rep_mode;
meathome 0:a1f905acca78 45 u8 pscan_period_mode;
meathome 0:a1f905acca78 46 u8 pscan_mode;
meathome 0:a1f905acca78 47 u8 dev_class[3];
meathome 0:a1f905acca78 48 u16 clock_offset;
meathome 0:a1f905acca78 49 } inquiry_info;
meathome 0:a1f905acca78 50
meathome 0:a1f905acca78 51 typedef struct
meathome 0:a1f905acca78 52 {
meathome 0:a1f905acca78 53 u8 status;
meathome 0:a1f905acca78 54 u16 handle;
meathome 0:a1f905acca78 55 BD_ADDR bdaddr;
meathome 0:a1f905acca78 56 u8 link_type;
meathome 0:a1f905acca78 57 u8 encr_mode;
meathome 0:a1f905acca78 58 } connection_info;
meathome 0:a1f905acca78 59
meathome 0:a1f905acca78 60 // Address struct for creating L2CAP sockets
meathome 0:a1f905acca78 61 typedef struct {
meathome 0:a1f905acca78 62 SocketAddrHdr hdr;
meathome 0:a1f905acca78 63 BD_ADDR bdaddr;
meathome 0:a1f905acca78 64 u16 psm;
meathome 0:a1f905acca78 65 } L2CAPAddr;
meathome 0:a1f905acca78 66
meathome 0:a1f905acca78 67 #pragma pack(4)
meathome 0:a1f905acca78 68
meathome 0:a1f905acca78 69 class BTDevice;
meathome 0:a1f905acca78 70 typedef struct
meathome 0:a1f905acca78 71 {
meathome 0:a1f905acca78 72 public:
meathome 0:a1f905acca78 73 SocketInternal si;
meathome 0:a1f905acca78 74 BTDevice* btdevice;
meathome 0:a1f905acca78 75 u16 scid;
meathome 0:a1f905acca78 76 u16 dcid;
meathome 0:a1f905acca78 77 } L2CAPSocket;
meathome 0:a1f905acca78 78
meathome 0:a1f905acca78 79 #define MAX_HCL_NAME_LENGTH 20 // TODO - BTDevice wants to be a multiple of 4
meathome 0:a1f905acca78 80
meathome 0:a1f905acca78 81 // BTDevice encapsulates individual device state
meathome 0:a1f905acca78 82 // It provides L2CAP layer sockets
meathome 0:a1f905acca78 83
meathome 0:a1f905acca78 84 class BTDevice : public SocketHandler
meathome 0:a1f905acca78 85 {
meathome 0:a1f905acca78 86 public:
meathome 0:a1f905acca78 87 HCITransport* _transport;
meathome 0:a1f905acca78 88 inquiry_info _info;
meathome 0:a1f905acca78 89 u16 _handle; // acl connection handle
meathome 0:a1f905acca78 90 u8 _state; // connection state
meathome 0:a1f905acca78 91 u8 _txid;
meathome 0:a1f905acca78 92 char _name[MAX_HCL_NAME_LENGTH];
meathome 0:a1f905acca78 93
meathome 0:a1f905acca78 94 void Init();
meathome 0:a1f905acca78 95
meathome 0:a1f905acca78 96 BD_ADDR* GetAddress() { return &_info.bdaddr; }
meathome 0:a1f905acca78 97
meathome 0:a1f905acca78 98 // Called from HCI
meathome 0:a1f905acca78 99 void ACLRecv(const u8* data, int len);
meathome 0:a1f905acca78 100
meathome 0:a1f905acca78 101 // SocketHandler
meathome 0:a1f905acca78 102 virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
meathome 0:a1f905acca78 103 virtual int Send(SocketInternal* sock, const u8* data, int len);
meathome 0:a1f905acca78 104 virtual int Close(SocketInternal* sock);
meathome 0:a1f905acca78 105
meathome 0:a1f905acca78 106 private:
meathome 0:a1f905acca78 107 L2CAPSocket* SCIDToSocket(int scid);
meathome 0:a1f905acca78 108 int Send(const u8* data, int len);
meathome 0:a1f905acca78 109 int Send(u8 c, u8 id, u16* params, int count);
meathome 0:a1f905acca78 110 int Connect(int scid, int psm);
meathome 0:a1f905acca78 111 int Disconnect(int scid, int dcid);
meathome 0:a1f905acca78 112 int ConfigureRequest(int dcid);
meathome 0:a1f905acca78 113 int ConfigureResponse(u8 rxid, int dcid);
meathome 0:a1f905acca78 114 int DisconnectResponse(u8 rxid, int scid, int dcid);
meathome 0:a1f905acca78 115 void Control(const u8* data, int len);
meathome 0:a1f905acca78 116 };
meathome 0:a1f905acca78 117
meathome 0:a1f905acca78 118 enum HCI_CALLBACK_EVENT
meathome 0:a1f905acca78 119 {
meathome 0:a1f905acca78 120 CALLBACK_NONE,
meathome 0:a1f905acca78 121 CALLBACK_READY,
meathome 0:a1f905acca78 122 CALLBACK_INQUIRY_RESULT,
meathome 0:a1f905acca78 123 CALLBACK_INQUIRY_DONE,
meathome 0:a1f905acca78 124 CALLBACK_REMOTE_NAME,
meathome 0:a1f905acca78 125 CALLBACK_CONNECTION_COMPLETE,
meathome 0:a1f905acca78 126 CALLBACK_CONNECTION_FAILED
meathome 0:a1f905acca78 127 };
meathome 0:a1f905acca78 128
meathome 0:a1f905acca78 129 // L2CAP Protocol/Service Multiplexor (PSM) values
meathome 0:a1f905acca78 130
meathome 0:a1f905acca78 131 #define L2CAP_PSM_ANY 0x0000 /* Any/Invalid PSM */
meathome 0:a1f905acca78 132 #define L2CAP_PSM_SDP 0x0001 /* Service Discovery Protocol */
meathome 0:a1f905acca78 133 #define L2CAP_PSM_RFCOMM 0x0003 /* RFCOMM protocol */
meathome 0:a1f905acca78 134 #define L2CAP_PSM_TCP 0x0005 /* Telephony Control Protocol */
meathome 0:a1f905acca78 135 #define L2CAP_PSM_TCS 0x0007 /* TCS cordless */
meathome 0:a1f905acca78 136 #define L2CAP_PSM_BNEP 0x000f /* Bluetooth Network Encapsulation Protocol*/
meathome 0:a1f905acca78 137 #define L2CAP_PSM_HID_CNTL 0x0011 /* HID Control */
meathome 0:a1f905acca78 138 #define L2CAP_PSM_HID_INTR 0x0013 /* HID Interrupt */
meathome 0:a1f905acca78 139 #define L2CAP_PSM_ESDP 0x0015 /* Extended Service Discovery Profile */
meathome 0:a1f905acca78 140 #define L2CAP_PSM_AVCTP 0x0017 /* Audio/Visual Control Transport Protocol */
meathome 0:a1f905acca78 141 #define L2CAP_PSM_AVDTP 0x0019 /* Audio/Visual Distribution */
meathome 0:a1f905acca78 142
meathome 0:a1f905acca78 143 // Callback from inquiry
meathome 0:a1f905acca78 144 typedef int (*HCICallback)(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len);
meathome 0:a1f905acca78 145
meathome 0:a1f905acca78 146 #define MAX_BTDEVICES 8
meathome 0:a1f905acca78 147
meathome 0:a1f905acca78 148 class HCITransport;
meathome 0:a1f905acca78 149 class HCI : public SocketHandler
meathome 0:a1f905acca78 150 {
meathome 0:a1f905acca78 151 HCITransport* _transport;
meathome 0:a1f905acca78 152 HCICallback _callback;
meathome 0:a1f905acca78 153 BD_ADDR _localAddr;
meathome 0:a1f905acca78 154
meathome 0:a1f905acca78 155 BTDevice _devices[MAX_BTDEVICES];
meathome 0:a1f905acca78 156 int _deviceCount;
meathome 0:a1f905acca78 157
meathome 0:a1f905acca78 158 int _acl_mtu;
meathome 0:a1f905acca78 159 int _acl_max_pkt;
meathome 0:a1f905acca78 160 int _sco_mtu;
meathome 0:a1f905acca78 161 int _sco_max_pkt;
meathome 0:a1f905acca78 162
meathome 0:a1f905acca78 163 int _state;
meathome 0:a1f905acca78 164
meathome 0:a1f905acca78 165 public:
meathome 0:a1f905acca78 166
meathome 0:a1f905acca78 167 // Open a local adapter
meathome 0:a1f905acca78 168 int Open(HCITransport* transport, HCICallback callback);
meathome 0:a1f905acca78 169
meathome 0:a1f905acca78 170 // Return list of discovered addreses
meathome 0:a1f905acca78 171 int GetDevices(BTDevice** devices, int maxDevices);
meathome 0:a1f905acca78 172
meathome 0:a1f905acca78 173 // Lookup a device by address or handle
meathome 0:a1f905acca78 174 BTDevice* Find(const BD_ADDR* addr);
meathome 0:a1f905acca78 175 BTDevice* Find(int handle);
meathome 0:a1f905acca78 176
meathome 0:a1f905acca78 177 // Disconnect from a remote device
meathome 0:a1f905acca78 178 int Disconnect(const BD_ADDR* addr);
meathome 0:a1f905acca78 179 int DisconnectAll();
meathome 0:a1f905acca78 180
meathome 0:a1f905acca78 181 // see what devies are in the system
meathome 0:a1f905acca78 182 int Inquiry(int duration = 10);
meathome 0:a1f905acca78 183
meathome 0:a1f905acca78 184 // get a name, delivered in callback
meathome 0:a1f905acca78 185 int RemoteNameRequest(const BD_ADDR* addr);
meathome 0:a1f905acca78 186
meathome 0:a1f905acca78 187 // Connect to a remote device
meathome 0:a1f905acca78 188 int CreateConnection(const BD_ADDR* remoteAddr);
meathome 0:a1f905acca78 189
meathome 0:a1f905acca78 190 bool Busy();
meathome 0:a1f905acca78 191
meathome 0:a1f905acca78 192 // called from transport
meathome 0:a1f905acca78 193 void HCIRecv(const u8* data, int len);
meathome 0:a1f905acca78 194
meathome 0:a1f905acca78 195 // called from transport
meathome 0:a1f905acca78 196 void ACLRecv(const u8* data, int len);
meathome 0:a1f905acca78 197
meathome 0:a1f905acca78 198 // SocketHandler methods for maintaining L2CAP sockets
meathome 0:a1f905acca78 199 virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
meathome 0:a1f905acca78 200 virtual int Send(SocketInternal* sock, const u8* data, int len);
meathome 0:a1f905acca78 201 virtual int Close(SocketInternal* sock);
meathome 0:a1f905acca78 202
meathome 0:a1f905acca78 203 private:
meathome 0:a1f905acca78 204 void InquiryResult(const inquiry_info* info);
meathome 0:a1f905acca78 205 void RemoteName(const BD_ADDR* addr, const char* name);
meathome 0:a1f905acca78 206 void ConnectComplete(const connection_info* info);
meathome 0:a1f905acca78 207 void DisconnectComplete(int handle);
meathome 0:a1f905acca78 208 int SendCmd(int cmd, const u8* params = 0, int len = 0);
meathome 0:a1f905acca78 209 void OnCommandComplete(int cmd, const u8* data, int len);
meathome 0:a1f905acca78 210 void Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
meathome 0:a1f905acca78 211 int PinCodeReply(const u8* data);
meathome 0:a1f905acca78 212 };
meathome 0:a1f905acca78 213
meathome 0:a1f905acca78 214 class HCITransport
meathome 0:a1f905acca78 215 {
meathome 0:a1f905acca78 216 protected:
meathome 0:a1f905acca78 217 HCI* _target;
meathome 0:a1f905acca78 218 public:
meathome 0:a1f905acca78 219 void Set(HCI* target) { _target = target; };
meathome 0:a1f905acca78 220 virtual void HCISend(const u8* data, int len) = 0;
meathome 0:a1f905acca78 221 virtual void ACLSend(const u8* data, int len) = 0;
meathome 0:a1f905acca78 222 };
meathome 0:a1f905acca78 223
meathome 0:a1f905acca78 224 #endif