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