1/*
2 * Copyright 2008, Oliver Ruiz Dorantes. All rights reserved.
3 * Copyright 2024, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6#ifndef L2CAP_ENDPOINT_H
7#define L2CAP_ENDPOINT_H
8
9
10#include <lock.h>
11#include <condition_variable.h>
12#include <util/AVLTree.h>
13
14#include <net_protocol.h>
15#include <net_socket.h>
16#include <ProtocolUtilities.h>
17
18#include <bluetooth/L2CAP/btL2CAP.h>
19#include "l2cap_internal.h"
20
21
22class L2capEndpoint;
23
24
25class L2capEndpoint : public net_protocol, public ProtocolSocket, public AVLTreeNode {
26public:
27						L2capEndpoint(net_socket* socket);
28	virtual				~L2capEndpoint();
29
30			status_t	Open();
31			status_t	Shutdown();
32			status_t	Close();
33			status_t	Free();
34
35			status_t	Bind(const struct sockaddr* _address);
36			status_t	Unbind();
37			status_t	Listen(int backlog);
38			status_t	Connect(const struct sockaddr* address);
39			status_t	Accept(net_socket** _acceptedSocket);
40
41			uint16		ChannelID() const { return fChannelID; }
42
43			ssize_t		ReadData(size_t numBytes, uint32 flags, net_buffer** _buffer);
44			ssize_t		SendData(net_buffer* buffer);
45			status_t	ReceiveData(net_buffer* buffer);
46			ssize_t		Sendable();
47			ssize_t		Receivable();
48
49public:
50			void		_HandleCommandRejected(uint8 ident, uint16 reason,
51							const l2cap_command_reject_data& data);
52			void 		_HandleConnectionReq(HciConnection* connection,
53							uint8 ident, uint16 psm, uint16 scid);
54			void		_HandleConnectionRsp(uint8 ident, const l2cap_connection_rsp& response);
55			void		_HandleConfigurationReq(uint8 ident, uint16 flags,
56							uint16* mtu, uint16* flush_timeout, l2cap_qos* flow);
57			void		_HandleConfigurationRsp(uint8 ident, uint16 scid, uint16 flags,
58							uint16 result, uint16* mtu, uint16* flush_timeout, l2cap_qos* flow);
59			void		_HandleDisconnectionReq(uint8 ident, uint16 scid);
60			void		_HandleDisconnectionRsp(uint8 ident, uint16 dcid, uint16 scid);
61
62private:
63	inline bool
64	_IsEstablishing()
65	{
66		return fState > LISTEN && fState < OPEN;
67	}
68
69			status_t	_WaitForStateChange(bigtime_t absoluteTimeout);
70
71	static	void		_SendTimer(net_timer* timer, void* _endpoint);
72			void		_SendQueued();
73
74			void		_SendChannelConfig();
75			status_t	_MarkEstablished();
76			void		_MarkClosed();
77
78private:
79	friend class L2capEndpointManager;
80
81	sem_id			fAcceptSemaphore;
82	mutex			fLock;
83
84	enum channel_status {
85		CLOSED,
86		BOUND,
87		LISTEN,
88
89		WAIT_FOR_CONNECTION_RSP,
90		CONFIGURATION,
91		OPEN,
92		WAIT_FOR_DISCONNECTION_RSP,
93		RECEIVED_DISCONNECTION_REQ,
94	} fState;
95
96	HciConnection*	fConnection;
97
98	ConditionVariable fCommandWait;
99
100	uint16			fChannelID, fDestinationChannelID;
101
102	net_fifo		fReceiveQueue, fSendQueue;
103	net_timer		fSendTimer;
104
105	struct ConfigState {
106		enum : uint8 {
107			NONE,
108			SENT,
109			DONE,
110		} in, out;
111	} fConfigState;
112	struct ChannelConfiguration {
113		uint16		incoming_mtu;
114		l2cap_qos	incoming_flow;
115		uint16		outgoing_mtu;
116		l2cap_qos	outgoing_flow;
117
118		uint16		flush_timeout;
119		uint16		link_timeout;
120	} fChannelConfig;
121};
122
123
124#endif	// L2CAP_ENDPOINT_H
125