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
28namespace Bluetooth {
29
30
31LocalDevice*
32LocalDevice::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
60LocalDevice*
61LocalDevice::GetLocalDevice()
62{
63	BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE);
64
65	return RequestLocalDeviceID(&request);
66}
67
68
69LocalDevice*
70LocalDevice::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
79LocalDevice*
80LocalDevice::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
89uint32
90LocalDevice::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
111DiscoveryAgent*
112LocalDevice::GetDiscoveryAgent()
113{
114	// TODO: Study a singleton here
115	return new (std::nothrow)DiscoveryAgent(this);
116}
117
118
119BString
120LocalDevice::GetProperty(const char* property)
121{
122	return NULL;
123
124}
125
126
127status_t
128LocalDevice::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
150int
151LocalDevice::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
178status_t
179LocalDevice::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
215struct authentication_t {
216	uint8 param;
217};
218
219
220status_t
221LocalDevice::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
229bdaddr_t
230LocalDevice::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
261hci_id
262LocalDevice::ID(void) const
263{
264	return fHid;
265}
266
267
268BString
269LocalDevice::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
298status_t
299LocalDevice::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
328DeviceClass
329LocalDevice::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
366status_t
367LocalDevice::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
399status_t
400LocalDevice::_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
424status_t
425LocalDevice::_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
450status_t
451LocalDevice::_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
475status_t
476LocalDevice::_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
503struct pageTimeout_t {
504	uint16 param;
505};
506
507
508status_t
509LocalDevice::_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
528status_t
529LocalDevice::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/*
553ServiceRecord
554LocalDevice::getRecord(Connection notifier) {
555
556}
557
558void
559LocalDevice::updateRecord(ServiceRecord srvRecord) {
560
561}
562*/
563
564
565LocalDevice::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
625LocalDevice::~LocalDevice()
626{
627	delete fMessenger;
628}
629
630
631} /* end namespace Bluetooth */
632