xref: /haiku/src/kits/bluetooth/RemoteDevice.cpp (revision 19733b44fa2862d0629d5dbfff0389bba79007d7)
1 /*
2  * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3  * Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <bluetooth/DeviceClass.h>
9 #include <bluetooth/DiscoveryAgent.h>
10 #include <bluetooth/DiscoveryListener.h>
11 #include <bluetooth/bdaddrUtils.h>
12 #include <bluetooth/LocalDevice.h>
13 #include <bluetooth/RemoteDevice.h>
14 
15 #include <bluetooth/HCI/btHCI_command.h>
16 #include <bluetooth/HCI/btHCI_event.h>
17 
18 #include <bluetooth/debug.h>
19 #include <bluetooth/bluetooth_error.h>
20 
21 #include <Catalog.h>
22 #include <CommandManager.h>
23 #include <Locale.h>
24 #include <bluetoothserver_p.h>
25 
26 #include "KitSupport.h"
27 
28 
29 #undef B_TRANSLATION_CONTEXT
30 #define B_TRANSLATION_CONTEXT "RemoteDevice"
31 
32 
33 namespace Bluetooth {
34 
35 
36 // TODO: Check headers for valid/reserved ranges
37 static const uint16 invalidConnectionHandle = 0xF000;
38 
39 
40 bool
IsTrustedDevice(void)41 RemoteDevice::IsTrustedDevice(void)
42 {
43 	CALLED();
44 	return true;
45 }
46 
47 
48 BString
GetFriendlyName(bool alwaysAsk)49 RemoteDevice::GetFriendlyName(bool alwaysAsk)
50 {
51 	CALLED();
52 	if (!alwaysAsk) {
53 		// Check if the name is already retrieved
54 		// TODO: Check if It is known from a KnownDevicesList
55 		return BString(B_TRANSLATE("Not implemented"));
56 	}
57 
58 	if (fDiscovererLocalDevice == NULL)
59 		return BString(B_TRANSLATE("#NoOwnerError#Not Valid name"));
60 
61 	if (fMessenger == NULL)
62 		return BString(B_TRANSLATE("#ServerNotReady#Not Valid name"));
63 
64 	void* remoteNameCommand = NULL;
65 	size_t size;
66 
67 	// Issue inquiry command
68 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
69 	BMessage reply;
70 
71 	request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
72 
73 	// Fill the request
74 	remoteNameCommand = buildRemoteNameRequest(fBdaddr, fPageRepetitionMode,
75 		fClockOffset, &size);
76 
77 	request.AddData("raw command", B_ANY_TYPE, remoteNameCommand, size);
78 
79 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_STATUS);
80 	request.AddInt16("opcodeExpected",
81 		PACK_OPCODE(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST));
82 
83 	request.AddInt16("eventExpected",  HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE);
84 
85 
86 	if (fMessenger->SendMessage(&request, &reply) == B_OK) {
87 		BString name;
88 		int8 status;
89 
90 		if ((reply.FindInt8("status", &status) == B_OK) && (status == BT_OK)) {
91 
92 			if ((reply.FindString("friendlyname", &name) == B_OK )) {
93 				return name;
94 			} else {
95 				return BString(""); // should not happen
96 			}
97 
98 		} else {
99 			// seems we got a negative event
100 			return BString(B_TRANSLATE("#CommandFailed#Not Valid name"));
101 		}
102 	}
103 
104 	return BString(B_TRANSLATE("#NotCompletedRequest#Not Valid name"));
105 }
106 
107 
108 BString
GetFriendlyName()109 RemoteDevice::GetFriendlyName()
110 {
111 	CALLED();
112 	return GetFriendlyName(true);
113 }
114 
115 
116 bdaddr_t
GetBluetoothAddress()117 RemoteDevice::GetBluetoothAddress()
118 {
119 	CALLED();
120 	return fBdaddr;
121 }
122 
123 
124 bool
Equals(RemoteDevice * obj)125 RemoteDevice::Equals(RemoteDevice* obj)
126 {
127 	CALLED();
128 	return bdaddrUtils::Compare(fBdaddr, obj->GetBluetoothAddress());
129 }
130 
131 
132 //  static RemoteDevice* GetRemoteDevice(Connection conn);
133 
134 
135 bool
Authenticate()136 RemoteDevice::Authenticate()
137 {
138 	CALLED();
139 	int8 btStatus = BT_ERROR;
140 
141 	if (fMessenger == NULL || fDiscovererLocalDevice == NULL)
142 		return false;
143 
144 	BluetoothCommand<typed_command(hci_cp_create_conn)>
145 		createConnection(OGF_LINK_CONTROL, OCF_CREATE_CONN);
146 
147 	bdaddrUtils::Copy(createConnection->bdaddr, fBdaddr);
148 	createConnection->pscan_rep_mode = fPageRepetitionMode;
149 	createConnection->pscan_mode = fScanMode; // Reserved in spec 2.1
150 	createConnection->clock_offset = fClockOffset | 0x8000; // substract!
151 
152 	uint32 roleSwitch;
153 	fDiscovererLocalDevice->GetProperty("role_switch_capable", &roleSwitch);
154 	createConnection->role_switch = (uint8)roleSwitch;
155 
156 	uint32 packetType;
157 	fDiscovererLocalDevice->GetProperty("packet_type", &packetType);
158 	createConnection->pkt_type = (uint16)packetType;
159 
160 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
161 	BMessage reply;
162 
163 	request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
164 	request.AddData("raw command", B_ANY_TYPE,
165 		createConnection.Data(), createConnection.Size());
166 
167 	// First we get the status about the starting of the connection
168 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_STATUS);
169 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
170 		OCF_CREATE_CONN));
171 
172 	// if authentication needed, we will send any of these commands
173 	// to accept or deny the LINK KEY [a]
174 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
175 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
176 		OCF_LINK_KEY_REPLY));
177 
178 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
179 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
180 		OCF_LINK_KEY_NEG_REPLY));
181 
182 	// in negative case, a pincode will be replied [b]
183 	// this request will be handled by sepatated by the pincode window
184 	// request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
185 	// request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
186 	//	OCF_PIN_CODE_REPLY));
187 
188 	// [a] this is expected of authentication required
189 	request.AddInt16("eventExpected", HCI_EVENT_LINK_KEY_REQ);
190 	// [b] If we deny the key an authentication will be requested
191 	// but this request will be handled by sepatated by the pincode
192 	// window
193 	// request.AddInt16("eventExpected", HCI_EVENT_PIN_CODE_REQ);
194 
195 	// this almost involves already the happy end
196 	request.AddInt16("eventExpected",  HCI_EVENT_LINK_KEY_NOTIFY);
197 
198 	request.AddInt16("eventExpected", HCI_EVENT_CONN_COMPLETE);
199 
200 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
201 		reply.FindInt8("status", &btStatus);
202 
203 	if (btStatus == BT_OK) {
204 		reply.FindInt16("handle", (int16*)&fHandle);
205 		return true;
206 	} else
207 		return false;
208 }
209 
210 
211 status_t
Disconnect(int8 reason)212 RemoteDevice::Disconnect(int8 reason)
213 {
214 	CALLED();
215 	if (fHandle != invalidConnectionHandle) {
216 
217 		int8 btStatus = BT_ERROR;
218 
219 		if (fMessenger == NULL || fDiscovererLocalDevice == NULL)
220 			return false;
221 
222 		BluetoothCommand<typed_command(struct hci_disconnect)>
223 			disconnect(OGF_LINK_CONTROL, OCF_DISCONNECT);
224 
225 		disconnect->reason = reason;
226 		disconnect->handle = fHandle;
227 
228 		BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
229 		BMessage reply;
230 
231 
232 		request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
233 		request.AddData("raw command", B_ANY_TYPE,
234 			disconnect.Data(), disconnect.Size());
235 
236 		request.AddInt16("eventExpected",  HCI_EVENT_CMD_STATUS);
237 		request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
238 			OCF_DISCONNECT));
239 
240 		request.AddInt16("eventExpected",  HCI_EVENT_DISCONNECTION_COMPLETE);
241 
242 		if (fMessenger->SendMessage(&request, &reply) == B_OK)
243 			reply.FindInt8("status", &btStatus);
244 
245 		if (btStatus == BT_OK)
246 			fHandle = invalidConnectionHandle;
247 
248 		return btStatus;
249 
250 	}
251 
252 	return B_ERROR;
253 }
254 
255 
256 //  bool Authorize(Connection conn);
257 //  bool Encrypt(Connection conn, bool on);
258 
259 
260 bool
IsAuthenticated()261 RemoteDevice::IsAuthenticated()
262 {
263 	CALLED();
264 	return true;
265 }
266 
267 
268 //  bool IsAuthorized(Connection conn);
269 
270 
271 bool
IsEncrypted()272 RemoteDevice::IsEncrypted()
273 {
274 	CALLED();
275 	return true;
276 }
277 
278 
279 LocalDevice*
GetLocalDeviceOwner()280 RemoteDevice::GetLocalDeviceOwner()
281 {
282 	CALLED();
283 	return fDiscovererLocalDevice;
284 }
285 
286 
287 /* Private */
288 void
SetLocalDeviceOwner(LocalDevice * ld)289 RemoteDevice::SetLocalDeviceOwner(LocalDevice* ld)
290 {
291 	CALLED();
292 	fDiscovererLocalDevice = ld;
293 }
294 
295 
296 /* Constructor */
RemoteDevice(const bdaddr_t address,uint8 record[3])297 RemoteDevice::RemoteDevice(const bdaddr_t address, uint8 record[3])
298 	:
299 	BluetoothDevice(),
300 	fDiscovererLocalDevice(NULL),
301 	fHandle(invalidConnectionHandle)
302 {
303 	CALLED();
304 	fBdaddr = address;
305 	fDeviceClass.SetRecord(record);
306 	fMessenger = _RetrieveBluetoothMessenger();
307 }
308 
309 
RemoteDevice(const BString & address)310 RemoteDevice::RemoteDevice(const BString& address)
311 	:
312 	BluetoothDevice(),
313 	fDiscovererLocalDevice(NULL),
314 	fHandle(invalidConnectionHandle)
315 {
316 	CALLED();
317 	fBdaddr = bdaddrUtils::FromString((const char*)address.String());
318 	fMessenger = _RetrieveBluetoothMessenger();
319 }
320 
321 
~RemoteDevice()322 RemoteDevice::~RemoteDevice()
323 {
324 	CALLED();
325 	delete fMessenger;
326 }
327 
328 
329 BString
GetProperty(const char * property)330 RemoteDevice::GetProperty(const char* property) /* Throwing */
331 {
332 	return NULL;
333 }
334 
335 
336 status_t
GetProperty(const char * property,uint32 * value)337 RemoteDevice::GetProperty(const char* property, uint32* value) /* Throwing */
338 {
339 	CALLED();
340 	return B_ERROR;
341 }
342 
343 
344 DeviceClass
GetDeviceClass()345 RemoteDevice::GetDeviceClass()
346 {
347 	CALLED();
348 	return fDeviceClass;
349 }
350 
351 } /* end namespace Bluetooth */
352