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:
vighnesh-sawant
2026-07-15 21:21:12 +00:00
committed by waddlesplash
parent 91994efedd
commit 94deadca17
21 changed files with 555 additions and 393 deletions
+1
View File
@@ -163,6 +163,7 @@ SYSTEM_SERVERS += [ FFilterByBuildFeatures
# Bluetooth stack + drivers
SYSTEM_NETWORK_PROTOCOLS +=
bluetooth
l2cap
;
SYSTEM_BT_STACK =
+18
View File
@@ -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_
+1
View File
@@ -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
+1 -1
View File
@@ -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,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
@@ -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,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);
}
}
@@ -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