Committer:
hosei2
Date:
Tue Jul 10 11:36:47 2012 +0000
Revision:
0:db1ba09e8bfa
zzz

Who changed what in which revision?

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