1/*
2 * Copyright 2008 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
8#include <bluetooth/DeviceClass.h>
9#include <bluetooth/DiscoveryAgent.h>
10#include <bluetooth/DiscoveryListener.h>
11#include <bluetooth/bdaddrUtils.h>
12#include <bluetooth/LocalDevice.h>
13#include <bluetooth/RemoteDevice.h>
14
15#include <bluetooth/HCI/btHCI_command.h>
16#include <bluetooth/HCI/btHCI_event.h>
17
18#include <bluetooth/debug.h>
19#include <bluetooth/bluetooth_error.h>
20
21#include <Catalog.h>
22#include <CommandManager.h>
23#include <Locale.h>
24#include <bluetoothserver_p.h>
25
26#include "KitSupport.h"
27
28
29#undef B_TRANSLATION_CONTEXT
30#define B_TRANSLATION_CONTEXT "RemoteDevice"
31
32
33namespace Bluetooth {
34
35
36// TODO: Check headers for valid/reserved ranges
37static const uint16 invalidConnectionHandle = 0xF000;
38
39
40bool
41RemoteDevice::IsTrustedDevice(void)
42{
43	CALLED();
44	return true;
45}
46
47
48BString
49RemoteDevice::GetFriendlyName(bool alwaysAsk)
50{
51	CALLED();
52	if (!alwaysAsk) {
53		// Check if the name is already retrieved
54		// TODO: Check if It is known from a KnownDevicesList
55		return BString(B_TRANSLATE("Not implemented"));
56	}
57
58	if (fDiscovererLocalDevice == NULL)
59		return BString(B_TRANSLATE("#NoOwnerError#Not Valid name"));
60
61	if (fMessenger == NULL)
62		return BString(B_TRANSLATE("#ServerNotReady#Not Valid name"));
63
64	void* remoteNameCommand = NULL;
65	size_t size;
66
67	// Issue inquiry command
68	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
69	BMessage reply;
70
71	request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
72
73	// Fill the request
74	remoteNameCommand = buildRemoteNameRequest(fBdaddr, fPageRepetitionMode,
75		fClockOffset, &size);
76
77	request.AddData("raw command", B_ANY_TYPE, remoteNameCommand, size);
78
79	request.AddInt16("eventExpected",  HCI_EVENT_CMD_STATUS);
80	request.AddInt16("opcodeExpected",
81		PACK_OPCODE(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST));
82
83	request.AddInt16("eventExpected",  HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE);
84
85
86	if (fMessenger->SendMessage(&request, &reply) == B_OK) {
87		BString name;
88		int8 status;
89
90		if ((reply.FindInt8("status", &status) == B_OK) && (status == BT_OK)) {
91
92			if ((reply.FindString("friendlyname", &name) == B_OK )) {
93				return name;
94			} else {
95				return BString(""); // should not happen
96			}
97
98		} else {
99			// seems we got a negative event
100			return BString(B_TRANSLATE("#CommandFailed#Not Valid name"));
101		}
102	}
103
104	return BString(B_TRANSLATE("#NotCompletedRequest#Not Valid name"));
105}
106
107
108BString
109RemoteDevice::GetFriendlyName()
110{
111	CALLED();
112	return GetFriendlyName(true);
113}
114
115
116bdaddr_t
117RemoteDevice::GetBluetoothAddress()
118{
119	CALLED();
120	return fBdaddr;
121}
122
123
124bool
125RemoteDevice::Equals(RemoteDevice* obj)
126{
127	CALLED();
128	return bdaddrUtils::Compare(fBdaddr, obj->GetBluetoothAddress());
129}
130
131
132//  static RemoteDevice* GetRemoteDevice(Connection conn);
133
134
135bool
136RemoteDevice::Authenticate()
137{
138	CALLED();
139	int8 btStatus = BT_ERROR;
140
141	if (fMessenger == NULL || fDiscovererLocalDevice == NULL)
142		return false;
143
144	BluetoothCommand<typed_command(hci_cp_create_conn)>
145		createConnection(OGF_LINK_CONTROL, OCF_CREATE_CONN);
146
147	bdaddrUtils::Copy(createConnection->bdaddr, fBdaddr);
148	createConnection->pscan_rep_mode = fPageRepetitionMode;
149	createConnection->pscan_mode = fScanMode; // Reserved in spec 2.1
150	createConnection->clock_offset = fClockOffset | 0x8000; // substract!
151
152	uint32 roleSwitch;
153	fDiscovererLocalDevice->GetProperty("role_switch_capable", &roleSwitch);
154	createConnection->role_switch = (uint8)roleSwitch;
155
156	uint32 packetType;
157	fDiscovererLocalDevice->GetProperty("packet_type", &packetType);
158	createConnection->pkt_type = (uint16)packetType;
159
160	BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
161	BMessage reply;
162
163	request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
164	request.AddData("raw command", B_ANY_TYPE,
165		createConnection.Data(), createConnection.Size());
166
167	// First we get the status about the starting of the connection
168	request.AddInt16("eventExpected",  HCI_EVENT_CMD_STATUS);
169	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
170		OCF_CREATE_CONN));
171
172	// if authentication needed, we will send any of these commands
173	// to accept or deny the LINK KEY [a]
174	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
175	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
176		OCF_LINK_KEY_REPLY));
177
178	request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
179	request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
180		OCF_LINK_KEY_NEG_REPLY));
181
182	// in negative case, a pincode will be replied [b]
183	// this request will be handled by sepatated by the pincode window
184	// request.AddInt16("eventExpected",  HCI_EVENT_CMD_COMPLETE);
185	// request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
186	//	OCF_PIN_CODE_REPLY));
187
188	// [a] this is expected of authentication required
189	request.AddInt16("eventExpected", HCI_EVENT_LINK_KEY_REQ);
190	// [b] If we deny the key an authentication will be requested
191	// but this request will be handled by sepatated by the pincode
192	// window
193	// request.AddInt16("eventExpected", HCI_EVENT_PIN_CODE_REQ);
194
195	// this almost involves already the happy end
196	request.AddInt16("eventExpected",  HCI_EVENT_LINK_KEY_NOTIFY);
197
198	request.AddInt16("eventExpected", HCI_EVENT_CONN_COMPLETE);
199
200	if (fMessenger->SendMessage(&request, &reply) == B_OK)
201		reply.FindInt8("status", &btStatus);
202
203	if (btStatus == BT_OK) {
204		reply.FindInt16("handle", (int16*)&fHandle);
205		return true;
206	} else
207		return false;
208}
209
210
211status_t
212RemoteDevice::Disconnect(int8 reason)
213{
214	CALLED();
215	if (fHandle != invalidConnectionHandle) {
216
217		int8 btStatus = BT_ERROR;
218
219		if (fMessenger == NULL || fDiscovererLocalDevice == NULL)
220			return false;
221
222		BluetoothCommand<typed_command(struct hci_disconnect)>
223			disconnect(OGF_LINK_CONTROL, OCF_DISCONNECT);
224
225		disconnect->reason = reason;
226		disconnect->handle = fHandle;
227
228		BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
229		BMessage reply;
230
231
232		request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
233		request.AddData("raw command", B_ANY_TYPE,
234			disconnect.Data(), disconnect.Size());
235
236		request.AddInt16("eventExpected",  HCI_EVENT_CMD_STATUS);
237		request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
238			OCF_DISCONNECT));
239
240		request.AddInt16("eventExpected",  HCI_EVENT_DISCONNECTION_COMPLETE);
241
242		if (fMessenger->SendMessage(&request, &reply) == B_OK)
243			reply.FindInt8("status", &btStatus);
244
245		if (btStatus == BT_OK)
246			fHandle = invalidConnectionHandle;
247
248		return btStatus;
249
250	}
251
252	return B_ERROR;
253}
254
255
256//  bool Authorize(Connection conn);
257//  bool Encrypt(Connection conn, bool on);
258
259
260bool
261RemoteDevice::IsAuthenticated()
262{
263	CALLED();
264	return true;
265}
266
267
268//  bool IsAuthorized(Connection conn);
269
270
271bool
272RemoteDevice::IsEncrypted()
273{
274	CALLED();
275	return true;
276}
277
278
279LocalDevice*
280RemoteDevice::GetLocalDeviceOwner()
281{
282	CALLED();
283	return fDiscovererLocalDevice;
284}
285
286
287/* Private */
288void
289RemoteDevice::SetLocalDeviceOwner(LocalDevice* ld)
290{
291	CALLED();
292	fDiscovererLocalDevice = ld;
293}
294
295
296/* Constructor */
297RemoteDevice::RemoteDevice(const bdaddr_t address, uint8 record[3])
298	:
299	BluetoothDevice(),
300	fDiscovererLocalDevice(NULL),
301	fHandle(invalidConnectionHandle)
302{
303	CALLED();
304	fBdaddr = address;
305	fDeviceClass.SetRecord(record);
306	fMessenger = _RetrieveBluetoothMessenger();
307}
308
309
310RemoteDevice::RemoteDevice(const BString& address)
311	:
312	BluetoothDevice(),
313	fDiscovererLocalDevice(NULL),
314	fHandle(invalidConnectionHandle)
315{
316	CALLED();
317	fBdaddr = bdaddrUtils::FromString((const char*)address.String());
318	fMessenger = _RetrieveBluetoothMessenger();
319}
320
321
322RemoteDevice::~RemoteDevice()
323{
324	CALLED();
325	delete fMessenger;
326}
327
328
329BString
330RemoteDevice::GetProperty(const char* property) /* Throwing */
331{
332	return NULL;
333}
334
335
336status_t
337RemoteDevice::GetProperty(const char* property, uint32* value) /* Throwing */
338{
339	CALLED();
340	return B_ERROR;
341}
342
343
344DeviceClass
345RemoteDevice::GetDeviceClass()
346{
347	CALLED();
348	return fDeviceClass;
349}
350
351} /* end namespace Bluetooth */
352