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