bluetooth: connection handling refactor

- Introduced cancel connection feature in bluetooth preferences
- Moved the connection handling logic into LocalDeviceImpl
- Made a watchers list to send notices to all concerned applications

Change-Id: Iba87caff68d1b9640fa8d901059daa7a624531f5
Reviewed-on: https://review.haiku-os.org/c/haiku/+/11171
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
mohammedrattia
2026-07-09 16:36:59 +00:00
committed by waddlesplash
parent eb349566e3
commit af619799ef
16 changed files with 632 additions and 260 deletions
+15
View File
@@ -113,13 +113,23 @@ struct hci_command_header {
} __attribute__ ((packed));
#define OCF_READ_CA_TIMEOUT 0x0015
struct hci_rp_read_conn_accept_timeout {
uint8 status;
uint16 conn_accept_timeout;
} __attribute__ ((packed));
#define OCF_WRITE_CA_TIMEOUT 0x0016
struct hci_cp_write_conn_accept_timeout {
uint16 conn_accept_timeout;
} __attribute__ ((packed));
#define OCF_READ_PG_TIMEOUT 0x0017
struct hci_rp_read_page_timeout {
uint8 status;
uint16 page_timeout;
} __attribute__ ((packed));
#define OCF_WRITE_PG_TIMEOUT 0x0018
struct hci_cp_write_page_timeout {
uint16 page_timeout;
} __attribute__ ((packed));
#define OCF_READ_SCAN_ENABLE 0x0019
struct hci_read_scan_enable {
@@ -250,6 +260,11 @@ struct hci_command_header {
uint16 pkt_type;
} __attribute__ ((packed));
#define OCF_CREATE_CONN_CANCEL 0x0008
struct hci_cp_create_conn_cancel {
bdaddr_t bdaddr;
} __attribute__ ((packed));
#define OCF_ACCEPT_CONN_REQ 0x0009
struct hci_cp_accept_conn_req {
bdaddr_t bdaddr;
+34 -28
View File
@@ -9,7 +9,7 @@
#include <bluetooth/bluetooth_error.h>
#include <bluetooth/BluetoothDevice.h>
#include <String.h>
#include <support/String.h>
#define B_BT_WAIT 0x00
#define B_BT_SUCCEEDED 0x01
@@ -26,33 +26,39 @@ public:
static const int WAIT = B_BT_WAIT;
static const int SUCCEEDED = B_BT_SUCCEEDED;
virtual ~RemoteDevice();
virtual ~RemoteDevice();
bool IsTrustedDevice();
BString GetFriendlyName(bool alwaysAsk); /* Throwing */
BString GetFriendlyName(void); /* Throwing */
BString GetCachedFriendlyName();
bdaddr_t GetBluetoothAddress();
DeviceClass GetDeviceClass();
bool IsTrustedDevice();
BString GetFriendlyName(bool alwaysAsk); /* Throwing */
BString GetFriendlyName(void); /* Throwing */
BString GetCachedFriendlyName();
bdaddr_t GetBluetoothAddress();
uint8 GetPageRepetitionMode();
uint8 GetScanMode();
uint8 GetClockOffset();
DeviceClass GetDeviceClass();
bool Equals(RemoteDevice* obj);
bool Equals(RemoteDevice* obj);
status_t Connect();
status_t CancelConnection();
status_t Disconnect();
/*static RemoteDevice* GetRemoteDevice(Connection conn); Throwing */
bool Authenticate(); /* Throwing */
status_t Disconnect(int8 reason = BT_REMOTE_USER_ENDED_CONNECTION);
/* bool Authorize(Connection conn); Throwing */
/*bool Encrypt(Connection conn, bool on); Throwing */
bool IsAuthenticated(); /* Throwing */
/*bool IsAuthorized(Connection conn); Throwing */
bool IsEncrypted(); /* Throwing */
bool IsAuthenticated(); /* Throwing */
bool IsEncrypted(); /* Throwing */
BString GetProperty(const char* property); /* Throwing */
status_t GetProperty(const char* property, uint32* value); /* Throwing */
BString GetProperty(const char* property); /* Throwing */
status_t GetProperty(const char* property, uint32* value); /* Throwing */
LocalDevice* GetLocalDeviceOwner();
LocalDevice* GetLocalDeviceOwner();
RemoteDevice(const BString& address);
RemoteDevice(const bdaddr_t address, uint8 record[3]);
RemoteDevice(const BString& address);
RemoteDevice(const bdaddr_t address, uint8 record[3]);
protected:
/* called by Discovery[Listener|Agent] */
@@ -61,17 +67,17 @@ protected:
private:
LocalDevice* fDiscovererLocalDevice;
BMessenger* fMessenger;
LocalDevice* fDiscovererLocalDevice;
BMessenger* fMessenger;
uint16 fHandle;
uint8 fPageRepetitionMode;
uint8 fScanPeriodMode;
uint8 fScanMode;
uint16 fClockOffset;
int8 fRSSI;
BString fFriendlyName;
bool fFriendlyNameIsComplete;
uint16 fHandle;
uint8 fPageRepetitionMode;
uint8 fScanPeriodMode;
uint8 fScanMode;
uint16 fClockOffset;
int8 fRSSI;
BString fFriendlyName;
bool fFriendlyNameIsComplete;
};
}
+17 -5
View File
@@ -6,6 +6,9 @@
#define BLUETOOTH_APP_SIGNATURE "application/x-vnd.Haiku-BluetoothPrefs"
/* Kit Comunication */
// Watching
#define BT_START_WATCHING_CONNECTIONS 'wtST'
#define BT_STOP_WATCHING_CONNECTIONS 'wtSP'
// LocalDevice
#define BT_MSG_COUNT_LOCAL_DEVICES 'btCd'
@@ -16,10 +19,19 @@
#define BT_MSG_GET_PROPERTY 'btgP'
// Discovery
#define BT_MSG_INQUIRY_STARTED 'IqSt'
#define BT_MSG_INQUIRY_COMPLETED 'IqCM'
#define BT_MSG_INQUIRY_TERMINATED 'IqTR'
#define BT_MSG_INQUIRY_ERROR 'IqER'
#define BT_MSG_INQUIRY_DEVICE 'IqDE'
#define BT_MSG_INQUIRY_STARTED 'IqSt'
#define BT_MSG_INQUIRY_COMPLETED 'IqCM'
#define BT_MSG_INQUIRY_TERMINATED 'IqTR'
#define BT_MSG_INQUIRY_ERROR 'IqER'
#define BT_MSG_INQUIRY_DEVICE 'IqDE'
// Pairing
#define BT_MSG_CONN_FAILED 'CnFL'
#define BT_MSG_CONN_COMPLETED 'CnCM'
#define BT_MSG_DISCONN_COMPLETED 'DcCM'
#define BT_REQ_CREATE_CONN 'rdCN'
#define BT_REQ_CANCEL_CONN 'rdCC'
#define BT_REQ_DISCONNECT 'rdDC'
#endif
@@ -6,6 +6,7 @@
#include <bluetooth/bdaddrUtils.h>
#include <bluetooth/bluetooth_error.h>
#include <bluetooth/HCI/btHCI_transport.h>
#include <bluetooth/HCI/btHCI_event.h>
@@ -49,6 +50,9 @@ PostEvent(bluetooth_device* ndev, void* event, size_t size)
= (struct hci_ev_conn_complete*)(outgoingEvent + 1);
// TODO: XXX parse handle field
if (data->status != BT_OK)
break;
HciConnection* conn = AddConnection(data->handle, BT_ACL,
data->bdaddr, ndev->index);
+5 -8
View File
@@ -81,21 +81,18 @@ DiscoveryAgent::StartInquiry(uint32 accessCode, DiscoveryListener* listener,
PACK_OPCODE(OGF_LINK_CONTROL, OCF_INQUIRY));
// For getting each discovered message
request.AddInt16("eventExpected", HCI_EVENT_INQUIRY_RESULT);
request.AddInt16("eventExpected", HCI_EVENT_INQUIRY_RESULT);
request.AddInt16("eventExpected", HCI_EVENT_INQUIRY_RESULT_WITH_RSSI);
request.AddInt16("eventExpected", HCI_EVENT_EXTENDED_INQUIRY_RESULT);
// For finishing each discovered message
request.AddInt16("eventExpected", HCI_EVENT_INQUIRY_COMPLETE);
request.AddInt16("eventExpected", HCI_EVENT_INQUIRY_COMPLETE);
if (fMessenger->SendMessage(&request, listener) == B_OK)
{
return B_OK;
}
if (fMessenger->SendMessage(&request, listener) == B_OK)
return B_OK;
return B_ERROR;
}
+74 -115
View File
@@ -133,6 +133,27 @@ RemoteDevice::GetBluetoothAddress()
}
uint8
RemoteDevice::GetClockOffset()
{
return fClockOffset;
}
uint8
RemoteDevice::GetScanMode()
{
return fScanMode;
}
uint8
RemoteDevice::GetPageRepetitionMode()
{
return fPageRepetitionMode;
}
bool
RemoteDevice::Equals(RemoteDevice* obj)
{
@@ -141,130 +162,70 @@ RemoteDevice::Equals(RemoteDevice* obj)
}
// static RemoteDevice* GetRemoteDevice(Connection conn);
bool
RemoteDevice::Authenticate()
status_t
RemoteDevice::Connect()
{
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 & ACL_PTYPE_MASK;
BMessage request(BT_MSG_HANDLE_SIMPLE_REQUEST);
BMessage reply;
BMessage request(BT_REQ_CREATE_CONN);
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));
bdaddr_t bdaddr = GetBluetoothAddress();
request.AddData("bdaddr", B_ANY_TYPE, &bdaddr, sizeof(bdaddr_t));
request.AddInt16("eventExpected", HCI_EVENT_LINK_KEY_REQ);
request.AddInt16("eventExpected", HCI_EVENT_ROLE_CHANGE);
request.AddInt16("eventExpected", HCI_EVENT_CONN_COMPLETE);
uint16 packetType;
fDiscovererLocalDevice->GetProperty("packet_type", (uint32*)&packetType);
request.AddUInt16("packet type", packetType);
if (fMessenger->SendMessage(&request, &reply) == B_OK)
reply.FindInt8("status", &btStatus);
request.AddUInt8("pscan_rep_mode", fPageRepetitionMode);
request.AddUInt8("pscan_mode", fScanMode);
request.AddUInt16("clock_offset", fClockOffset);
if (btStatus != BT_OK)
return false;
reply.FindInt16("handle", (int16*)&fHandle);
BluetoothCommand<typed_command(hci_cp_auth_requested)> authRequest(OGF_LINK_CONTROL,
OCF_AUTH_REQUESTED);
authRequest->handle = fHandle;
BMessage authRequestMsg(BT_MSG_HANDLE_SIMPLE_REQUEST);
BMessage authReply;
authRequestMsg.AddInt32("hci_id", fDiscovererLocalDevice->ID());
authRequestMsg.AddData("raw command", B_ANY_TYPE, authRequest.Data(), authRequest.Size());
authRequestMsg.AddInt16("eventExpected", HCI_EVENT_CMD_STATUS);
authRequestMsg.AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL, OCF_AUTH_REQUESTED));
authRequestMsg.AddInt16("eventExpected", HCI_EVENT_AUTH_COMPLETE);
int8 authStatus = BT_ERROR;
if (fMessenger->SendMessage(&authRequestMsg, &authReply) == B_OK)
authReply.FindInt8("status", &authStatus);
if (authStatus == BT_OK)
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;
}
uint8 roleSwitch;
fDiscovererLocalDevice->GetProperty("role_switch_capable", (uint32*)&roleSwitch);
request.AddUInt8("role_switch", roleSwitch);
if (fMessenger->SendMessage(&request) == B_OK)
return B_OK;
return B_ERROR;
}
status_t
RemoteDevice::CancelConnection()
{
CALLED();
BMessage request(BT_REQ_CANCEL_CONN);
request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
bdaddr_t bdaddr = GetBluetoothAddress();
request.AddData("bdaddr", B_ANY_TYPE, &bdaddr, sizeof(bdaddr_t));
if (fMessenger->SendMessage(&request) == B_OK)
return B_OK;
return B_ERROR;
}
status_t
RemoteDevice::Disconnect()
{
CALLED();
BMessage request(BT_REQ_DISCONNECT);
request.AddInt32("hci_id", fDiscovererLocalDevice->ID());
request.AddUInt16("handle", fHandle);
request.AddUInt8("reason", BT_REMOTE_USER_ENDED_CONNECTION);
if (fMessenger->SendMessage(&request) == B_OK)
return B_OK;
return B_ERROR;
}
// static RemoteDevice* GetRemoteDevice(Connection conn);
// bool Authorize(Connection conn);
// bool Encrypt(Connection conn, bool on);
@@ -309,8 +270,7 @@ RemoteDevice::SetLocalDeviceOwner(LocalDevice* ld)
RemoteDevice::RemoteDevice(const bdaddr_t address, uint8 record[3])
:
BluetoothDevice(),
fDiscovererLocalDevice(NULL),
fHandle(invalidConnectionHandle)
fDiscovererLocalDevice(NULL)
{
CALLED();
fBdaddr = address;
@@ -322,8 +282,7 @@ RemoteDevice::RemoteDevice(const bdaddr_t address, uint8 record[3])
RemoteDevice::RemoteDevice(const BString& address)
:
BluetoothDevice(),
fDiscovererLocalDevice(NULL),
fHandle(invalidConnectionHandle)
fDiscovererLocalDevice(NULL)
{
CALLED();
fBdaddr = bdaddrUtils::FromString((const char*)address.String());
@@ -94,6 +94,27 @@ BluetoothWindow::BluetoothWindow(BRect frame)
.AddGlue()
.End()
.End();
StartWatchingServer();
be_roster->StartWatching(this, B_REQUEST_LAUNCHED);
}
void
BluetoothWindow::StartWatchingServer()
{
BMessage watchReq = BMessage(BT_START_WATCHING_CONNECTIONS);
watchReq.AddMessenger("messenger", BMessenger(this));
BMessenger(BLUETOOTH_SIGNATURE).SendMessage(&watchReq);
}
void
BluetoothWindow::StopWatchingServer()
{
BMessage stopWatchReq = BMessage(BT_STOP_WATCHING_CONNECTIONS);
stopWatchReq.AddMessenger("messenger", BMessenger(this));
BMessenger(BLUETOOTH_SIGNATURE).SendMessage(&stopWatchReq);
}
@@ -102,6 +123,24 @@ BluetoothWindow::MessageReceived(BMessage* message)
{
//message->PrintToStream();
switch (message->what) {
case BT_MSG_CONN_COMPLETED:
case BT_MSG_CONN_FAILED:
case BT_MSG_DISCONN_COMPLETED:
{
fRemoteDevices->MessageReceived(message);
break;
}
case B_SOME_APP_LAUNCHED:
{
const char* signature;
if (message->FindString("signature", &signature) == B_OK
&& strcmp(signature, BLUETOOTH_SIGNATURE) == 0)
StartWatchingServer();
break;
}
case kMsgSetConnectionPolicy:
case kMsgSetDeviceClass:
case kMsgSetFriendlyName:
@@ -139,9 +178,11 @@ BluetoothWindow::MessageReceived(BMessage* message)
case kMsgAddToRemoteList:
PostMessage(message, fRemoteDevices);
break;
case kMsgRefresh:
fSettingsView->MessageReceived(message);
break;
case B_ABOUT_REQUESTED:
be_app->PostMessage(message);
break;
@@ -155,6 +196,7 @@ BluetoothWindow::MessageReceived(BMessage* message)
bool
BluetoothWindow::QuitRequested()
{
StopWatchingServer();
be_app->PostMessage(B_QUIT_REQUESTED);
return true;
}
@@ -24,6 +24,9 @@ public:
void MessageReceived(BMessage *message);
private:
void StartWatchingServer();
void StopWatchingServer();
RemoteDevicesView* fRemoteDevices;
BButton* fDefaultsButton;
BButton* fRevertButton;
+16 -1
View File
@@ -20,7 +20,8 @@ namespace Bluetooth {
DeviceListItem::DeviceListItem(RemoteDevice* bDevice)
:
BListItem(),
fDevice(bDevice)
fDevice(bDevice),
fConnState(RD_DISCONNECTED)
{
fAddress = bDevice->GetBluetoothAddress();
fClass = bDevice->GetDeviceClass();
@@ -158,4 +159,18 @@ DeviceListItem::Device() const
}
void
DeviceListItem::SetConnState(DeviceConnState connState)
{
fConnState = connState;
}
DeviceConnState
DeviceListItem::GetConnState()
{
return fConnState;
}
}
+21 -9
View File
@@ -12,6 +12,14 @@
namespace Bluetooth {
enum DeviceConnState {
RD_CONNECTED,
RD_CONNECTING,
RD_DISCONNECTED
};
class DeviceListItem : public BListItem
{
public:
@@ -19,20 +27,24 @@ class DeviceListItem : public BListItem
~DeviceListItem();
void DrawItem(BView*, BRect, bool = false);
void Update(BView* owner, const BFont* font);
void DrawItem(BView*, BRect, bool = false);
void Update(BView* owner, const BFont* font);
static int Compare(const void* firstArg, const void* secondArg);
void SetDevice(RemoteDevice* bDevice);
RemoteDevice* Device() const;
static int Compare(const void* firstArg, const void* secondArg);
void SetDevice(RemoteDevice* bDevice);
RemoteDevice* Device() const;
void SetConnState(DeviceConnState connState);
DeviceConnState GetConnState();
private:
RemoteDevice* fDevice;
bdaddr_t fAddress;
DeviceClass fClass;
BString fName;
int32 fRSSI;
bdaddr_t fAddress;
DeviceClass fClass;
BString fName;
int32 fRSSI;
DeviceConnState fConnState;
};
}
+101 -10
View File
@@ -26,7 +26,6 @@
#include "BluetoothWindow.h"
#include "defs.h"
#include "DeviceListItem.h"
#include "InquiryPanel.h"
#include "RemoteDevicesView.h"
@@ -38,10 +37,30 @@ static const uint32 kMsgAddDevices = 'ddDv';
static const uint32 kMsgRemoveDevice = 'rmDv';
static const uint32 kMsgPairDevice = 'trDv';
static const uint32 kMsgDisconnectDevice = 'dsDv';
static const uint32 kMsgConnComplete = 'cmDv';
static const uint32 kMsgCancelConn = 'cnDv';
//static const uint32 kMsgBlockDevice = 'blDv';
//static const uint32 kMsgRefreshDevices = 'rfDv';
using namespace Bluetooth;
class DeviceListView : public BListView
{
public:
DeviceListView(const char* name, list_view_type type)
:
BListView(name, type)
{
}
void
SelectionChanged()
{
RemoteDevicesView* remoteDevicesView = static_cast<RemoteDevicesView*>(Parent()->Parent());
remoteDevicesView->DeviceSelected();
}
};
RemoteDevicesView::RemoteDevicesView(const char* name, uint32 flags)
: BView(name, flags)
@@ -54,9 +73,16 @@ RemoteDevicesView::RemoteDevicesView(const char* name, uint32 flags)
pairButton = new BButton("pair", B_TRANSLATE("Pair" B_UTF8_ELLIPSIS),
new BMessage(kMsgPairDevice));
pairButton->SetEnabled(false);
disconnectButton = new BButton("disconnect", B_TRANSLATE("Disconnect"),
new BMessage(kMsgDisconnectDevice));
disconnectButton->SetEnabled(false);
cancelButton = new BButton("cancel", B_TRANSLATE("Cancel"),
new BMessage(kMsgCancelConn));
cancelButton->SetEnabled(false);
/*
blockButton = new BButton("block", B_TRANSLATE("As blocked"),
new BMessage(kMsgBlockDevice));
@@ -66,7 +92,7 @@ RemoteDevicesView::RemoteDevicesView(const char* name, uint32 flags)
new BMessage(kMsgRefreshDevices));
*/
// Set up device list
fDeviceList = new BListView("DeviceList", B_SINGLE_SELECTION_LIST);
fDeviceList = new DeviceListView("DeviceList", B_SINGLE_SELECTION_LIST);
fScrollView = new BScrollView("ScrollView", fDeviceList, 0, false, true);
@@ -83,18 +109,16 @@ RemoteDevicesView::RemoteDevicesView(const char* name, uint32 flags)
// .AddGlue()
.Add(pairButton)
.Add(disconnectButton)
.Add(cancelButton)
// .Add(blockButton)
.AddGlue()
.End()
.End();
fDeviceList->SetSelectionMessage(NULL);
}
RemoteDevicesView::~RemoteDevicesView(void)
{
}
@@ -106,6 +130,7 @@ RemoteDevicesView::AttachedToWindow(void)
removeButton->SetTarget(this);
pairButton->SetTarget(this);
disconnectButton->SetTarget(this);
cancelButton->SetTarget(this);
// blockButton->SetTarget(this);
// availButton->SetTarget(this);
@@ -163,14 +188,34 @@ RemoteDevicesView::MessageReceived(BMessage* message)
if (device == NULL)
break;
RemoteDevice* remote = dynamic_cast<RemoteDevice*>(device->Device());
if (remote == NULL)
break;
remote->Authenticate();
fConnectingDeviceItem = device;
fConnectingDeviceItem->SetConnState(RD_CONNECTING);
DeviceSelected();
remote->Connect();
break;
}
case BT_MSG_CONN_COMPLETED:
{
uint8 status;
message->FindUInt8("status", &status);
if (status == BT_OK)
fConnectingDeviceItem->SetConnState(RD_CONNECTED);
else
fConnectingDeviceItem->SetConnState(RD_DISCONNECTED);
DeviceSelected();
fConnectingDeviceItem = NULL;
break;
}
case kMsgDisconnectDevice:
{
DeviceListItem* device = static_cast<DeviceListItem*>(fDeviceList
@@ -181,12 +226,28 @@ RemoteDevicesView::MessageReceived(BMessage* message)
RemoteDevice* remote = dynamic_cast<RemoteDevice*>(device->Device());
if (remote == NULL)
break;
fConnectingDeviceItem = device;
remote->Disconnect();
break;
}
case BT_MSG_CONN_FAILED:
case BT_MSG_DISCONN_COMPLETED:
{
fConnectingDeviceItem->SetConnState(RD_DISCONNECTED);
DeviceSelected();
fConnectingDeviceItem = NULL;
break;
}
case kMsgCancelConn:
{
fConnectingDeviceItem->Device()->CancelConnection();
break;
}
default:
BView::MessageReceived(message);
break;
@@ -194,13 +255,43 @@ RemoteDevicesView::MessageReceived(BMessage* message)
}
void RemoteDevicesView::LoadSettings(void)
void
RemoteDevicesView::DeviceSelected()
{
DeviceListItem* device = static_cast<DeviceListItem*>(fDeviceList
->ItemAt(fDeviceList->CurrentSelection(0)));
if (device == NULL)
return;
switch (device->GetConnState()) {
case RD_CONNECTING:
pairButton->SetEnabled(false);
disconnectButton->SetEnabled(false);
cancelButton->SetEnabled(true);
break;
case RD_CONNECTED:
pairButton->SetEnabled(false);
disconnectButton->SetEnabled(true);
cancelButton->SetEnabled(false);
break;
case RD_DISCONNECTED:
pairButton->SetEnabled(true);
disconnectButton->SetEnabled(false);
cancelButton->SetEnabled(false);
break;
}
}
void
RemoteDevicesView::LoadSettings(void)
{
}
bool RemoteDevicesView::IsDefaultable(void)
bool
RemoteDevicesView::IsDefaultable(void)
{
return true;
}
+10 -2
View File
@@ -21,6 +21,12 @@
#include <StringView.h>
#include <Invoker.h>
#include "DeviceListItem.h"
using namespace Bluetooth;
class DeviceListView;
class RemoteDevicesView : public BView
{
@@ -30,6 +36,7 @@ public:
void AttachedToWindow(void);
void MessageReceived(BMessage *msg);
void DeviceSelected();
void LoadSettings(void);
bool IsDefaultable(void);
@@ -43,12 +50,13 @@ protected:
BButton* removeButton;
BButton* pairButton;
BButton* disconnectButton;
BButton* cancelButton;
// BButton* blockButton;
// BButton* availButton;
BListView* fDeviceList;
DeviceListView* fDeviceList;
BScrollView* fScrollView;
DeviceListItem* fConnectingDeviceItem;
};
#endif
+64 -3
View File
@@ -63,6 +63,7 @@ BluetoothServer::BluetoothServer()
{
fDeviceManager = new DeviceManager();
fLocalDevicesList.MakeEmpty();
fWatchersList.MakeEmpty();
fEventListener2 = new BluetoothPortListener(BT_USERLAND_PORT_NAME,
(BluetoothPortListener::port_listener_func)&DispatchEvent);
@@ -129,8 +130,7 @@ void BluetoothServer::MessageReceived(BMessage* message)
BMessage reply;
status_t status = B_WOULD_BLOCK; // mark somehow to do not reply anything
switch (message->what)
{
switch (message->what) {
case BT_MSG_ADD_DEVICE:
{
BString str;
@@ -198,13 +198,59 @@ void BluetoothServer::MessageReceived(BMessage* message)
return;
}
case BT_REQ_CREATE_CONN:
{
LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message);
if (lDeviceImpl == NULL)
break;
lDeviceImpl->CreateConnection(message);
break;
}
case BT_REQ_CANCEL_CONN:
{
LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message);
if (lDeviceImpl == NULL)
break;
lDeviceImpl->CancelConnection(message);
break;
}
case BT_REQ_DISCONNECT:
{
LocalDeviceImpl* lDeviceImpl = LocateDelegateFromMessage(message);
if (lDeviceImpl == NULL)
break;
lDeviceImpl->Disconnect(message);
break;
}
case BT_START_WATCHING_CONNECTIONS:
{
BMessenger* messenger = new BMessenger();
if (message->FindMessenger("messenger", messenger) == B_OK)
fWatchersList.AddItem(messenger);
break;
}
case BT_STOP_WATCHING_CONNECTIONS:
{
BMessenger* messenger = new BMessenger();
if (message->FindMessenger("messenger", messenger) == B_OK)
fWatchersList.RemoveItem(messenger);
break;
}
default:
BApplication::MessageReceived(message);
break;
}
// Can we reply right now?
// TOD: review this condition
// TODO: review this condition
if (status != B_WOULD_BLOCK) {
reply.AddInt32("status", status);
message->SendReply(&reply);
@@ -214,6 +260,21 @@ void BluetoothServer::MessageReceived(BMessage* message)
}
void
BluetoothServer::NotifyWatchers(BMessage* notice)
{
for (int32 i = 0; i < fWatchersList.CountItems(); i++) {
BMessenger* messenger = fWatchersList.ItemAt(i);
if (!messenger->IsValid()) {
fWatchersList.RemoveItemAt(i);
i--;
continue;
}
messenger->SendMessage(notice);
}
}
#if 0
#pragma mark -
#endif
+3
View File
@@ -37,6 +37,7 @@ typedef enum {
#define BLACKBOARD_LD(X) (BLACKBOARD_END+X-HCI_DEVICE_INDEX_OFFSET)
typedef BObjectList<LocalDeviceImpl> LocalDevicesList;
typedef BObjectList<BMessenger> WatchersList;
typedef PortListener<struct hci_event_header,
HCI_MAX_EVENT_SIZE, // Event Body can hold max 255 + 2 header
24 // Some devices have sent chunks of 24 events(inquiry result)
@@ -65,6 +66,7 @@ public:
status_t HandleGetProperty(BMessage* message, BMessage* reply);
status_t HandleSimpleRequest(BMessage* message, BMessage* reply);
void NotifyWatchers(BMessage* notice);
LocalDeviceImpl* LocateLocalDeviceImpl(hci_id hid);
@@ -78,6 +80,7 @@ private:
void _RemoveDeskbarIcon();
LocalDevicesList fLocalDevicesList;
WatchersList fWatchersList;
// Notification system
+212 -75
View File
@@ -126,14 +126,16 @@ LocalDeviceImpl::HandleUnexpectedEvent(struct hci_event_header* event)
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
// should belong to a request? can be sporadic or initiated by us?
DisconnectionComplete(
JumpEventHeader
<struct hci_ev_disconnection_complete_reply>(event),
NULL);
JumpEventHeader<struct hci_ev_disconnection_complete_reply>(event));
break;
// TODO: feedback unexpected not handled
case HCI_EVENT_CONN_COMPLETE:
ConnectionComplete(JumpEventHeader<struct hci_ev_conn_complete>(event));
break;
default:
TRACE_BT("Couldn't handle the unexpected event with code: %x", event->ecode);
break;
}
}
@@ -153,18 +155,6 @@ LocalDeviceImpl::HandleExpectedRequest(struct hci_event_header* event,
InquiryResult(JumpEventHeader<uint8>(event), request);
break;
case HCI_EVENT_CONN_COMPLETE:
ConnectionComplete(
JumpEventHeader<struct hci_ev_conn_complete>(event), request);
break;
case HCI_EVENT_DISCONNECTION_COMPLETE:
// should belong to a request? can be sporadic or initiated by us?
DisconnectionComplete(
JumpEventHeader<struct hci_ev_disconnection_complete_reply>
(event), request);
break;
case HCI_EVENT_AUTH_COMPLETE:
AuthComplete(JumpEventHeader<struct hci_ev_auth_complete>(event), request);
break;
@@ -759,6 +749,7 @@ LocalDeviceImpl::CommandComplete(struct hci_ev_cmd_complete* event,
}
// place here all CC that just replies a uint8 status
case PACK_OPCODE(OGF_LINK_CONTROL, OCF_CREATE_CONN_CANCEL):
case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_RESET):
case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_SCAN_ENABLE):
case PACK_OPCODE(OGF_CONTROL_BASEBAND, OCF_WRITE_CLASS_OF_DEV):
@@ -826,8 +817,10 @@ LocalDeviceImpl::CommandStatus(struct hci_ev_cmd_status* event,
TRACE_BT("LocalDeviceImpl: Command Status for remote friendly name %x\n",
event->status);
reply.AddInt8("status", event->status);
request->SendReply(&reply);
if (event->status != BT_OK) {
reply.AddInt8("status", event->status);
request->SendReply(&reply);
}
// printf("Sending reply... %ld\n", status);
// debug reply.PrintToStream();
@@ -839,20 +832,48 @@ LocalDeviceImpl::CommandStatus(struct hci_ev_cmd_status* event,
{
TRACE_BT("LocalDeviceImpl: Command Status for create connection %x\n", event->status);
ClearWantedEvent(request, HCI_EVENT_CMD_STATUS, opcodeExpected);
if (event->status != BT_OK) {
switch (event->status) {
case BT_OK:
ClearWantedEvent(request, HCI_EVENT_CMD_STATUS, opcodeExpected);
break;
case BT_ACL_CONNECTION_EXISTS:
reply.what = BT_MSG_CONN_COMPLETED;
reply.AddUInt8("status", BT_OK);
request->SendReply(&reply);
reply.AddInt8("status", event->status);
request->SendReply(&reply);
// printf("Sending reply... %ld\n", status);
// debug reply.PrintToStream();
ClearWantedEvent(request);
break;
default:
reply.what = BT_MSG_CONN_FAILED;
reply.AddUInt8("status", event->status);
request->SendReply(&reply);
ClearWantedEvent(request);
break;
}
}
break;
case PACK_OPCODE(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ):
case PACK_OPCODE(OGF_LINK_CONTROL, OCF_DISCONNECT):
{
TRACE_BT("LocalDeviceImpl: Command Status for disconnect %x\n", event->status);
ClearWantedEvent(request, HCI_EVENT_CMD_STATUS, opcodeExpected);
if (event->status == BT_NO_CONNECTION) {
reply.what = BT_MSG_DISCONN_COMPLETED;
reply.AddInt8("status", event->status);
((BluetoothServer*)be_app)->NotifyWatchers(&reply);
ClearWantedEvent(request);
}
}
break;
case PACK_OPCODE(OGF_LINK_CONTROL, OCF_ACCEPT_CONN_REQ):
{
TRACE_BT("LocalDeviceImpl: Command Status for accept connection request %x\n",
event->status);
@@ -1171,7 +1192,6 @@ LocalDeviceImpl::ConnectionRequest(struct hci_ev_conn_request* event,
newrequest->AddInt16("eventExpected", HCI_EVENT_LINK_KEY_REQ);
newrequest->AddInt16("eventExpected", HCI_EVENT_ROLE_CHANGE);
newrequest->AddInt16("eventExpected", HCI_EVENT_CONN_COMPLETE);
#if 0
newrequest->AddInt16("eventExpected", HCI_EVENT_MAX_SLOT_CHANGE);
@@ -1191,10 +1211,145 @@ LocalDeviceImpl::ConnectionRequest(struct hci_ev_conn_request* event,
void
LocalDeviceImpl::ConnectionComplete(struct hci_ev_conn_complete* event,
BMessage* request)
LocalDeviceImpl::CreateConnection(BMessage* message)
{
const bdaddr_t* bdaddr;
ssize_t addr_size;
message->FindData("bdaddr", B_ANY_TYPE, (const void**)&bdaddr, &addr_size);
TRACE_BT("LocalDeviceImpl: Create Connection to %s...\n",
bdaddrUtils::ToString(*bdaddr).String());
BluetoothCommand<typed_command(hci_cp_create_conn)>
command(OGF_LINK_CONTROL, OCF_CREATE_CONN);
command->bdaddr = *bdaddr;
message->FindUInt16("packet type", &command->pkt_type);
command->pkt_type &= ACL_PTYPE_MASK;
message->FindUInt8("pscan_rep_mode", &command->pscan_rep_mode);
message->FindUInt8("pscan_mode", &command->pscan_mode); // Reserved in spec 2.1
message->FindUInt16("clock_offset", &command->clock_offset);
command->clock_offset |= 0x8000; // substract!
message->FindUInt8("role_switch", &command->role_switch);
if (fHCIDelegate->IssueCommand(command.Data(), command.Size()) == B_ERROR) {
TRACE_BT("LocalDeviceImpl: Command issued error for %s\n", __FUNCTION__);
return;
} else {
TRACE_BT("LocalDeviceImpl: Command issued for %s\n", __FUNCTION__);
}
BMessage* newRequest = new BMessage;
newRequest->AddInt32("hci_id", fHCIDelegate->Id());
newRequest->AddInt16("eventExpected", HCI_EVENT_CMD_STATUS);
newRequest->AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL, OCF_CREATE_CONN));
newRequest->AddInt16("eventExpected", HCI_EVENT_LINK_KEY_REQ);
newRequest->AddInt16("eventExpected", HCI_EVENT_ROLE_CHANGE);
AddWantedEvent(newRequest);
}
void
LocalDeviceImpl::CancelConnection(BMessage* message)
{
const bdaddr_t* bdaddr;
ssize_t addr_size;
message->FindData("bdaddr", B_ANY_TYPE, (const void**)&bdaddr, &addr_size);
TRACE_BT("LocalDeviceImpl: Cancel Connection to %s...\n",
bdaddrUtils::ToString(*bdaddr).String());
BluetoothCommand<typed_command(hci_cp_create_conn_cancel)> command(OGF_LINK_CONTROL,
OCF_CREATE_CONN_CANCEL);
command->bdaddr = *bdaddr;
if (fHCIDelegate->IssueCommand(command.Data(), command.Size()) == B_ERROR) {
TRACE_BT("LocalDeviceImpl: Command issued error for %s\n", __FUNCTION__);
return;
} else {
TRACE_BT("LocalDeviceImpl: Command issued for %s\n", __FUNCTION__);
}
BMessage* newRequest = new BMessage(BT_MSG_HANDLE_SIMPLE_REQUEST);
newRequest->AddInt32("hci_id", fHCIDelegate->Id());
newRequest->AddInt16("eventExpected", HCI_EVENT_CMD_COMPLETE);
newRequest->AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL, OCF_CREATE_CONN_CANCEL));
AddWantedEvent(newRequest);
}
void
LocalDeviceImpl::Disconnect(BMessage* message)
{
TRACE_BT("LocalDeviceImpl: %s...\n", __FUNCTION__);
BluetoothCommand<typed_command(hci_disconnect)> command(OGF_LINK_CONTROL,
OCF_DISCONNECT);
message->FindUInt16("handle", &command->handle);
message->FindUInt8("reason", &command->reason);
if (fHCIDelegate->IssueCommand(command.Data(), command.Size()) == B_ERROR) {
TRACE_BT("LocalDeviceImpl: Command issued error for %s\n", __FUNCTION__);
return;
} else {
TRACE_BT("LocalDeviceImpl: Command issued for %s\n", __FUNCTION__);
}
BMessage* newRequest = new BMessage(BT_MSG_HANDLE_SIMPLE_REQUEST);
newRequest->AddInt32("hci_id", fHCIDelegate->Id());
newRequest->AddInt16("eventExpected", HCI_EVENT_CMD_STATUS);
newRequest->AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL, OCF_DISCONNECT));
AddWantedEvent(newRequest);
}
void
LocalDeviceImpl::Authenticate(uint16 handle)
{
TRACE_BT("LocalDeviceImpl: %s...\n", __FUNCTION__);
BluetoothCommand<typed_command(hci_cp_auth_requested)> command(OGF_LINK_CONTROL,
OCF_AUTH_REQUESTED);
command->handle = handle;
if (fHCIDelegate->IssueCommand(command.Data(), command.Size()) == B_ERROR) {
TRACE_BT("LocalDeviceImpl: Command issued error for %s\n", __FUNCTION__);
return;
} else {
TRACE_BT("LocalDeviceImpl: Command issued for %s\n", __FUNCTION__);
}
BMessage* newRequest = new BMessage();
newRequest->AddInt32("hci_id", fHCIDelegate->Id());
newRequest->AddInt16("eventExpected", HCI_EVENT_CMD_STATUS);
newRequest->AddInt16("opcodeExpected", PACK_OPCODE(OGF_LINK_CONTROL, OCF_AUTH_REQUESTED));
newRequest->AddInt16("eventExpected", HCI_EVENT_AUTH_COMPLETE);
AddWantedEvent(newRequest);
}
void
LocalDeviceImpl::ConnectionComplete(struct hci_ev_conn_complete* event)
{
BMessage reply;
reply.AddUInt8("status", event->status);
if (event->status == BT_OK) {
uint8 cod[3] = {0, 0, 0};
// TODO: Review, this rDevice is leaked
@@ -1206,59 +1361,38 @@ LocalDeviceImpl::ConnectionComplete(struct hci_ev_conn_complete* event,
bdaddrUtils::ToString(event->bdaddr).String(), event->handle,
event->link_type, event->encrypt_mode);
BMessage* newrequest = new BMessage;
newrequest->AddInt16("eventExpected", HCI_EVENT_IO_CAPABILITY_REQUEST);
newrequest->AddInt16("eventExpected", HCI_EVENT_IO_CAPABILITY_RESPONSE);
// this implies PAIRING complete
newrequest->AddInt16("eventExpected", HCI_EVENT_LINK_KEY_NOTIFY);
AddWantedEvent(newrequest);
Authenticate(event->handle);
reply.what = BT_MSG_CONN_COMPLETED;
} else {
TRACE_BT("LocalDeviceImpl: %s: failed with error %s\n", __FUNCTION__,
BluetoothError(event->status));
reply.what = BT_MSG_CONN_FAILED;
}
BMessage* newrequest = new BMessage;
newrequest->AddInt16("eventExpected", HCI_EVENT_IO_CAPABILITY_REQUEST);
newrequest->AddInt16("eventExpected", HCI_EVENT_IO_CAPABILITY_RESPONSE);
// this implies PAIRING complete
newrequest->AddInt16("eventExpected", HCI_EVENT_LINK_KEY_NOTIFY);
AddWantedEvent(newrequest);
// it was expected
if (request != NULL) {
BMessage reply;
reply.AddInt8("status", event->status);
if (event->status == BT_OK)
reply.AddInt16("handle", event->handle);
printf("%s: Sending reply...\n", __func__);
status_t status = request->SendReply(&reply);
if (status < B_OK)
printf("%s: Error sending reply!\n", __func__);
// debug reply.PrintToStream();
ClearWantedEvent(request, HCI_EVENT_CONN_COMPLETE);
}
((BluetoothServer*)be_app)->NotifyWatchers(&reply);
}
void
LocalDeviceImpl::DisconnectionComplete(
struct hci_ev_disconnection_complete_reply* event, BMessage* request)
LocalDeviceImpl::DisconnectionComplete(hci_ev_disconnection_complete_reply* event)
{
TRACE_BT("LocalDeviceImpl: %s: Handle=%#x, reason=%s status=%x\n", __FUNCTION__, event->handle,
BluetoothError(event->reason), event->status);
if (request != NULL) {
BMessage reply;
reply.AddInt8("status", event->status);
BMessage reply(BT_MSG_DISCONN_COMPLETED);
reply.AddInt8("status", event->status);
printf("%s: Sending reply...\n", __func__);
status_t status = request->SendReply(&reply);
if (status < B_OK)
printf("%s: Error sending reply!\n", __func__);
// debug reply.PrintToStream();
ClearWantedEvent(request);
}
((BluetoothServer*)be_app)->NotifyWatchers(&reply);
}
@@ -1275,6 +1409,7 @@ LocalDeviceImpl::PinCodeRequest(struct hci_ev_pin_code_req* event,
void
LocalDeviceImpl::RoleChange(hci_ev_role_change* event, BMessage* request)
{
// TODO: we shall update the RemoteDevice
TRACE_BT("LocalDeviceImpl: %s: Address %s role=%d status=%d\n", __FUNCTION__,
bdaddrUtils::ToString(event->bdaddr).String(), event->role, event->status);
}
@@ -1284,6 +1419,7 @@ void
LocalDeviceImpl::PageScanRepetitionModeChange(
struct hci_ev_page_scan_rep_mode_change* event, BMessage* request)
{
// TODO: we shall update the RemoteDevice
TRACE_BT("LocalDeviceImpl: %s: Address %s type=%d\n", __FUNCTION__,
bdaddrUtils::ToString(event->bdaddr).String(), event->page_scan_rep_mode);
}
@@ -1293,6 +1429,7 @@ void
LocalDeviceImpl::LinkKeyNotify(hci_ev_link_key_notify* event,
BMessage* request)
{
// TODO: Here we are supposed to save the link key in the Database
TRACE_BT("LocalDeviceImpl: %s: Address %s, key=%s, type=%d\n", __FUNCTION__,
bdaddrUtils::ToString(event->bdaddr).String(),
LinkKeyUtils::ToString(event->link_key).String(), event->key_type);
@@ -1309,7 +1446,7 @@ LocalDeviceImpl::LinkKeyRequested(struct hci_ev_link_key_req* keyRequested,
bdaddrUtils::ToString(keyRequested->bdaddr).String());
// TODO:
// Here we are suposed to check the BDADDR received, look into the server
// Here we are supposed to check the BDADDR received, look into the server
// (RemoteDevice Database) if we have any pas link key interchanged with
// the given address if we have we are to accept it will "Link key Request
// Reply". As we dont not have such database yet, we will always deny it
@@ -1404,7 +1541,7 @@ LocalDeviceImpl::IOCapabilityRequest(struct hci_ev_io_capability_request* event,
TRACE_BT("LocalDeviceImpl: IO Capability Request from %s...\n",
bdaddrUtils::ToString(event->bdaddr).String());
// this should be temporary, need to change this to HCI_IO_CAP_DISPLAY_YES_NO
// TODO: this should be temporary, need to change this to HCI_IO_CAP_DISPLAY_YES_NO
command = buildIOCapabilityRequestReply(event->bdaddr, HCI_IO_CAP_NO_INPUT_NO_OUTPUT,
HCI_OOB_DATA_NOT_PRESENT, HCI_AUTH_REQ_NO_MITM_NO_BOND, &size);
@@ -1484,8 +1621,8 @@ LocalDeviceImpl::SimplePairingComplete(struct hci_ev_simple_pairing_complete* ev
void
LocalDeviceImpl::AuthComplete(struct hci_ev_auth_complete* eventData, BMessage* request)
{
int16 handle = B_LENDIAN_TO_HOST_INT16(eventData->handle);
int8 status = eventData->status;
uint16 handle = B_LENDIAN_TO_HOST_INT16(eventData->handle);
uint8 status = eventData->status;
if (status == BT_OK) {
TRACE_BT("LocalDeviceImpl: Authentication Successful for handle %d\n", handle);
@@ -1496,8 +1633,8 @@ LocalDeviceImpl::AuthComplete(struct hci_ev_auth_complete* eventData, BMessage*
if (request != NULL) {
BMessage reply;
reply.AddInt8("status", status);
reply.AddInt16("handle", handle);
reply.AddUInt8("status", status);
reply.AddUInt16("handle", handle);
request->SendReply(&reply);
@@ -1542,4 +1679,4 @@ LocalDeviceImpl::ProcessSimpleRequest(BMessage* request)
}
return B_ERROR;
}
}
+11 -4
View File
@@ -31,7 +31,14 @@ public:
void HandleEvent(struct hci_event_header* event);
// Request handling
status_t ProcessSimpleRequest(BMessage* request);
status_t ProcessSimpleRequest(BMessage* request);
void NotifyWatchers(BMessage* notice);
// Connection
void CreateConnection(BMessage* message);
void CancelConnection(BMessage* message);
void Disconnect(BMessage* message);
private:
void HandleUnexpectedEvent(struct hci_event_header* event);
@@ -56,10 +63,10 @@ private:
remotename, BMessage* request);
// Connection
void ConnectionComplete(struct hci_ev_conn_complete* event, BMessage* request);
void Authenticate(uint16 handle);
void ConnectionComplete(struct hci_ev_conn_complete* event);
void ConnectionRequest(struct hci_ev_conn_request* event, BMessage* request);
void DisconnectionComplete(struct hci_ev_disconnection_complete_reply* event,
BMessage* request);
void DisconnectionComplete(struct hci_ev_disconnection_complete_reply* event);
// Pairing
void PinCodeRequest(struct hci_ev_pin_code_req* event, BMessage* request);