xref: /haiku/src/kits/bluetooth/LocalDevice.cpp (revision 19733b44fa2862d0629d5dbfff0389bba79007d7)
1 /*
2  * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3  * Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com
4  * Copyright 2012 Fredrik Modéen, [firstname]@[lastname]
5  * All rights reserved. Distributed under the terms of the MIT License.
6  */
7 
8 
9 #include <bluetooth/bluetooth_error.h>
10 
11 #include <bluetooth/HCI/btHCI_command.h>
12 #include <bluetooth/HCI/btHCI_event.h>
13 
14 #include <bluetooth/DeviceClass.h>
15 #include <bluetooth/DiscoveryAgent.h>
16 #include <bluetooth/LocalDevice.h>
17 #include <bluetooth/RemoteDevice.h>
18 
19 #include <bluetooth/bdaddrUtils.h>
20 #include <bluetoothserver_p.h>
21 #include <CommandManager.h>
22 
23 #include <new>
24 
25 #include "KitSupport.h"
26 
27 
28 namespace Bluetooth {
29 
30 
31 LocalDevice*
RequestLocalDeviceID(BMessage * request)32 LocalDevice::RequestLocalDeviceID(BMessage* request)
33 {
34 	BMessage reply;
35 	hci_id hid;
36 	LocalDevice* lDevice = NULL;
37 
38 	BMessenger* messenger = _RetrieveBluetoothMessenger();
39 
40 	if (messenger == NULL)
41 		return NULL;
42 
43 	if (messenger->SendMessage(request, &reply) == B_OK
44 		&& reply.FindInt32("hci_id", &hid) == B_OK ) {
45 
46 		if (hid >= 0)
47 			lDevice = new (std::nothrow)LocalDevice(hid);
48 	}
49 
50 	delete messenger;
51 	return lDevice;
52 }
53 
54 
55 #if 0
56 #pragma -
57 #endif
58 
59 
60 LocalDevice*
GetLocalDevice()61 LocalDevice::GetLocalDevice()
62 {
63 	BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE);
64 
65 	return RequestLocalDeviceID(&request);
66 }
67 
68 
69 LocalDevice*
GetLocalDevice(const hci_id hid)70 LocalDevice::GetLocalDevice(const hci_id hid)
71 {
72 	BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE);
73 	request.AddInt32("hci_id", hid);
74 
75 	return RequestLocalDeviceID(&request);
76 }
77 
78 
79 LocalDevice*
GetLocalDevice(const bdaddr_t bdaddr)80 LocalDevice::GetLocalDevice(const bdaddr_t bdaddr)
81 {
82 	BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE);
83 	request.AddData("bdaddr", B_ANY_TYPE, &bdaddr, sizeof(bdaddr_t));
84 
85 	return RequestLocalDeviceID(&request);
86 }
87 
88 
89 uint32
GetLocalDeviceCount()90 LocalDevice::GetLocalDeviceCount()
91 {
92 	BMessenger* messenger = _RetrieveBluetoothMessenger();
93 	uint32 count = 0;
94 
95 	if (messenger != NULL) {
96 
97 		BMessage request(BT_MSG_COUNT_LOCAL_DEVICES);
98 		BMessage reply;
99 
100 		if (messenger->SendMessage(&request, &reply) == B_OK)
101 			count = reply.FindInt32("count");
102 
103 		delete messenger;
104 	}
105 
106 	return count;
107 
108 }
109 
110 
111 DiscoveryAgent*
GetDiscoveryAgent()112 LocalDevice::GetDiscoveryAgent()
113 {
114 	// TODO: Study a singleton here
115 	return new (std::nothrow)DiscoveryAgent(this);
116 }
117 
118 
119 BString
GetProperty(const char * property)120 LocalDevice::GetProperty(const char* property)
121 {
122 	return NULL;
123 
124 }
125 
126 
127 status_t
GetProperty(const char * property,uint32 * value)128 LocalDevice::GetProperty(const char* property, uint32* value)
129 {
130 	if (fMessenger == NULL)
131 		return B_ERROR;
132 
133 	BMessage request(BT_MSG_GET_PROPERTY);
134 	BMessage reply;
135 
136 	request.AddInt32("hci_id", fHid);
137 	request.AddString("property", property);
138 
139 	if (fMessenger->SendMessage(&request, &reply) == B_OK) {
140 		if (reply.FindInt32("result", (int32*)value ) == B_OK ) {
141 			return B_OK;
142 
143 		}
144 	}
145 
146 	return B_ERROR;
147 }
148 
149 
150 int
GetDiscoverable()151 LocalDevice::GetDiscoverable()
152 {
153 	if (fMessenger == NULL)
154 		return -1;
155 
156 	size_t	size;
157 	void* command = buildReadScan(&size);
158 	if (command == NULL)
159 		return -1;
160 
161 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
162 	request.AddInt32("hci_id", fHid);
163 	request.AddData("raw command", B_ANY_TYPE, command, size);
164 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
165 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
166 		OCF_READ_SCAN_ENABLE));
167 
168 	int8 discoverable;
169 	BMessage reply;
170 	if (fMessenger->SendMessage(&request, &reply) == B_OK
171 		&& reply.FindInt8("scan_enable", &discoverable) == B_OK)
172 		return discoverable;
173 
174 	return -1;
175 }
176 
177 
178 status_t
SetDiscoverable(int mode)179 LocalDevice::SetDiscoverable(int mode)
180 {
181 	if (fMessenger == NULL)
182 		return B_ERROR;
183 
184 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
185 	BMessage reply;
186 
187 	size_t size;
188 	int8 bt_status = BT_ERROR;
189 
190 	request.AddInt32("hci_id", fHid);
191 
192 
193 	void* command = buildWriteScan(mode, &size);
194 
195 	if (command == NULL) {
196 		return B_NO_MEMORY;
197 	}
198 
199 	request.AddData("raw command", B_ANY_TYPE, command, size);
200 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
201 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
202 		OCF_WRITE_SCAN_ENABLE));
203 
204 	if (fMessenger->SendMessage(&request, &reply) == B_OK) {
205 		if (reply.FindInt8("status", &bt_status ) == B_OK ) {
206 			return bt_status;
207 
208 		}
209 	}
210 
211 	return B_ERROR;
212 }
213 
214 
215 struct authentication_t {
216 	uint8 param;
217 };
218 
219 
220 status_t
SetAuthentication(bool authentication)221 LocalDevice::SetAuthentication(bool authentication)
222 {
223 	return SingleParameterCommandRequest<struct authentication_t, uint8>
224 		(OGF_CONTROL_BASEBAND, OCF_WRITE_AUTH_ENABLE, authentication,
225 		NULL, fHid, fMessenger);
226 }
227 
228 
229 bdaddr_t
GetBluetoothAddress()230 LocalDevice::GetBluetoothAddress()
231 {
232 	if (fMessenger == NULL)
233 		return bdaddrUtils::LocalAddress();
234 
235 	size_t	size;
236 	void* command = buildReadBdAddr(&size);
237 
238 	if (command == NULL)
239 		return bdaddrUtils::LocalAddress();
240 
241 	const bdaddr_t* bdaddr;
242 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
243 	BMessage reply;
244 	ssize_t	ssize;
245 
246 	request.AddInt32("hci_id", fHid);
247 	request.AddData("raw command", B_ANY_TYPE, command, size);
248 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
249 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM,
250 		OCF_READ_BD_ADDR));
251 
252 	if (fMessenger->SendMessage(&request, &reply) == B_OK
253 		&& reply.FindData("bdaddr", B_ANY_TYPE, 0,
254 			(const void**)&bdaddr, &ssize) == B_OK)
255 			return *bdaddr;
256 
257 	return bdaddrUtils::LocalAddress();
258 }
259 
260 
261 hci_id
ID(void) const262 LocalDevice::ID(void) const
263 {
264 	return fHid;
265 }
266 
267 
268 BString
GetFriendlyName()269 LocalDevice::GetFriendlyName()
270 {
271 	if (fMessenger == NULL)
272 		return BString("Unknown|Messenger");
273 
274 	size_t	size;
275 	void* command = buildReadLocalName(&size);
276 	if (command == NULL)
277 		return BString("Unknown|NoMemory");
278 
279 	BString friendlyname;
280 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
281 	BMessage reply;
282 
283 
284 	request.AddInt32("hci_id", fHid);
285 	request.AddData("raw command", B_ANY_TYPE, command, size);
286 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
287 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
288 		OCF_READ_LOCAL_NAME));
289 
290 	if (fMessenger->SendMessage(&request, &reply) == B_OK
291 		&& reply.FindString("friendlyname", &friendlyname) == B_OK)
292 		return friendlyname;
293 
294 	return BString("Unknown|ServerFailed");
295 }
296 
297 
298 status_t
SetFriendlyName(BString & name)299 LocalDevice::SetFriendlyName(BString& name)
300 {
301 	int8 btStatus = BT_ERROR;
302 
303 	if (fMessenger == NULL)
304 		return btStatus;
305 
306 	BluetoothCommand<typed_command(hci_write_local_name)>
307 		writeName(OGF_CONTROL_BASEBAND, OCF_WRITE_LOCAL_NAME);
308 
309 	strcpy(writeName->local_name, name.String());
310 
311 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
312 	BMessage reply;
313 
314 	request.AddInt32("hci_id", fHid);
315 	request.AddData("raw command", B_ANY_TYPE,
316 		writeName.Data(), writeName.Size());
317 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
318 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
319 		OCF_WRITE_LOCAL_NAME));
320 
321 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
322 		reply.FindInt8("status", &btStatus);
323 
324 	return btStatus;
325 }
326 
327 
328 DeviceClass
GetDeviceClass()329 LocalDevice::GetDeviceClass()
330 {
331 
332 //	if (fDeviceClass.IsUnknownDeviceClass()) {
333 
334 		if (fMessenger == NULL)
335 			return fDeviceClass;
336 
337 		size_t	size;
338 		void* command = buildReadClassOfDevice(&size);
339 		if (command == NULL)
340 			return fDeviceClass;
341 
342 		BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
343 		BMessage reply;
344 		const uint8* bufferRecord;
345 		ssize_t	ssize;
346 
347 		request.AddInt32("hci_id", fHid);
348 		request.AddData("raw command", B_ANY_TYPE, command, size);
349 		request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
350 		request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
351 			OCF_READ_CLASS_OF_DEV));
352 
353 		if (fMessenger->SendMessage(&request, &reply) == B_OK
354 			&& reply.FindData("devclass", B_ANY_TYPE, 0, (const void**)&bufferRecord,
355 			&ssize) == B_OK) {
356 			uint8 record[3] = { bufferRecord[0], bufferRecord[1], bufferRecord[2] };
357 			fDeviceClass.SetRecord(record);
358 		}
359 //	}
360 
361 	return fDeviceClass;
362 
363 }
364 
365 
366 status_t
SetDeviceClass(DeviceClass deviceClass)367 LocalDevice::SetDeviceClass(DeviceClass deviceClass)
368 {
369 	int8 bt_status = BT_ERROR;
370 
371 	if (fMessenger == NULL)
372 		return bt_status;
373 
374 	BluetoothCommand<typed_command(hci_write_dev_class)>
375 		setDeviceClass(OGF_CONTROL_BASEBAND, OCF_WRITE_CLASS_OF_DEV);
376 
377 	setDeviceClass->dev_class[0] = deviceClass.Record() & 0xFF;
378 	setDeviceClass->dev_class[1] = (deviceClass.Record() & 0xFF00) >> 8;
379 	setDeviceClass->dev_class[2] = (deviceClass.Record() & 0xFF0000) >> 16;
380 
381 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
382 	BMessage reply;
383 
384 	request.AddInt32("hci_id", fHid);
385 	request.AddData("raw command", B_ANY_TYPE,
386 		setDeviceClass.Data(), setDeviceClass.Size());
387 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
388 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
389 		OCF_WRITE_CLASS_OF_DEV));
390 
391 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
392 		reply.FindInt8("status", &bt_status);
393 
394 	return bt_status;
395 
396 }
397 
398 
399 status_t
_ReadLocalVersion()400 LocalDevice::_ReadLocalVersion()
401 {
402 	int8 bt_status = BT_ERROR;
403 
404 	BluetoothCommand<> localVersion(OGF_INFORMATIONAL_PARAM,
405 		OCF_READ_LOCAL_VERSION);
406 
407 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
408 	BMessage reply;
409 
410 	request.AddInt32("hci_id", fHid);
411 	request.AddData("raw command", B_ANY_TYPE,
412 		localVersion.Data(), localVersion.Size());
413 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
414 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM,
415 		OCF_READ_LOCAL_VERSION));
416 
417 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
418 		reply.FindInt8("status", &bt_status);
419 
420 	return bt_status;
421 }
422 
423 
424 status_t
_ReadBufferSize()425 LocalDevice::_ReadBufferSize()
426 {
427 	int8 bt_status = BT_ERROR;
428 
429 	BluetoothCommand<> BufferSize(OGF_INFORMATIONAL_PARAM,
430 		OCF_READ_BUFFER_SIZE);
431 
432 
433 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
434 	BMessage reply;
435 
436 	request.AddInt32("hci_id", fHid);
437 	request.AddData("raw command", B_ANY_TYPE,
438 		BufferSize.Data(), BufferSize.Size());
439 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
440 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM,
441 		OCF_READ_BUFFER_SIZE));
442 
443 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
444 		reply.FindInt8("status", &bt_status);
445 
446 	return bt_status;
447 }
448 
449 
450 status_t
_ReadLocalFeatures()451 LocalDevice::_ReadLocalFeatures()
452 {
453 	int8 bt_status = BT_ERROR;
454 
455 	BluetoothCommand<> LocalFeatures(OGF_INFORMATIONAL_PARAM,
456 		OCF_READ_LOCAL_FEATURES);
457 
458 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
459 	BMessage reply;
460 
461 	request.AddInt32("hci_id", fHid);
462 	request.AddData("raw command", B_ANY_TYPE,
463 		LocalFeatures.Data(), LocalFeatures.Size());
464 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
465 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_INFORMATIONAL_PARAM,
466 		OCF_READ_LOCAL_FEATURES));
467 
468 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
469 		reply.FindInt8("status", &bt_status);
470 
471 	return bt_status;
472 }
473 
474 
475 status_t
_ReadLinkKeys()476 LocalDevice::_ReadLinkKeys()
477 {
478 	int8 bt_status = BT_ERROR;
479 
480 	BluetoothCommand<> LocalFeatures(OGF_CONTROL_BASEBAND,
481 		OCF_READ_STORED_LINK_KEY);
482 
483 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
484 	BMessage reply;
485 
486 	request.AddInt32("hci_id", fHid);
487 	request.AddData("raw command", B_ANY_TYPE,
488 		LocalFeatures.Data(), LocalFeatures.Size());
489 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
490 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
491 		OCF_READ_STORED_LINK_KEY));
492 
493 	request.AddInt16("eventExpected",  HCI_EVENT_RETURN_LINK_KEYS);
494 
495 
496 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
497 		reply.FindInt8("status", &bt_status);
498 
499 	return bt_status;
500 }
501 
502 
503 struct pageTimeout_t {
504 	uint16 param;
505 };
506 
507 
508 status_t
_ReadTimeouts()509 LocalDevice::_ReadTimeouts()
510 {
511 
512 	// Read PageTimeout
513 	NonParameterCommandRequest(OGF_CONTROL_BASEBAND,
514 		OCF_READ_PG_TIMEOUT, NULL, fHid, fMessenger);
515 
516 	// Write PageTimeout
517 	SingleParameterCommandRequest<struct pageTimeout_t, uint16>
518 		(OGF_CONTROL_BASEBAND, OCF_WRITE_PG_TIMEOUT, 0x8000, NULL,
519 		fHid, fMessenger);
520 
521 	// Write PageTimeout
522 	return SingleParameterCommandRequest<struct pageTimeout_t, uint16>
523 		(OGF_CONTROL_BASEBAND, OCF_WRITE_CA_TIMEOUT, 0x7d00, NULL,
524 		fHid, fMessenger);
525 }
526 
527 
528 status_t
Reset()529 LocalDevice::Reset()
530 {
531 	int8 bt_status = BT_ERROR;
532 
533 	BluetoothCommand<> Reset(OGF_CONTROL_BASEBAND, OCF_RESET);
534 
535 	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
536 	BMessage reply;
537 
538 	request.AddInt32("hci_id", fHid);
539 	request.AddData("raw command", B_ANY_TYPE, Reset.Data(), Reset.Size());
540 	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
541 	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_CONTROL_BASEBAND,
542 		OCF_RESET));
543 
544 	if (fMessenger->SendMessage(&request, &reply) == B_OK)
545 		reply.FindInt8("status", &bt_status);
546 
547 	return bt_status;
548 
549 }
550 
551 
552 /*
553 ServiceRecord
554 LocalDevice::getRecord(Connection notifier) {
555 
556 }
557 
558 void
559 LocalDevice::updateRecord(ServiceRecord srvRecord) {
560 
561 }
562 */
563 
564 
LocalDevice(hci_id hid)565 LocalDevice::LocalDevice(hci_id hid)
566 	:
567 	BluetoothDevice(),
568 	fHid(hid)
569 {
570 	fMessenger = _RetrieveBluetoothMessenger();
571 
572 	_ReadBufferSize();
573 	_ReadLocalFeatures();
574 	_ReadLocalVersion();
575 	_ReadTimeouts();
576 	_ReadLinkKeys();
577 
578 	// Uncomment this if you want your device to have a nicer default name
579 	// BString name("HaikuBluetooth");
580 	// SetFriendlyName(name);
581 
582 
583 	uint32 value;
584 
585 	// HARDCODE -> move this to addons
586 	if (GetProperty("manufacturer", &value) == B_OK
587 		&& value == 15) {
588 
589 		// Uncomment this out if your Broadcom dongle is not working properly
590 		// Reset();	// Perform a reset to Broadcom buggyland
591 
592 // Uncomment this out if your Broadcom dongle has a null bdaddr
593 //#define BT_WRITE_BDADDR_FOR_BCM2035
594 #ifdef BT_WRITE_BDADDR_FOR_BCM2035
595 #warning Writting broadcom bdaddr @ init.
596 		// try write bdaddr to a bcm2035 -> will be moved to an addon
597 		int8 bt_status = BT_ERROR;
598 
599 		BluetoothCommand<typed_command(hci_write_bcm2035_bdaddr)>
600 			writeAddress(OGF_VENDOR_CMD, OCF_WRITE_BCM2035_BDADDR);
601 
602 		BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
603 		BMessage reply;
604 		writeAddress->bdaddr.b[0] = 0x3C;
605 		writeAddress->bdaddr.b[1] = 0x19;
606 		writeAddress->bdaddr.b[2] = 0x30;
607 		writeAddress->bdaddr.b[3] = 0xC9;
608 		writeAddress->bdaddr.b[4] = 0x03;
609 		writeAddress->bdaddr.b[5] = 0x00;
610 
611 		request.AddInt32("hci_id", fHid);
612 		request.AddData("raw command", B_ANY_TYPE,
613 			writeAddress.Data(), writeAddress.Size());
614 		request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
615 		request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_VENDOR_CMD,
616 			OCF_WRITE_BCM2035_BDADDR));
617 
618 		if (fMessenger->SendMessage(&request, &reply) == B_OK)
619 			reply.FindInt8("status", &bt_status);
620 #endif
621 	}
622 }
623 
624 
~LocalDevice()625 LocalDevice::~LocalDevice()
626 {
627 	delete fMessenger;
628 }
629 
630 
631 } /* end namespace Bluetooth */
632