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
27namespace Bluetooth {
28
29
30LocalDevice*
31LocalDevice::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
59LocalDevice*
60LocalDevice::GetLocalDevice()
61{
62	BMessage request(BT_MSG_ACQUIRE_LOCAL_DEVICE);
63
64	return RequestLocalDeviceID(&request);
65}
66
67
68LocalDevice*
69LocalDevice::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
78LocalDevice*
79LocalDevice::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
88uint32
89LocalDevice::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
110DiscoveryAgent*
111LocalDevice::GetDiscoveryAgent()
112{
113	// TODO: Study a singleton here
114	return new (std::nothrow)DiscoveryAgent(this);
115}
116
117
118BString
119LocalDevice::GetProperty(const char* property)
120{
121	return NULL;
122
123}
124
125
126status_t
127LocalDevice::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
149int
150LocalDevice::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
177status_t
178LocalDevice::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
214struct authentication_t {
215	uint8 param;
216};
217
218status_t
219LocalDevice::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
227bdaddr_t
228LocalDevice::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
259hci_id
260LocalDevice::ID(void) const
261{
262	return fHid;
263}
264
265
266BString
267LocalDevice::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
296status_t
297LocalDevice::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
326DeviceClass
327LocalDevice::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
364status_t
365LocalDevice::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
397status_t
398LocalDevice::_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
422status_t
423LocalDevice::_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
447status_t
448LocalDevice::_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
472status_t
473LocalDevice::_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
500struct pageTimeout_t {
501	uint16 param;
502};
503
504status_t
505LocalDevice::_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
524status_t
525LocalDevice::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/*
549ServiceRecord
550LocalDevice::getRecord(Connection notifier) {
551
552}
553
554void
555LocalDevice::updateRecord(ServiceRecord srvRecord) {
556
557}
558*/
559
560
561LocalDevice::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
621LocalDevice::~LocalDevice()
622{
623	delete fMessenger;
624}
625
626
627}
628