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