Bluetooth: Refactor l2cap into two protocols l2cap and bluetooth
This commits splits the address handling into bluetooth protocol and does the rest in l2cap. This is to allow for a different struct for sco and l2cap. Change-Id: I4c577691118613cd3be75eb7ef191fd2f07d742d Reviewed-on: https://review.haiku-os.org/c/haiku/+/11181 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
91994efedd
commit
94deadca17
@@ -163,6 +163,7 @@ SYSTEM_SERVERS += [ FFilterByBuildFeatures
|
||||
|
||||
# Bluetooth stack + drivers
|
||||
SYSTEM_NETWORK_PROTOCOLS +=
|
||||
bluetooth
|
||||
l2cap
|
||||
;
|
||||
SYSTEM_BT_STACK =
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _BTSCO_H_
|
||||
#define _BTSCO_H_
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
||||
struct sockaddr_sco {
|
||||
uint8 sco_len; /* total length */
|
||||
uint8 sco_family; /* address family */
|
||||
bdaddr_t sco_bdaddr; /* address */
|
||||
};
|
||||
|
||||
|
||||
#endif // _BTSCO_H_
|
||||
@@ -6,6 +6,7 @@
|
||||
#define _BTMODULES_H
|
||||
|
||||
|
||||
#define NET_BLUETOOTH_CORE_NAME "network/protocols/bluetooth/v1"
|
||||
#define NET_BLUETOOTH_L2CAP_NAME "network/protocols/l2cap/v1"
|
||||
|
||||
#endif // _BCOREDATA_H
|
||||
|
||||
@@ -4,7 +4,7 @@ SubInclude HAIKU_TOP src add-ons kernel network protocols icmp ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols icmp6 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols ipv4 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols ipv6 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols l2cap ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols tcp ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols udp ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols unix ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols bluetooth ;
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel network protocols bluetooth ;
|
||||
|
||||
UsePrivateKernelHeaders ;
|
||||
UsePrivateHeaders net bluetooth ;
|
||||
|
||||
KernelAddon bluetooth :
|
||||
bluetooth_address.cpp
|
||||
bluetooth.cpp
|
||||
;
|
||||
|
||||
SubInclude HAIKU_TOP src add-ons kernel network protocols bluetooth l2cap ;
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2026, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <net_protocol.h>
|
||||
#include <net_stack.h>
|
||||
|
||||
extern net_address_module_info gBluetoothAddressModule;
|
||||
net_stack_module_info* gStackModule;
|
||||
static net_domain* sDomain;
|
||||
|
||||
|
||||
status_t
|
||||
bluetooth_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
{
|
||||
status_t status = gStackModule->register_domain(AF_BLUETOOTH, "bluetooth", NULL,
|
||||
&gBluetoothAddressModule, &sDomain);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case B_MODULE_UNINIT:
|
||||
gStackModule->unregister_domain(sDomain);
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{NET_STACK_MODULE_NAME, (module_info**)&gStackModule},
|
||||
{}
|
||||
};
|
||||
|
||||
module_info* modules[] = {
|
||||
(module_info*)&gBluetoothAddressModule,
|
||||
NULL
|
||||
};
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Copyright 2006-2024, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
*/
|
||||
|
||||
|
||||
#include "bluetooth_address.h"
|
||||
|
||||
#include <net_datalink.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <net_protocol.h>
|
||||
#include <net_stack.h>
|
||||
|
||||
#include <NetUtilities.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <bluetooth/L2CAP/btL2CAP.h>
|
||||
#include <bluetooth/SCO/btSCO.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
||||
#include <btModules.h>
|
||||
|
||||
extern net_stack_module_info* gStackModule;
|
||||
extern status_t bluetooth_std_ops(int32 op, ...);
|
||||
|
||||
|
||||
static inline const bdaddr_t*
|
||||
get_bdaddr(const sockaddr* address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return NULL;
|
||||
if (address->sa_len == sizeof(sockaddr_l2cap))
|
||||
return &((const sockaddr_l2cap*)address)->l2cap_bdaddr;
|
||||
if (address->sa_len == sizeof(sockaddr_sco))
|
||||
return &((const sockaddr_sco*)address)->sco_bdaddr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline bdaddr_t*
|
||||
get_bdaddr(sockaddr* address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return NULL;
|
||||
if (address->sa_len == sizeof(sockaddr_l2cap))
|
||||
return &((sockaddr_l2cap*)address)->l2cap_bdaddr;
|
||||
if (address->sa_len == sizeof(sockaddr_sco))
|
||||
return &((sockaddr_sco*)address)->sco_bdaddr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bdaddrs_equal(const bdaddr_t& ba1, const bdaddr_t& ba2)
|
||||
{
|
||||
return memcmp(&ba1, &ba2, sizeof(bdaddr_t)) == 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bluetooth_is_empty_address(const sockaddr* address, bool checkPort)
|
||||
{
|
||||
if (address == NULL || address->sa_len == 0 || address->sa_family == AF_UNSPEC)
|
||||
return true;
|
||||
|
||||
const bdaddr_t* addr = get_bdaddr(address);
|
||||
if (addr == NULL)
|
||||
return true;
|
||||
|
||||
const bdaddr_t null_addr = {{0, 0, 0, 0, 0, 0}};
|
||||
bool emptyAddr = bdaddrs_equal(*addr, null_addr);
|
||||
if (!emptyAddr)
|
||||
return false;
|
||||
|
||||
if (checkPort && address->sa_len == sizeof(sockaddr_l2cap))
|
||||
return ((const sockaddr_l2cap*)address)->l2cap_psm == 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_copy_address(const sockaddr* from, sockaddr** to, bool replaceWithZeros = false,
|
||||
const sockaddr* mask = NULL)
|
||||
{
|
||||
if (replaceWithZeros) {
|
||||
*to = (sockaddr*)malloc(sizeof(sockaddr_l2cap));
|
||||
if (*to == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(*to, 0, sizeof(sockaddr_l2cap));
|
||||
(*to)->sa_family = AF_BLUETOOTH;
|
||||
(*to)->sa_len = sizeof(sockaddr_l2cap);
|
||||
} else {
|
||||
if (from == NULL)
|
||||
return B_OK;
|
||||
|
||||
if (from->sa_family != AF_BLUETOOTH)
|
||||
return B_MISMATCHED_VALUES;
|
||||
|
||||
*to = (sockaddr*)malloc(from->sa_len);
|
||||
if (*to == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memcpy(*to, from, from->sa_len);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bluetooth_equal_addresses(const sockaddr* a, const sockaddr* b)
|
||||
{
|
||||
if (a == NULL && b == NULL)
|
||||
return true;
|
||||
if (a != NULL && b == NULL)
|
||||
return bluetooth_is_empty_address(a, false);
|
||||
if (a == NULL && b != NULL)
|
||||
return bluetooth_is_empty_address(b, false);
|
||||
|
||||
const bdaddr_t* addr_a = get_bdaddr(a);
|
||||
const bdaddr_t* addr_b = get_bdaddr(b);
|
||||
if (addr_a == NULL || addr_b == NULL)
|
||||
return false;
|
||||
|
||||
return bdaddrs_equal(*addr_a, *addr_b);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bluetooth_equal_ports(const sockaddr* a, const sockaddr* b)
|
||||
{
|
||||
uint16 portA = (a != NULL && a->sa_len == sizeof(sockaddr_l2cap))
|
||||
? ((const sockaddr_l2cap*)a)->l2cap_psm
|
||||
: 0;
|
||||
uint16 portB = (b != NULL && b->sa_len == sizeof(sockaddr_l2cap))
|
||||
? ((const sockaddr_l2cap*)b)->l2cap_psm
|
||||
: 0;
|
||||
return portA == portB;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bluetooth_equal_addresses_and_ports(const sockaddr* a, const sockaddr* b)
|
||||
{
|
||||
if (a == NULL && b == NULL)
|
||||
return true;
|
||||
if (a != NULL && b == NULL)
|
||||
return bluetooth_is_empty_address(a, true);
|
||||
if (a == NULL && b != NULL)
|
||||
return bluetooth_is_empty_address(b, true);
|
||||
|
||||
if (!bluetooth_equal_addresses(a, b))
|
||||
return false;
|
||||
|
||||
return bluetooth_equal_ports(a, b);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bluetooth_equal_masked_addresses(const sockaddr* a, const sockaddr* b, const sockaddr* mask)
|
||||
{
|
||||
// no masks
|
||||
return bluetooth_equal_addresses(a, b);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bluetooth_is_same_family(const sockaddr* address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return false;
|
||||
|
||||
return address->sa_family == AF_BLUETOOTH;
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
bluetooth_first_mask_bit(const sockaddr* mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
bluetooth_check_mask(const sockaddr* mask)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_print_address(const sockaddr* address, char** _buffer, bool printPort)
|
||||
{
|
||||
if (_buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (address == NULL) {
|
||||
*_buffer = strdup("<none>");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
const bdaddr_t* addr = get_bdaddr(address);
|
||||
if (addr != NULL) {
|
||||
*_buffer = strdup("<invalid>");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
char tmp[32];
|
||||
if (printPort && address->sa_len == sizeof(sockaddr_l2cap)) {
|
||||
snprintf(tmp, sizeof(tmp), "%02X:%02X:%02X:%02X:%02X:%02X|%u", addr->b[5], addr->b[4],
|
||||
addr->b[3], addr->b[2], addr->b[1], addr->b[0],
|
||||
((const sockaddr_l2cap*)address)->l2cap_psm);
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "%02X:%02X:%02X:%02X:%02X:%02X", addr->b[5], addr->b[4],
|
||||
addr->b[3], addr->b[2], addr->b[1], addr->b[0]);
|
||||
}
|
||||
|
||||
*_buffer = strdup(tmp);
|
||||
return *_buffer ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_print_address_buffer(const sockaddr* address, char* buffer, size_t bufferSize,
|
||||
bool printPort)
|
||||
{
|
||||
if (address == NULL) {
|
||||
strlcpy(buffer, "<none>", bufferSize);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
const bdaddr_t* addr = get_bdaddr(address);
|
||||
if (addr == NULL) {
|
||||
strlcpy(buffer, "<invalid>", bufferSize);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
if (printPort && address->sa_len == sizeof(sockaddr_l2cap)) {
|
||||
snprintf(buffer, bufferSize, "%02X:%02X:%02X:%02X:%02X:%02X|%u", addr->b[5], addr->b[4],
|
||||
addr->b[3], addr->b[2], addr->b[1], addr->b[0],
|
||||
((const sockaddr_l2cap*)address)->l2cap_psm);
|
||||
} else {
|
||||
snprintf(buffer, bufferSize, "%02X:%02X:%02X:%02X:%02X:%02X", addr->b[5], addr->b[4],
|
||||
addr->b[3], addr->b[2], addr->b[1], addr->b[0]);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static uint16
|
||||
bluetooth_get_port(const sockaddr* address)
|
||||
{
|
||||
if (address != NULL && address->sa_len == sizeof(sockaddr_l2cap))
|
||||
return ((const sockaddr_l2cap*)address)->l2cap_psm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_set_port(sockaddr* address, uint16 port)
|
||||
{
|
||||
if (address != NULL && address->sa_len == sizeof(sockaddr_l2cap)) {
|
||||
((sockaddr_l2cap*)address)->l2cap_psm = port;
|
||||
return B_OK;
|
||||
}
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_set_to(sockaddr* address, const sockaddr* from)
|
||||
{
|
||||
if (address == NULL || from == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (from->sa_family != AF_BLUETOOTH)
|
||||
return B_MISMATCHED_VALUES;
|
||||
|
||||
if (address->sa_len == sizeof(sockaddr_l2cap) && from->sa_len == sizeof(sockaddr_l2cap)) {
|
||||
memcpy(address, from, sizeof(sockaddr_l2cap));
|
||||
return B_OK;
|
||||
}
|
||||
if (address->sa_len == sizeof(sockaddr_sco) && from->sa_len == sizeof(sockaddr_sco)) {
|
||||
memcpy(address, from, sizeof(sockaddr_sco));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_mask_address(const sockaddr* address, const sockaddr* mask, sockaddr* result)
|
||||
{
|
||||
// no masks
|
||||
return bluetooth_set_to(result, address);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_set_to_empty_address(sockaddr* address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
bdaddr_t* addr = get_bdaddr(address);
|
||||
if (addr != NULL) {
|
||||
memset(addr, 0, sizeof(bdaddr_t));
|
||||
if (address->sa_len == sizeof(sockaddr_l2cap))
|
||||
((sockaddr_l2cap*)address)->l2cap_psm = 0;
|
||||
return B_OK;
|
||||
}
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_set_to_defaults(sockaddr* _defaultMask, sockaddr* _defaultBroadcast,
|
||||
const sockaddr* _address, const sockaddr* _netmask)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (_defaultMask != NULL)
|
||||
error = bluetooth_set_to_empty_address(_defaultMask);
|
||||
if (error == B_OK && _defaultBroadcast != NULL)
|
||||
error = bluetooth_set_to_empty_address(_defaultBroadcast);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_update_to(sockaddr* address, const sockaddr* from)
|
||||
{
|
||||
if (address == NULL || from == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
bdaddr_t* toAddr = get_bdaddr(address);
|
||||
const bdaddr_t* fromAddr = get_bdaddr(from);
|
||||
if (toAddr != NULL && fromAddr != NULL) {
|
||||
const bdaddr_t null_addr = {{0, 0, 0, 0, 0, 0}};
|
||||
if (bdaddrs_equal(*toAddr, null_addr))
|
||||
*toAddr = *fromAddr;
|
||||
|
||||
if (address->sa_len == sizeof(sockaddr_l2cap) && from->sa_len == sizeof(sockaddr_l2cap)) {
|
||||
sockaddr_l2cap* l2cap_to = (sockaddr_l2cap*)address;
|
||||
const sockaddr_l2cap* l2cap_from = (const sockaddr_l2cap*)from;
|
||||
if (l2cap_to->l2cap_psm == 0)
|
||||
l2cap_to->l2cap_psm = l2cap_from->l2cap_psm;
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
bluetooth_hash_address(const sockaddr* address, bool includePort)
|
||||
{
|
||||
if (address == NULL || address->sa_len == 0)
|
||||
return 0;
|
||||
|
||||
const bdaddr_t* addr = get_bdaddr(address);
|
||||
if (addr == NULL)
|
||||
return 0;
|
||||
|
||||
uint32 hash = 0;
|
||||
for (size_t i = 0; i < sizeof(addr->b); i++)
|
||||
hash += addr->b[i] << (i * 2);
|
||||
|
||||
if (includePort && address->sa_len == sizeof(sockaddr_l2cap))
|
||||
hash += ((const sockaddr_l2cap*)address)->l2cap_psm;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
bluetooth_hash_address_pair(const sockaddr* ourAddress, const sockaddr* peerAddress)
|
||||
{
|
||||
return bluetooth_hash_address(ourAddress, true) * 17
|
||||
^ bluetooth_hash_address(peerAddress, true);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
bluetooth_checksum_address(Checksum* checksum, const sockaddr* address)
|
||||
{
|
||||
if (checksum == NULL || address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
const bdaddr_t* addr = get_bdaddr(address);
|
||||
if (addr == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
for (uint i = 0; i < sizeof(bdaddr_t); i++)
|
||||
(*checksum) << addr->b[i];
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
net_address_module_info gBluetoothAddressModule = {
|
||||
{
|
||||
NET_BLUETOOTH_CORE_NAME,
|
||||
0,
|
||||
bluetooth_std_ops
|
||||
},
|
||||
0,
|
||||
|
||||
bluetooth_copy_address,
|
||||
bluetooth_mask_address,
|
||||
bluetooth_equal_addresses,
|
||||
bluetooth_equal_ports,
|
||||
bluetooth_equal_addresses_and_ports,
|
||||
bluetooth_equal_masked_addresses,
|
||||
bluetooth_is_empty_address,
|
||||
bluetooth_is_same_family,
|
||||
bluetooth_first_mask_bit,
|
||||
bluetooth_check_mask,
|
||||
bluetooth_print_address,
|
||||
bluetooth_print_address_buffer,
|
||||
bluetooth_get_port,
|
||||
bluetooth_set_port,
|
||||
bluetooth_set_to,
|
||||
bluetooth_set_to_empty_address,
|
||||
bluetooth_set_to_defaults,
|
||||
bluetooth_update_to,
|
||||
bluetooth_hash_address,
|
||||
bluetooth_hash_address_pair,
|
||||
bluetooth_checksum_address,
|
||||
NULL // get_loopback_address
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2026, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BLUETOOTH_ADDRESS_H
|
||||
#define BLUETOOTH_ADDRESS_H
|
||||
|
||||
#include <net_datalink.h>
|
||||
|
||||
extern net_address_module_info gBluetoothAddressModule;
|
||||
|
||||
#endif // BLUETOOTH_ADDRESS_H
|
||||
+1
-2
@@ -1,11 +1,10 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel network protocols l2cap ;
|
||||
SubDir HAIKU_TOP src add-ons kernel network protocols bluetooth l2cap ;
|
||||
|
||||
UsePrivateKernelHeaders ;
|
||||
UsePrivateHeaders net bluetooth ;
|
||||
|
||||
KernelAddon l2cap :
|
||||
l2cap.cpp
|
||||
l2cap_address.cpp
|
||||
l2cap_command.cpp
|
||||
l2cap_signal.cpp
|
||||
L2capEndpoint.cpp
|
||||
+7
-4
@@ -11,7 +11,6 @@
|
||||
#include <NetBufferUtilities.h>
|
||||
|
||||
#include "L2capEndpointManager.h"
|
||||
#include "l2cap_address.h"
|
||||
#include "l2cap_signal.h"
|
||||
#include <btDebug.h>
|
||||
|
||||
@@ -275,7 +274,7 @@ L2capEndpoint::Connect(const struct sockaddr* _address)
|
||||
return EAFNOSUPPORT;
|
||||
|
||||
TRACE("l2cap: connect(\"%s\")\n",
|
||||
ConstSocketAddress(&gL2capAddressModule, _address).AsString().Data());
|
||||
ConstSocketAddress(AddressModule(), _address).AsString().Data());
|
||||
MutexLocker _(fLock);
|
||||
|
||||
status_t status;
|
||||
@@ -305,8 +304,9 @@ L2capEndpoint::Connect(const struct sockaddr* _address)
|
||||
if (hid <= 0)
|
||||
return ENETUNREACH;
|
||||
|
||||
TRACE("l2cap: %" B_PRId32 " for route %s\n", hid,
|
||||
bdaddrUtils::ToString(address->l2cap_bdaddr).String());
|
||||
TRACE("l2cap: %" B_PRId32 " for route %02X:%02X:%02X:%02X:%02X:%02X\n", hid,
|
||||
address->l2cap_bdaddr.b[5], address->l2cap_bdaddr.b[4], address->l2cap_bdaddr.b[3],
|
||||
address->l2cap_bdaddr.b[2], address->l2cap_bdaddr.b[1], address->l2cap_bdaddr.b[0]);
|
||||
|
||||
fConnection = btCoreData->ConnectionByDestination(
|
||||
address->l2cap_bdaddr, hid);
|
||||
@@ -867,5 +867,8 @@ L2capEndpoint::_MarkClosed()
|
||||
|
||||
fState = CLOSED;
|
||||
|
||||
socket->error = ENOTCONN;
|
||||
gSocketModule->notify(socket, B_SELECT_ERROR, ENOTCONN);
|
||||
|
||||
gL2capEndpointManager.UnbindFromChannel(this);
|
||||
}
|
||||
+6
-3
@@ -6,8 +6,7 @@
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
|
||||
#include <bluetooth/bdaddrUtils.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
L2capEndpointManager gL2capEndpointManager;
|
||||
|
||||
@@ -32,7 +31,8 @@ status_t
|
||||
L2capEndpointManager::Bind(L2capEndpoint* endpoint, const sockaddr_l2cap& address)
|
||||
{
|
||||
// TODO: Support binding to specific addresses?
|
||||
if (!Bluetooth::bdaddrUtils::Compare(address.l2cap_bdaddr, BDADDR_ANY))
|
||||
const bdaddr_t anyAddr = BDADDR_ANY;
|
||||
if (memcmp(&address.l2cap_bdaddr, &anyAddr, sizeof(bdaddr_t)) != 0)
|
||||
return EINVAL;
|
||||
|
||||
// PSM values must be odd.
|
||||
@@ -132,6 +132,9 @@ L2capEndpointManager::Disconnected(HciConnection* connection)
|
||||
|
||||
endpoint->fConnection = NULL;
|
||||
endpoint->fState = L2capEndpoint::CLOSED;
|
||||
|
||||
endpoint->socket->error = ENOTCONN;
|
||||
gSocketModule->notify(endpoint->socket, B_SELECT_ERROR, ENOTCONN);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-8
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "l2cap_address.h"
|
||||
#include "l2cap_command.h"
|
||||
#include "l2cap_internal.h"
|
||||
#include "l2cap_signal.h"
|
||||
@@ -32,8 +31,7 @@ bt_hci_module_info* btDevices;
|
||||
net_buffer_module_info* gBufferModule;
|
||||
net_stack_module_info* gStackModule;
|
||||
net_socket_module_info* gSocketModule;
|
||||
|
||||
static struct net_domain* sDomain;
|
||||
module_info* gBluetoothModuleInfo;
|
||||
|
||||
|
||||
net_protocol*
|
||||
@@ -196,7 +194,7 @@ l2cap_read_avail(net_protocol* protocol)
|
||||
struct net_domain*
|
||||
l2cap_get_domain(net_protocol* protocol)
|
||||
{
|
||||
return sDomain;
|
||||
return gStackModule->get_domain(AF_BLUETOOTH);
|
||||
}
|
||||
|
||||
|
||||
@@ -342,12 +340,13 @@ l2cap_std_ops(int32 op, ...)
|
||||
|
||||
error = gStackModule->register_domain_protocols(AF_BLUETOOTH,
|
||||
SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP,
|
||||
NET_BLUETOOTH_L2CAP_NAME, NULL);
|
||||
NET_BLUETOOTH_L2CAP_NAME,
|
||||
NULL);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
error = gStackModule->register_domain(AF_BLUETOOTH, "l2cap",
|
||||
&gL2CAPModule, &gL2capAddressModule, &sDomain);
|
||||
error = gStackModule->register_domain_receiving_protocol(AF_BLUETOOTH,
|
||||
BLUETOOTH_PROTO_L2CAP, NET_BLUETOOTH_L2CAP_NAME);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@@ -356,7 +355,6 @@ l2cap_std_ops(int32 op, ...)
|
||||
|
||||
case B_MODULE_UNINIT:
|
||||
gL2capEndpointManager.~L2capEndpointManager();
|
||||
gStackModule->unregister_domain(sDomain);
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
@@ -411,6 +409,7 @@ module_dependency module_dependencies[] = {
|
||||
{NET_SOCKET_MODULE_NAME, (module_info**)&gSocketModule},
|
||||
{BT_CORE_DATA_MODULE_NAME, (module_info**)&btCoreData},
|
||||
{BT_HCI_MODULE_NAME, (module_info**)&btDevices},
|
||||
{NET_BLUETOOTH_CORE_NAME, &gBluetoothModuleInfo},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2024, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
*/
|
||||
|
||||
|
||||
#include <net_datalink.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <NetUtilities.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <bluetooth/L2CAP/btL2CAP.h>
|
||||
|
||||
|
||||
static bool
|
||||
bdaddrs_equal(const bdaddr_t& ba1, const bdaddr_t& ba2)
|
||||
{
|
||||
return memcmp(&ba1, &ba2, sizeof(bdaddr_t)) == 0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_copy_address(const sockaddr *from, sockaddr **to,
|
||||
bool replaceWithZeros = false, const sockaddr *mask = NULL)
|
||||
{
|
||||
if (replaceWithZeros) {
|
||||
*to = (sockaddr *)malloc(sizeof(sockaddr_l2cap));
|
||||
if (*to == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(*to, 0, sizeof(sockaddr_l2cap));
|
||||
(*to)->sa_family = AF_BLUETOOTH;
|
||||
(*to)->sa_len = sizeof(sockaddr_l2cap);
|
||||
} else {
|
||||
if (from == NULL)
|
||||
return B_OK;
|
||||
if (from->sa_family != AF_BLUETOOTH)
|
||||
return B_MISMATCHED_VALUES;
|
||||
|
||||
*to = (sockaddr *)malloc(sizeof(sockaddr_l2cap));
|
||||
if (*to == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memcpy(*to, from, sizeof(sockaddr_l2cap));
|
||||
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
l2cap_is_empty_address(const sockaddr *_address, bool checkPort)
|
||||
{
|
||||
if (_address == NULL || _address->sa_len == 0
|
||||
|| _address->sa_family == AF_UNSPEC)
|
||||
return true;
|
||||
|
||||
const sockaddr_l2cap *address = (const sockaddr_l2cap *)_address;
|
||||
|
||||
return bdaddrs_equal(address->l2cap_bdaddr, BDADDR_NULL)
|
||||
&& (!checkPort || address->l2cap_psm == 0);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
l2cap_is_same_family(const sockaddr *address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return false;
|
||||
|
||||
return address->sa_family == AF_BLUETOOTH;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
l2cap_equal_addresses(const sockaddr *_a, const sockaddr *_b)
|
||||
{
|
||||
if (_a == NULL && _b == NULL)
|
||||
return true;
|
||||
if (_a != NULL && _b == NULL)
|
||||
return l2cap_is_empty_address(_a, false);
|
||||
if (_a == NULL && _b != NULL)
|
||||
return l2cap_is_empty_address(_b, false);
|
||||
|
||||
const sockaddr_l2cap *a = (const sockaddr_l2cap *)_a;
|
||||
const sockaddr_l2cap *b = (const sockaddr_l2cap *)_b;
|
||||
|
||||
return bdaddrs_equal(a->l2cap_bdaddr, b->l2cap_bdaddr);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
l2cap_equal_ports(const sockaddr *a, const sockaddr *b)
|
||||
{
|
||||
uint16 portA = a ? ((sockaddr_l2cap *)a)->l2cap_psm : 0;
|
||||
uint16 portB = b ? ((sockaddr_l2cap *)b)->l2cap_psm : 0;
|
||||
return portA == portB;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
l2cap_equal_addresses_and_ports(const sockaddr *_a, const sockaddr *_b)
|
||||
{
|
||||
if (_a == NULL && _b == NULL)
|
||||
return true;
|
||||
if (_a != NULL && _b == NULL)
|
||||
return l2cap_is_empty_address(_a, true);
|
||||
if (_a == NULL && _b != NULL)
|
||||
return l2cap_is_empty_address(_b, true);
|
||||
|
||||
const sockaddr_l2cap *a = (const sockaddr_l2cap *)_a;
|
||||
const sockaddr_l2cap *b = (const sockaddr_l2cap *)_b;
|
||||
|
||||
return bdaddrs_equal(a->l2cap_bdaddr, b->l2cap_bdaddr)
|
||||
&& (a->l2cap_psm == b->l2cap_psm);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
l2cap_equal_masked_addresses(const sockaddr *a, const sockaddr *b,
|
||||
const sockaddr *mask)
|
||||
{
|
||||
// no masks
|
||||
return l2cap_equal_addresses(a, b);
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
l2cap_first_mask_bit(const sockaddr *_mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
l2cap_check_mask(const sockaddr *_mask)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_print_address_buffer(const sockaddr *_address, char *buffer,
|
||||
size_t bufferSize, bool printPort)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
const sockaddr_l2cap *address = (const sockaddr_l2cap *)_address;
|
||||
if (address == NULL) {
|
||||
strlcpy(buffer, "<none>", bufferSize);
|
||||
} else {
|
||||
bdaddr_t addr = address->l2cap_bdaddr;
|
||||
if (printPort) {
|
||||
snprintf(buffer, bufferSize,
|
||||
"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X|%u", addr.b[0],
|
||||
addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5],
|
||||
address->l2cap_psm);
|
||||
} else {
|
||||
snprintf(buffer, bufferSize,
|
||||
"%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",addr.b[0],
|
||||
addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5]);
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_print_address(const sockaddr *_address, char **_buffer, bool printPort)
|
||||
{
|
||||
if (_buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
char tmp[32];
|
||||
l2cap_print_address_buffer(_address, tmp, sizeof(tmp), printPort);
|
||||
|
||||
*_buffer = strdup(tmp);
|
||||
if (*_buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static uint16
|
||||
l2cap_get_port(const sockaddr *address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return 0;
|
||||
|
||||
return ((sockaddr_l2cap *)address)->l2cap_psm;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_set_port(sockaddr *address, uint16 port)
|
||||
{
|
||||
if (address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
((sockaddr_l2cap *)address)->l2cap_psm = port;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_set_to(sockaddr *address, const sockaddr *from)
|
||||
{
|
||||
if (address == NULL || from == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (from->sa_family != AF_BLUETOOTH)
|
||||
return B_MISMATCHED_VALUES;
|
||||
|
||||
memcpy(address, from, sizeof(sockaddr_l2cap));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_mask_address(const sockaddr *address, const sockaddr *mask,
|
||||
sockaddr *result)
|
||||
{
|
||||
// no masks
|
||||
return l2cap_set_to(result, address);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_update_to(sockaddr *_address, const sockaddr *_from)
|
||||
{
|
||||
sockaddr_l2cap *address = (sockaddr_l2cap *)_address;
|
||||
const sockaddr_l2cap *from = (const sockaddr_l2cap *)_from;
|
||||
|
||||
if (address == NULL || from == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (from->l2cap_family != AF_BLUETOOTH)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
address->l2cap_family = AF_BLUETOOTH;
|
||||
address->l2cap_len = sizeof(sockaddr_l2cap);
|
||||
|
||||
if (bdaddrs_equal(address->l2cap_bdaddr, BDADDR_NULL))
|
||||
address->l2cap_bdaddr = from->l2cap_bdaddr;
|
||||
|
||||
if (address->l2cap_psm == 0)
|
||||
address->l2cap_psm = from->l2cap_psm;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_set_to_empty_address(sockaddr *address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
memset(address, 0, sizeof(sockaddr_l2cap));
|
||||
address->sa_len = sizeof(sockaddr_l2cap);
|
||||
address->sa_family = AF_BLUETOOTH;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
|
||||
const sockaddr *_address, const sockaddr *_mask)
|
||||
{
|
||||
if (_address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = B_OK;
|
||||
if (_defaultMask != NULL)
|
||||
error = l2cap_set_to_empty_address(_defaultMask);
|
||||
if (error == B_OK && _defaultBroadcast != NULL)
|
||||
error = l2cap_set_to_empty_address(_defaultBroadcast);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
l2cap_hash_address(const struct sockaddr* _address, bool includePort)
|
||||
{
|
||||
const sockaddr_l2cap* address = (const sockaddr_l2cap*)_address;
|
||||
if (address == NULL || address->l2cap_len == 0)
|
||||
return 0;
|
||||
|
||||
uint32 hash = 0;
|
||||
for (size_t i = 0; i < sizeof(address->l2cap_bdaddr.b); i++)
|
||||
hash += address->l2cap_bdaddr.b[i] << (i * 2);
|
||||
|
||||
if (includePort)
|
||||
hash += address->l2cap_psm;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
l2cap_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
|
||||
{
|
||||
return l2cap_hash_address(ourAddress, true) * 17
|
||||
+ l2cap_hash_address(peerAddress, true);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_checksum_address(struct Checksum *checksum, const sockaddr *address)
|
||||
{
|
||||
if (checksum == NULL || address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
for (uint i = 0; i < sizeof(bdaddr_t); i++)
|
||||
(*checksum) << ((sockaddr_l2cap*)address)->l2cap_bdaddr.b[i];
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
net_address_module_info gL2capAddressModule = {
|
||||
{
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS,
|
||||
l2cap_copy_address,
|
||||
l2cap_mask_address,
|
||||
l2cap_equal_addresses,
|
||||
l2cap_equal_ports,
|
||||
l2cap_equal_addresses_and_ports,
|
||||
l2cap_equal_masked_addresses,
|
||||
l2cap_is_empty_address,
|
||||
l2cap_is_same_family,
|
||||
l2cap_first_mask_bit,
|
||||
l2cap_check_mask,
|
||||
l2cap_print_address,
|
||||
l2cap_print_address_buffer,
|
||||
l2cap_get_port,
|
||||
l2cap_set_port,
|
||||
l2cap_set_to,
|
||||
l2cap_set_to_empty_address,
|
||||
l2cap_set_to_defaults,
|
||||
l2cap_update_to,
|
||||
l2cap_hash_address,
|
||||
l2cap_hash_address_pair,
|
||||
l2cap_checksum_address,
|
||||
NULL // get_loopback_address
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver-ruiz.dorantes_at_gmail.com
|
||||
*/
|
||||
#ifndef L2CAP_ADDRESS_H
|
||||
#define L2CAP_ADDRESS_H
|
||||
|
||||
extern struct net_address_module_info gL2capAddressModule;
|
||||
|
||||
#endif // L2CAP_ADDRESS_H
|
||||
Reference in New Issue
Block a user