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