352 lines
7.8 KiB
C++
352 lines
7.8 KiB
C++
/*
|
|
* Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
|
* Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com
|
|
* All rights reserved. Distributed under the terms of the MIT License.
|
|
*/
|
|
|
|
|
|
#include <bluetooth/DeviceClass.h>
|
|
#include <bluetooth/DiscoveryAgent.h>
|
|
#include <bluetooth/DiscoveryListener.h>
|
|
#include <bluetooth/bdaddrUtils.h>
|
|
#include <bluetooth/LocalDevice.h>
|
|
#include <bluetooth/RemoteDevice.h>
|
|
|
|
#include <bluetooth/HCI/btHCI_command.h>
|
|
#include <bluetooth/HCI/btHCI_event.h>
|
|
|
|
#include <bluetooth/debug.h>
|
|
#include <bluetooth/bluetooth_error.h>
|
|
|
|
#include <Catalog.h>
|
|
#include <CommandManager.h>
|
|
#include <Locale.h>
|
|
#include <bluetoothserver_p.h>
|
|
|
|
#include "KitSupport.h"
|
|
|
|
|
|
#undef B_TRANSLATION_CONTEXT
|
|
#define B_TRANSLATION_CONTEXT "RemoteDevice"
|
|
|
|
|
|
namespace Bluetooth {
|
|
|
|
|
|
// TODO: Check headers for valid/reserved ranges
|
|
static const uint16 invalidConnectionHandle = 0xF000;
|
|
|
|
|
|
bool
|
|
RemoteDevice::IsTrustedDevice(void)
|
|
{
|
|
CALLED();
|
|
return true;
|
|
}
|
|
|
|
|
|
BString
|
|
RemoteDevice::GetFriendlyName(bool alwaysAsk)
|
|
{
|
|
CALLED();
|
|
if (!alwaysAsk) {
|
|
// Check if the name is already retrieved
|
|
// TODO: Check if It is known from a KnownDevicesList
|
|
return BString(B_TRANSLATE("Not implemented"));
|
|
}
|
|
|
|
if (fDiscovererLocalDevice == NULL)
|
|
return BString(B_TRANSLATE("#NoOwnerError#Not Valid name"));
|
|
|
|
if (fMessenger == NULL)
|
|
return BString(B_TRANSLATE("#ServerNotReady#Not Valid name"));
|
|
|
|
void* remoteNameCommand = NULL;
|
|
size_t size;
|
|
|
|
// Issue inquiry command
|
|
BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
|
|
BMessage reply;
|
|
|
|
request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
|
|
|
|
// Fill the request
|
|
remoteNameCommand = buildRemoteNameRequest(fBdaddr, fPageRepetitionMode,
|
|
fClockOffset, &size);
|
|
|
|
request.AddData("raw command", B_ANY_TYPE, remoteNameCommand, size);
|
|
|
|
request.AddInt16("eventExpected", HCI_EVENT_CMD_STATUS);
|
|
request.AddInt16("opcodeExpected",
|
|
PACK_OPCODE(OGF_LINK_CONTROL, OCF_REMOTE_NAME_REQUEST));
|
|
|
|
request.AddInt16("eventExpected", HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE);
|
|
|
|
|
|
if (fMessenger->SendMessage(&request, &reply) == B_OK) {
|
|
BString name;
|
|
int8 status;
|
|
|
|
if ((reply.FindInt8("status", &status) == B_OK) && (status == BT_OK)) {
|
|
|
|
if ((reply.FindString("friendlyname", &name) == B_OK )) {
|
|
return name;
|
|
} else {
|
|
return BString(""); // should not happen
|
|
}
|
|
|
|
} else {
|
|
// seems we got a negative event
|
|
return BString(B_TRANSLATE("#CommandFailed#Not Valid name"));
|
|
}
|
|
}
|
|
|
|
return BString(B_TRANSLATE("#NotCompletedRequest#Not Valid name"));
|
|
}
|
|
|
|
|
|
BString
|
|
RemoteDevice::GetFriendlyName()
|
|
{
|
|
CALLED();
|
|
return GetFriendlyName(true);
|
|
}
|
|
|
|
|
|
bdaddr_t
|
|
RemoteDevice::GetBluetoothAddress()
|
|
{
|
|
CALLED();
|
|
return fBdaddr;
|
|
}
|
|
|
|
|
|
bool
|
|
RemoteDevice::Equals(RemoteDevice* obj)
|
|
{
|
|
CALLED();
|
|
return bdaddrUtils::Compare(fBdaddr, obj->GetBluetoothAddress());
|
|
}
|
|
|
|
|
|
// static RemoteDevice* GetRemoteDevice(Connection conn);
|
|
|
|
|
|
bool
|
|
RemoteDevice::Authenticate()
|
|
{
|
|
CALLED();
|
|
int8 btStatus = BT_ERROR;
|
|
|
|
if (fMessenger == NULL || fDiscovererLocalDevice == NULL)
|
|
return false;
|
|
|
|
BluetoothCommand<typed_command(hci_cp_create_conn)>
|
|
createConnection(OGF_LINK_CONTROL, OCF_CREATE_CONN);
|
|
|
|
bdaddrUtils::Copy(createConnection->bdaddr, fBdaddr);
|
|
createConnection->pscan_rep_mode = fPageRepetitionMode;
|
|
createConnection->pscan_mode = fScanMode; // Reserved in spec 2.1
|
|
createConnection->clock_offset = fClockOffset | 0x8000; // substract!
|
|
|
|
uint32 roleSwitch;
|
|
fDiscovererLocalDevice->GetProperty("role_switch_capable", &roleSwitch);
|
|
createConnection->role_switch = (uint8)roleSwitch;
|
|
|
|
uint32 packetType;
|
|
fDiscovererLocalDevice->GetProperty("packet_type", &packetType);
|
|
createConnection->pkt_type = (uint16)packetType;
|
|
|
|
BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
|
|
BMessage reply;
|
|
|
|
request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
|
|
request.AddData("raw command", B_ANY_TYPE,
|
|
createConnection.Data(), createConnection.Size());
|
|
|
|
// First we get the status about the starting of the connection
|
|
request.AddInt16("eventExpected", HCI_EVENT_CMD_STATUS);
|
|
request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
|
|
OCF_CREATE_CONN));
|
|
|
|
// if authentication needed, we will send any of these commands
|
|
// to accept or deny the LINK KEY [a]
|
|
request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE);
|
|
request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
|
|
OCF_LINK_KEY_REPLY));
|
|
|
|
request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE);
|
|
request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
|
|
OCF_LINK_KEY_NEG_REPLY));
|
|
|
|
// in negative case, a pincode will be replied [b]
|
|
// this request will be handled by sepatated by the pincode window
|
|
// request.AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE);
|
|
// request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
|
|
// OCF_PIN_CODE_REPLY));
|
|
|
|
// [a] this is expected of authentication required
|
|
request.AddInt16("eventExpected", HCI_EVENT_LINK_KEY_REQ);
|
|
// [b] If we deny the key an authentication will be requested
|
|
// but this request will be handled by sepatated by the pincode
|
|
// window
|
|
// request.AddInt16("eventExpected", HCI_EVENT_PIN_CODE_REQ);
|
|
|
|
// this almost involves already the happy end
|
|
request.AddInt16("eventExpected", HCI_EVENT_LINK_KEY_NOTIFY);
|
|
|
|
request.AddInt16("eventExpected", HCI_EVENT_CONN_COMPLETE);
|
|
|
|
if (fMessenger->SendMessage(&request, &reply) == B_OK)
|
|
reply.FindInt8("status", &btStatus);
|
|
|
|
if (btStatus == BT_OK) {
|
|
reply.FindInt16("handle", (int16*)&fHandle);
|
|
return true;
|
|
} else
|
|
return false;
|
|
}
|
|
|
|
|
|
status_t
|
|
RemoteDevice::Disconnect(int8 reason)
|
|
{
|
|
CALLED();
|
|
if (fHandle != invalidConnectionHandle) {
|
|
|
|
int8 btStatus = BT_ERROR;
|
|
|
|
if (fMessenger == NULL || fDiscovererLocalDevice == NULL)
|
|
return false;
|
|
|
|
BluetoothCommand<typed_command(struct hci_disconnect)>
|
|
disconnect(OGF_LINK_CONTROL, OCF_DISCONNECT);
|
|
|
|
disconnect->reason = reason;
|
|
disconnect->handle = fHandle;
|
|
|
|
BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
|
|
BMessage reply;
|
|
|
|
|
|
request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
|
|
request.AddData("raw command", B_ANY_TYPE,
|
|
disconnect.Data(), disconnect.Size());
|
|
|
|
request.AddInt16("eventExpected", HCI_EVENT_CMD_STATUS);
|
|
request.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL,
|
|
OCF_DISCONNECT));
|
|
|
|
request.AddInt16("eventExpected", HCI_EVENT_DISCONNECTION_COMPLETE);
|
|
|
|
if (fMessenger->SendMessage(&request, &reply) == B_OK)
|
|
reply.FindInt8("status", &btStatus);
|
|
|
|
if (btStatus == BT_OK)
|
|
fHandle = invalidConnectionHandle;
|
|
|
|
return btStatus;
|
|
|
|
}
|
|
|
|
return B_ERROR;
|
|
}
|
|
|
|
|
|
// bool Authorize(Connection conn);
|
|
// bool Encrypt(Connection conn, bool on);
|
|
|
|
|
|
bool
|
|
RemoteDevice::IsAuthenticated()
|
|
{
|
|
CALLED();
|
|
return true;
|
|
}
|
|
|
|
|
|
// bool IsAuthorized(Connection conn);
|
|
|
|
|
|
bool
|
|
RemoteDevice::IsEncrypted()
|
|
{
|
|
CALLED();
|
|
return true;
|
|
}
|
|
|
|
|
|
LocalDevice*
|
|
RemoteDevice::GetLocalDeviceOwner()
|
|
{
|
|
CALLED();
|
|
return fDiscovererLocalDevice;
|
|
}
|
|
|
|
|
|
/* Private */
|
|
void
|
|
RemoteDevice::SetLocalDeviceOwner(LocalDevice* ld)
|
|
{
|
|
CALLED();
|
|
fDiscovererLocalDevice = ld;
|
|
}
|
|
|
|
|
|
/* Constructor */
|
|
RemoteDevice::RemoteDevice(const bdaddr_t address, uint8 record[3])
|
|
:
|
|
BluetoothDevice(),
|
|
fDiscovererLocalDevice(NULL),
|
|
fHandle(invalidConnectionHandle)
|
|
{
|
|
CALLED();
|
|
fBdaddr = address;
|
|
fDeviceClass.SetRecord(record);
|
|
fMessenger = _RetrieveBluetoothMessenger();
|
|
}
|
|
|
|
|
|
RemoteDevice::RemoteDevice(const BString& address)
|
|
:
|
|
BluetoothDevice(),
|
|
fDiscovererLocalDevice(NULL),
|
|
fHandle(invalidConnectionHandle)
|
|
{
|
|
CALLED();
|
|
fBdaddr = bdaddrUtils::FromString((const char*)address.String());
|
|
fMessenger = _RetrieveBluetoothMessenger();
|
|
}
|
|
|
|
|
|
RemoteDevice::~RemoteDevice()
|
|
{
|
|
CALLED();
|
|
delete fMessenger;
|
|
}
|
|
|
|
|
|
BString
|
|
RemoteDevice::GetProperty(const char* property) /* Throwing */
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
status_t
|
|
RemoteDevice::GetProperty(const char* property, uint32* value) /* Throwing */
|
|
{
|
|
CALLED();
|
|
return B_ERROR;
|
|
}
|
|
|
|
|
|
DeviceClass
|
|
RemoteDevice::GetDeviceClass()
|
|
{
|
|
CALLED();
|
|
return fDeviceClass;
|
|
}
|
|
|
|
} /* end namespace Bluetooth */
|