1c15ecd98SOliver Ruiz Dorantes /*
2*bb83316aSAugustin Cavalier * Copyright 2007, Oliver Ruiz Dorantes. All rights reserved.
3*bb83316aSAugustin Cavalier * Copyright 2024, Haiku, Inc. All rights reserved.
4*bb83316aSAugustin Cavalier * Distributed under the terms of the MIT License.
5c15ecd98SOliver Ruiz Dorantes */
6c15ecd98SOliver Ruiz Dorantes
73e248012SOliver Ruiz Dorantes #include <net_datalink.h>
83e248012SOliver Ruiz Dorantes #include <net_protocol.h>
93e248012SOliver Ruiz Dorantes #include <net_stack.h>
103e248012SOliver Ruiz Dorantes #include <NetBufferUtilities.h>
113e248012SOliver Ruiz Dorantes
123e248012SOliver Ruiz Dorantes #include <new>
133e248012SOliver Ruiz Dorantes
14c61dc72fSOliver Ruiz Dorantes #include "l2cap_address.h"
15*bb83316aSAugustin Cavalier #include "l2cap_command.h"
16b9b8d43cSOliver Ruiz Dorantes #include "l2cap_internal.h"
17*bb83316aSAugustin Cavalier #include "l2cap_signal.h"
18b9b8d43cSOliver Ruiz Dorantes #include "L2capEndpoint.h"
19*bb83316aSAugustin Cavalier #include "L2capEndpointManager.h"
20c61dc72fSOliver Ruiz Dorantes
21b9b8d43cSOliver Ruiz Dorantes #include <bluetooth/HCI/btHCI_acl.h>
22b9b8d43cSOliver Ruiz Dorantes #include <btModules.h>
233e248012SOliver Ruiz Dorantes #include <btDebug.h>
243e248012SOliver Ruiz Dorantes
253e248012SOliver Ruiz Dorantes
26c61dc72fSOliver Ruiz Dorantes extern net_protocol_module_info gL2CAPModule;
27c61dc72fSOliver Ruiz Dorantes
28b9b8d43cSOliver Ruiz Dorantes // module references
29b9b8d43cSOliver Ruiz Dorantes bluetooth_core_data_module_info* btCoreData;
30*bb83316aSAugustin Cavalier bt_hci_module_info* btDevices;
317cc7cadaSOliver Ruiz Dorantes
323e248012SOliver Ruiz Dorantes net_buffer_module_info* gBufferModule;
337cc7cadaSOliver Ruiz Dorantes net_stack_module_info* gStackModule;
34b9b8d43cSOliver Ruiz Dorantes net_socket_module_info* gSocketModule;
353e248012SOliver Ruiz Dorantes
36c61dc72fSOliver Ruiz Dorantes static struct net_domain* sDomain;
373e248012SOliver Ruiz Dorantes
38*bb83316aSAugustin Cavalier
393e248012SOliver Ruiz Dorantes net_protocol*
l2cap_init_protocol(net_socket * socket)403e248012SOliver Ruiz Dorantes l2cap_init_protocol(net_socket* socket)
413e248012SOliver Ruiz Dorantes {
42c58e1d7fSAlexander von Gluck IV CALLED();
43c58e1d7fSAlexander von Gluck IV
44b9b8d43cSOliver Ruiz Dorantes L2capEndpoint* protocol = new(std::nothrow) L2capEndpoint(socket);
453e248012SOliver Ruiz Dorantes if (protocol == NULL)
463e248012SOliver Ruiz Dorantes return NULL;
473e248012SOliver Ruiz Dorantes
483e248012SOliver Ruiz Dorantes return protocol;
493e248012SOliver Ruiz Dorantes }
503e248012SOliver Ruiz Dorantes
513e248012SOliver Ruiz Dorantes
523e248012SOliver Ruiz Dorantes status_t
l2cap_uninit_protocol(net_protocol * protocol)533e248012SOliver Ruiz Dorantes l2cap_uninit_protocol(net_protocol* protocol)
543e248012SOliver Ruiz Dorantes {
55c58e1d7fSAlexander von Gluck IV CALLED();
56c61dc72fSOliver Ruiz Dorantes
5731f87630SOliver Ruiz Dorantes L2capEndpoint* endpoint = static_cast<L2capEndpoint*>(protocol);
5831f87630SOliver Ruiz Dorantes delete endpoint;
5931f87630SOliver Ruiz Dorantes
603e248012SOliver Ruiz Dorantes return B_OK;
613e248012SOliver Ruiz Dorantes }
623e248012SOliver Ruiz Dorantes
633e248012SOliver Ruiz Dorantes
643e248012SOliver Ruiz Dorantes status_t
l2cap_open(net_protocol * protocol)653e248012SOliver Ruiz Dorantes l2cap_open(net_protocol* protocol)
663e248012SOliver Ruiz Dorantes {
67*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Open();
683e248012SOliver Ruiz Dorantes }
693e248012SOliver Ruiz Dorantes
703e248012SOliver Ruiz Dorantes
713e248012SOliver Ruiz Dorantes status_t
l2cap_close(net_protocol * protocol)723e248012SOliver Ruiz Dorantes l2cap_close(net_protocol* protocol)
733e248012SOliver Ruiz Dorantes {
74*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Close();
753e248012SOliver Ruiz Dorantes }
763e248012SOliver Ruiz Dorantes
773e248012SOliver Ruiz Dorantes
783e248012SOliver Ruiz Dorantes status_t
l2cap_free(net_protocol * protocol)793e248012SOliver Ruiz Dorantes l2cap_free(net_protocol* protocol)
803e248012SOliver Ruiz Dorantes {
81*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Free();
823e248012SOliver Ruiz Dorantes }
833e248012SOliver Ruiz Dorantes
843e248012SOliver Ruiz Dorantes
853e248012SOliver Ruiz Dorantes status_t
l2cap_connect(net_protocol * protocol,const struct sockaddr * address)863e248012SOliver Ruiz Dorantes l2cap_connect(net_protocol* protocol, const struct sockaddr* address)
873e248012SOliver Ruiz Dorantes {
88*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Connect(address);
893e248012SOliver Ruiz Dorantes }
903e248012SOliver Ruiz Dorantes
913e248012SOliver Ruiz Dorantes
923e248012SOliver Ruiz Dorantes status_t
l2cap_accept(net_protocol * protocol,struct net_socket ** _acceptedSocket)933e248012SOliver Ruiz Dorantes l2cap_accept(net_protocol* protocol, struct net_socket** _acceptedSocket)
943e248012SOliver Ruiz Dorantes {
95a58b3b32SOliver Ruiz Dorantes return ((L2capEndpoint*)protocol)->Accept(_acceptedSocket);
963e248012SOliver Ruiz Dorantes }
973e248012SOliver Ruiz Dorantes
983e248012SOliver Ruiz Dorantes
993e248012SOliver Ruiz Dorantes status_t
l2cap_control(net_protocol * protocol,int level,int option,void * value,size_t * _length)1003e248012SOliver Ruiz Dorantes l2cap_control(net_protocol* protocol, int level, int option, void* value,
1013e248012SOliver Ruiz Dorantes size_t* _length)
1023e248012SOliver Ruiz Dorantes {
103c58e1d7fSAlexander von Gluck IV CALLED();
104a5bf1237SOliver Ruiz Dorantes return EOPNOTSUPP;
1053e248012SOliver Ruiz Dorantes }
1063e248012SOliver Ruiz Dorantes
1073e248012SOliver Ruiz Dorantes
1083e248012SOliver Ruiz Dorantes status_t
l2cap_getsockopt(net_protocol * protocol,int level,int option,void * value,int * _length)1093e248012SOliver Ruiz Dorantes l2cap_getsockopt(net_protocol* protocol, int level, int option,
110*bb83316aSAugustin Cavalier void* value, int* _length)
1113e248012SOliver Ruiz Dorantes {
112c58e1d7fSAlexander von Gluck IV CALLED();
113*bb83316aSAugustin Cavalier return gSocketModule->get_option(protocol->socket, level, option, value,
114*bb83316aSAugustin Cavalier _length);
1153e248012SOliver Ruiz Dorantes }
1163e248012SOliver Ruiz Dorantes
1173e248012SOliver Ruiz Dorantes
1183e248012SOliver Ruiz Dorantes status_t
l2cap_setsockopt(net_protocol * protocol,int level,int option,const void * _value,int length)1193e248012SOliver Ruiz Dorantes l2cap_setsockopt(net_protocol* protocol, int level, int option,
120*bb83316aSAugustin Cavalier const void* _value, int length)
1213e248012SOliver Ruiz Dorantes {
122c58e1d7fSAlexander von Gluck IV CALLED();
123*bb83316aSAugustin Cavalier return gSocketModule->set_option(protocol->socket, level, option,
124*bb83316aSAugustin Cavalier _value, length);
1253e248012SOliver Ruiz Dorantes }
1263e248012SOliver Ruiz Dorantes
1273e248012SOliver Ruiz Dorantes
1283e248012SOliver Ruiz Dorantes status_t
l2cap_bind(net_protocol * protocol,const struct sockaddr * address)1293e248012SOliver Ruiz Dorantes l2cap_bind(net_protocol* protocol, const struct sockaddr* address)
1303e248012SOliver Ruiz Dorantes {
131b9b8d43cSOliver Ruiz Dorantes return ((L2capEndpoint*)protocol)->Bind(address);
1323e248012SOliver Ruiz Dorantes }
1333e248012SOliver Ruiz Dorantes
1343e248012SOliver Ruiz Dorantes
1353e248012SOliver Ruiz Dorantes status_t
l2cap_unbind(net_protocol * protocol,struct sockaddr * address)1363e248012SOliver Ruiz Dorantes l2cap_unbind(net_protocol* protocol, struct sockaddr* address)
1373e248012SOliver Ruiz Dorantes {
138*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Unbind();
1393e248012SOliver Ruiz Dorantes }
1403e248012SOliver Ruiz Dorantes
1413e248012SOliver Ruiz Dorantes
1423e248012SOliver Ruiz Dorantes status_t
l2cap_listen(net_protocol * protocol,int count)1433e248012SOliver Ruiz Dorantes l2cap_listen(net_protocol* protocol, int count)
1443e248012SOliver Ruiz Dorantes {
145b9b8d43cSOliver Ruiz Dorantes return ((L2capEndpoint*)protocol)->Listen(count);
1463e248012SOliver Ruiz Dorantes }
1473e248012SOliver Ruiz Dorantes
1483e248012SOliver Ruiz Dorantes
1493e248012SOliver Ruiz Dorantes status_t
l2cap_shutdown(net_protocol * protocol,int direction)1503e248012SOliver Ruiz Dorantes l2cap_shutdown(net_protocol* protocol, int direction)
1513e248012SOliver Ruiz Dorantes {
152*bb83316aSAugustin Cavalier if (direction != SHUT_RDWR)
1533e248012SOliver Ruiz Dorantes return EOPNOTSUPP;
154*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Shutdown();
1553e248012SOliver Ruiz Dorantes }
1563e248012SOliver Ruiz Dorantes
1573e248012SOliver Ruiz Dorantes
1583e248012SOliver Ruiz Dorantes status_t
l2cap_send_data(net_protocol * protocol,net_buffer * buffer)1593e248012SOliver Ruiz Dorantes l2cap_send_data(net_protocol* protocol, net_buffer* buffer)
1603e248012SOliver Ruiz Dorantes {
1618638173cSOliver Ruiz Dorantes return ((L2capEndpoint*)protocol)->SendData(buffer);
1623e248012SOliver Ruiz Dorantes }
1633e248012SOliver Ruiz Dorantes
1643e248012SOliver Ruiz Dorantes
1653e248012SOliver Ruiz Dorantes status_t
l2cap_send_routed_data(net_protocol * protocol,struct net_route * route,net_buffer * buffer)1663e248012SOliver Ruiz Dorantes l2cap_send_routed_data(net_protocol* protocol, struct net_route* route,
1673e248012SOliver Ruiz Dorantes net_buffer* buffer)
1683e248012SOliver Ruiz Dorantes {
169c58e1d7fSAlexander von Gluck IV CALLED();
170ef36d964SOliver Ruiz Dorantes return EOPNOTSUPP;
1713e248012SOliver Ruiz Dorantes }
1723e248012SOliver Ruiz Dorantes
1733e248012SOliver Ruiz Dorantes
1743e248012SOliver Ruiz Dorantes ssize_t
l2cap_send_avail(net_protocol * protocol)1753e248012SOliver Ruiz Dorantes l2cap_send_avail(net_protocol* protocol)
1763e248012SOliver Ruiz Dorantes {
177*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Sendable();
1783e248012SOliver Ruiz Dorantes }
1793e248012SOliver Ruiz Dorantes
1803e248012SOliver Ruiz Dorantes
1813e248012SOliver Ruiz Dorantes status_t
l2cap_read_data(net_protocol * protocol,size_t numBytes,uint32 flags,net_buffer ** _buffer)1823e248012SOliver Ruiz Dorantes l2cap_read_data(net_protocol* protocol, size_t numBytes, uint32 flags,
1833e248012SOliver Ruiz Dorantes net_buffer** _buffer)
1843e248012SOliver Ruiz Dorantes {
1857cc7cadaSOliver Ruiz Dorantes return ((L2capEndpoint*)protocol)->ReadData(numBytes, flags, _buffer);
1863e248012SOliver Ruiz Dorantes }
1873e248012SOliver Ruiz Dorantes
1883e248012SOliver Ruiz Dorantes
1893e248012SOliver Ruiz Dorantes ssize_t
l2cap_read_avail(net_protocol * protocol)1903e248012SOliver Ruiz Dorantes l2cap_read_avail(net_protocol* protocol)
1913e248012SOliver Ruiz Dorantes {
192*bb83316aSAugustin Cavalier return ((L2capEndpoint*)protocol)->Receivable();
1933e248012SOliver Ruiz Dorantes }
1943e248012SOliver Ruiz Dorantes
1953e248012SOliver Ruiz Dorantes
1963e248012SOliver Ruiz Dorantes struct net_domain*
l2cap_get_domain(net_protocol * protocol)1973e248012SOliver Ruiz Dorantes l2cap_get_domain(net_protocol* protocol)
1983e248012SOliver Ruiz Dorantes {
199c61dc72fSOliver Ruiz Dorantes return sDomain;
2003e248012SOliver Ruiz Dorantes }
2013e248012SOliver Ruiz Dorantes
2023e248012SOliver Ruiz Dorantes
2033e248012SOliver Ruiz Dorantes size_t
l2cap_get_mtu(net_protocol * protocol,const struct sockaddr * address)2043e248012SOliver Ruiz Dorantes l2cap_get_mtu(net_protocol* protocol, const struct sockaddr* address)
2053e248012SOliver Ruiz Dorantes {
206c58e1d7fSAlexander von Gluck IV CALLED();
2073e248012SOliver Ruiz Dorantes return protocol->next->module->get_mtu(protocol->next, address);
2083e248012SOliver Ruiz Dorantes }
2093e248012SOliver Ruiz Dorantes
2103e248012SOliver Ruiz Dorantes
211*bb83316aSAugustin Cavalier static HciConnection*
connection_for(net_buffer * buffer)212*bb83316aSAugustin Cavalier connection_for(net_buffer* buffer)
213*bb83316aSAugustin Cavalier {
214*bb83316aSAugustin Cavalier const sockaddr_l2cap* l2capAddr = (sockaddr_l2cap*)buffer->source;
215*bb83316aSAugustin Cavalier const sockaddr_dl* interfaceAddr = (sockaddr_dl*)buffer->interface_address->local;
216*bb83316aSAugustin Cavalier struct HciConnection* connection = btCoreData->ConnectionByDestination(
217*bb83316aSAugustin Cavalier l2capAddr->l2cap_bdaddr, interfaceAddr->sdl_index);
218*bb83316aSAugustin Cavalier buffer->interface_address = NULL;
219*bb83316aSAugustin Cavalier // This isn't a real interface_address; it could confuse the buffer module.
220*bb83316aSAugustin Cavalier // FIXME: We probably should have an alternate interface for passing along data.
221*bb83316aSAugustin Cavalier return connection;
222*bb83316aSAugustin Cavalier }
223*bb83316aSAugustin Cavalier
224*bb83316aSAugustin Cavalier
2253e248012SOliver Ruiz Dorantes status_t
l2cap_receive_data(net_buffer * buffer)2263e248012SOliver Ruiz Dorantes l2cap_receive_data(net_buffer* buffer)
2273e248012SOliver Ruiz Dorantes {
228*bb83316aSAugustin Cavalier if (buffer->size < sizeof(l2cap_basic_header)) {
229*bb83316aSAugustin Cavalier ERROR("%s: invalid L2CAP packet: too small. len=%" B_PRIu32 "\n",
230*bb83316aSAugustin Cavalier __func__, buffer->size);
231*bb83316aSAugustin Cavalier gBufferModule->free(buffer);
232*bb83316aSAugustin Cavalier return EMSGSIZE;
233*bb83316aSAugustin Cavalier }
2343e248012SOliver Ruiz Dorantes
235*bb83316aSAugustin Cavalier NetBufferHeaderReader<l2cap_basic_header> bufferHeader(buffer);
236*bb83316aSAugustin Cavalier if (bufferHeader.Status() != B_OK)
237*bb83316aSAugustin Cavalier return ENOBUFS;
2383e248012SOliver Ruiz Dorantes
239*bb83316aSAugustin Cavalier uint16 length = le16toh(bufferHeader->length);
240*bb83316aSAugustin Cavalier uint16 dcid = le16toh(bufferHeader->dcid);
241*bb83316aSAugustin Cavalier
242*bb83316aSAugustin Cavalier TRACE("%s: len=%d cid=%x\n", __func__, length, dcid);
243*bb83316aSAugustin Cavalier
244*bb83316aSAugustin Cavalier bufferHeader.Remove();
245*bb83316aSAugustin Cavalier
246*bb83316aSAugustin Cavalier if (length != buffer->size) {
247*bb83316aSAugustin Cavalier ERROR("l2cap: payload length mismatch, packetlen=%d, bufferlen=%" B_PRIu32 "\n",
248*bb83316aSAugustin Cavalier length, buffer->size);
249*bb83316aSAugustin Cavalier return EMSGSIZE;
250*bb83316aSAugustin Cavalier }
251*bb83316aSAugustin Cavalier
252*bb83316aSAugustin Cavalier status_t status = B_ERROR;
253*bb83316aSAugustin Cavalier switch (dcid) {
254*bb83316aSAugustin Cavalier case L2CAP_SIGNALING_CID:
255*bb83316aSAugustin Cavalier {
256*bb83316aSAugustin Cavalier // We need to find the connection this packet is associated with.
257*bb83316aSAugustin Cavalier struct HciConnection* connection = connection_for(buffer);
258*bb83316aSAugustin Cavalier if (connection == NULL) {
259*bb83316aSAugustin Cavalier panic("no connection for received L2CAP command");
260*bb83316aSAugustin Cavalier return ENOTCONN;
261*bb83316aSAugustin Cavalier }
262*bb83316aSAugustin Cavalier
263*bb83316aSAugustin Cavalier status = l2cap_handle_signaling_command(connection, buffer);
264*bb83316aSAugustin Cavalier break;
265*bb83316aSAugustin Cavalier }
266*bb83316aSAugustin Cavalier
267*bb83316aSAugustin Cavalier case L2CAP_CONNECTIONLESS_CID:
268*bb83316aSAugustin Cavalier {
269*bb83316aSAugustin Cavalier NetBufferHeaderReader<l2cap_connectionless_header> connlessHeader(buffer);
270*bb83316aSAugustin Cavalier const uint16 psm = le16toh(connlessHeader->psm);
271*bb83316aSAugustin Cavalier L2capEndpoint* endpoint = gL2capEndpointManager.ForPSM(psm);
272*bb83316aSAugustin Cavalier if (endpoint == NULL)
273*bb83316aSAugustin Cavalier return ECONNRESET;
274*bb83316aSAugustin Cavalier
275*bb83316aSAugustin Cavalier connlessHeader.Remove();
276*bb83316aSAugustin Cavalier buffer->interface_address = NULL;
277*bb83316aSAugustin Cavalier
278*bb83316aSAugustin Cavalier status = endpoint->ReceiveData(buffer);
279*bb83316aSAugustin Cavalier break;
280*bb83316aSAugustin Cavalier }
281*bb83316aSAugustin Cavalier
282*bb83316aSAugustin Cavalier default:
283*bb83316aSAugustin Cavalier {
284*bb83316aSAugustin Cavalier L2capEndpoint* endpoint = gL2capEndpointManager.ForChannel(dcid);
285*bb83316aSAugustin Cavalier if (endpoint == NULL)
286*bb83316aSAugustin Cavalier return ECONNRESET;
287*bb83316aSAugustin Cavalier
288*bb83316aSAugustin Cavalier buffer->interface_address = NULL;
289*bb83316aSAugustin Cavalier status = endpoint->ReceiveData(buffer);
290*bb83316aSAugustin Cavalier break;
291*bb83316aSAugustin Cavalier }
292*bb83316aSAugustin Cavalier }
293*bb83316aSAugustin Cavalier
294*bb83316aSAugustin Cavalier return status;
2953e248012SOliver Ruiz Dorantes }
2963e248012SOliver Ruiz Dorantes
2973e248012SOliver Ruiz Dorantes
2983e248012SOliver Ruiz Dorantes status_t
l2cap_error_received(net_error error,net_buffer * data)2992b415445SAxel Dörfler l2cap_error_received(net_error error, net_buffer* data)
3003e248012SOliver Ruiz Dorantes {
301c58e1d7fSAlexander von Gluck IV CALLED();
302c61dc72fSOliver Ruiz Dorantes
303*bb83316aSAugustin Cavalier if (error == B_NET_ERROR_UNREACH_HOST) {
304*bb83316aSAugustin Cavalier struct HciConnection* connection = connection_for(data);
305*bb83316aSAugustin Cavalier if (connection == NULL)
306*bb83316aSAugustin Cavalier return ENOTCONN;
307*bb83316aSAugustin Cavalier
308*bb83316aSAugustin Cavalier // Disconnect all connections with this HciConnection.
309*bb83316aSAugustin Cavalier gL2capEndpointManager.Disconnected(connection);
310*bb83316aSAugustin Cavalier
311*bb83316aSAugustin Cavalier gBufferModule->free(data);
312*bb83316aSAugustin Cavalier return B_OK;
313*bb83316aSAugustin Cavalier }
314*bb83316aSAugustin Cavalier
3153e248012SOliver Ruiz Dorantes return B_ERROR;
3163e248012SOliver Ruiz Dorantes }
3173e248012SOliver Ruiz Dorantes
3183e248012SOliver Ruiz Dorantes
3193e248012SOliver Ruiz Dorantes status_t
l2cap_error_reply(net_protocol * protocol,net_buffer * cause,net_error error,net_error_data * errorData)3202b415445SAxel Dörfler l2cap_error_reply(net_protocol* protocol, net_buffer* cause, net_error error,
3212b415445SAxel Dörfler net_error_data* errorData)
3223e248012SOliver Ruiz Dorantes {
323c58e1d7fSAlexander von Gluck IV CALLED();
3243e248012SOliver Ruiz Dorantes return B_ERROR;
3253e248012SOliver Ruiz Dorantes }
3263e248012SOliver Ruiz Dorantes
3273e248012SOliver Ruiz Dorantes
3282b415445SAxel Dörfler // #pragma mark -
3292b415445SAxel Dörfler
3303e248012SOliver Ruiz Dorantes
3313e248012SOliver Ruiz Dorantes static status_t
l2cap_std_ops(int32 op,...)3323e248012SOliver Ruiz Dorantes l2cap_std_ops(int32 op, ...)
3333e248012SOliver Ruiz Dorantes {
334b9b8d43cSOliver Ruiz Dorantes status_t error;
335b9b8d43cSOliver Ruiz Dorantes
336c58e1d7fSAlexander von Gluck IV CALLED();
337c61dc72fSOliver Ruiz Dorantes
3383e248012SOliver Ruiz Dorantes switch (op) {
3393e248012SOliver Ruiz Dorantes case B_MODULE_INIT:
3403e248012SOliver Ruiz Dorantes {
341*bb83316aSAugustin Cavalier new(&gL2capEndpointManager) L2capEndpointManager;
342*bb83316aSAugustin Cavalier
343a5bf1237SOliver Ruiz Dorantes error = gStackModule->register_domain_protocols(AF_BLUETOOTH,
344a5bf1237SOliver Ruiz Dorantes SOCK_STREAM, BLUETOOTH_PROTO_L2CAP,
345*bb83316aSAugustin Cavalier NET_BLUETOOTH_L2CAP_NAME, NULL);
346a5bf1237SOliver Ruiz Dorantes if (error != B_OK)
347c61dc72fSOliver Ruiz Dorantes return error;
348c61dc72fSOliver Ruiz Dorantes
3492b415445SAxel Dörfler error = gStackModule->register_domain(AF_BLUETOOTH, "l2cap",
350*bb83316aSAugustin Cavalier &gL2CAPModule, &gL2capAddressModule, &sDomain);
351a5bf1237SOliver Ruiz Dorantes if (error != B_OK)
352c61dc72fSOliver Ruiz Dorantes return error;
353c61dc72fSOliver Ruiz Dorantes
3543e248012SOliver Ruiz Dorantes return B_OK;
3553e248012SOliver Ruiz Dorantes }
3563e248012SOliver Ruiz Dorantes
3573e248012SOliver Ruiz Dorantes case B_MODULE_UNINIT:
358*bb83316aSAugustin Cavalier gL2capEndpointManager.~L2capEndpointManager();
3597cc7cadaSOliver Ruiz Dorantes gStackModule->unregister_domain(sDomain);
3603e248012SOliver Ruiz Dorantes return B_OK;
3613e248012SOliver Ruiz Dorantes
3623e248012SOliver Ruiz Dorantes default:
3633e248012SOliver Ruiz Dorantes return B_ERROR;
3643e248012SOliver Ruiz Dorantes }
3653e248012SOliver Ruiz Dorantes }
3663e248012SOliver Ruiz Dorantes
3673e248012SOliver Ruiz Dorantes
368c61dc72fSOliver Ruiz Dorantes net_protocol_module_info gL2CAPModule = {
3693e248012SOliver Ruiz Dorantes {
370b9b8d43cSOliver Ruiz Dorantes NET_BLUETOOTH_L2CAP_NAME,
371*bb83316aSAugustin Cavalier 0,
3723e248012SOliver Ruiz Dorantes l2cap_std_ops
3733e248012SOliver Ruiz Dorantes },
3743e248012SOliver Ruiz Dorantes NET_PROTOCOL_ATOMIC_MESSAGES,
3753e248012SOliver Ruiz Dorantes
3763e248012SOliver Ruiz Dorantes l2cap_init_protocol,
3773e248012SOliver Ruiz Dorantes l2cap_uninit_protocol,
3783e248012SOliver Ruiz Dorantes l2cap_open,
3793e248012SOliver Ruiz Dorantes l2cap_close,
3803e248012SOliver Ruiz Dorantes l2cap_free,
3813e248012SOliver Ruiz Dorantes l2cap_connect,
3823e248012SOliver Ruiz Dorantes l2cap_accept,
3833e248012SOliver Ruiz Dorantes l2cap_control,
3843e248012SOliver Ruiz Dorantes l2cap_getsockopt,
3853e248012SOliver Ruiz Dorantes l2cap_setsockopt,
3863e248012SOliver Ruiz Dorantes l2cap_bind,
3873e248012SOliver Ruiz Dorantes l2cap_unbind,
3883e248012SOliver Ruiz Dorantes l2cap_listen,
3893e248012SOliver Ruiz Dorantes l2cap_shutdown,
3903e248012SOliver Ruiz Dorantes l2cap_send_data,
3913e248012SOliver Ruiz Dorantes l2cap_send_routed_data,
3923e248012SOliver Ruiz Dorantes l2cap_send_avail,
3933e248012SOliver Ruiz Dorantes l2cap_read_data,
3943e248012SOliver Ruiz Dorantes l2cap_read_avail,
3953e248012SOliver Ruiz Dorantes l2cap_get_domain,
3963e248012SOliver Ruiz Dorantes l2cap_get_mtu,
3973e248012SOliver Ruiz Dorantes l2cap_receive_data,
3989871124eSAxel Dörfler NULL, // deliver_data()
3992b415445SAxel Dörfler l2cap_error_received,
4003e248012SOliver Ruiz Dorantes l2cap_error_reply,
4019871124eSAxel Dörfler NULL, // add_ancillary_data()
4029871124eSAxel Dörfler NULL, // process_ancillary_data()
40378888c44SAxel Dörfler NULL, // process_ancillary_data_no_container()
4049871124eSAxel Dörfler NULL, // send_data_no_buffer()
4059871124eSAxel Dörfler NULL // read_data_no_buffer()
4063e248012SOliver Ruiz Dorantes };
4073e248012SOliver Ruiz Dorantes
4083e248012SOliver Ruiz Dorantes module_dependency module_dependencies[] = {
4097cc7cadaSOliver Ruiz Dorantes {NET_STACK_MODULE_NAME, (module_info**)&gStackModule},
4103e248012SOliver Ruiz Dorantes {NET_BUFFER_MODULE_NAME, (module_info**)&gBufferModule},
411b9b8d43cSOliver Ruiz Dorantes {NET_SOCKET_MODULE_NAME, (module_info**)&gSocketModule},
412*bb83316aSAugustin Cavalier {BT_CORE_DATA_MODULE_NAME, (module_info**)&btCoreData},
413*bb83316aSAugustin Cavalier {BT_HCI_MODULE_NAME, (module_info**)&btDevices},
4143e248012SOliver Ruiz Dorantes {}
4153e248012SOliver Ruiz Dorantes };
4163e248012SOliver Ruiz Dorantes
4173e248012SOliver Ruiz Dorantes module_info* modules[] = {
418c61dc72fSOliver Ruiz Dorantes (module_info*)&gL2CAPModule,
4193e248012SOliver Ruiz Dorantes NULL
4203e248012SOliver Ruiz Dorantes };
421