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