1/*
2 * Copyright 2008 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3 * All rights reserved. Distributed under the terms of the MIT License.
4 */
5#include "ConnectionInterface.h"
6#include "ChannelInterface.h"
7#include "FrameInterface.h"
8
9
10#include <bluetooth/bdaddrUtils.h>
11#include <bluetooth/HCI/btHCI_transport.h>
12#include <bluetooth/HCI/btHCI_event.h>
13
14#define BT_DEBUG_THIS_MODULE
15#include <btDebug.h>
16
17
18int32 api_version = B_CUR_DRIVER_API_VERSION;
19
20
21DoublyLinkedList<HciConnection> sConnectionList;
22net_buffer_module_info* gBufferModule = NULL;
23
24
25inline bool
26ExistConnectionByDestination(const bdaddr_t& destination, hci_id hid = -1)
27{
28	return ConnectionByDestination(destination, hid) != NULL;
29}
30
31
32inline bool
33ExistConnectionByHandle(uint16 handle, hci_id hid)
34{
35	return ConnectionByHandle(handle, hid);
36}
37
38
39static int
40DumpHciConnections(int argc, char** argv)
41{
42	HciConnection* conn;
43	L2capChannel* chan;
44	L2capFrame* frame;
45	DoublyLinkedList<HciConnection>::Iterator iterator
46		= sConnectionList.GetIterator();
47
48	while (iterator.HasNext()) {
49		conn = iterator.Next();
50		/*
51		kprintf("LocalDevice=0x%" B_PRIx32 " Destination=%s handle=%#x type=%d"
52			"outqueue=%" B_PRId32 " expected=%" B_PRId32 "\n", conn->Hid,
53			bdaddrUtils::ToString(conn->destination).String(), conn->handle,
54			conn->type, conn->OutGoingFrames.Count(),
55			conn->ExpectedResponses.Count());
56		*/
57
58		// each channel
59		kprintf("\tChannels\n");
60		DoublyLinkedList<L2capChannel>::Iterator channelIterator
61			= conn->ChannelList.GetIterator();
62
63		while (channelIterator.HasNext()) {
64			chan = channelIterator.Next();
65			kprintf("\t\tscid=%x dcid=%x state=%x cfg=%x\n", chan->scid,
66				chan->dcid, chan->state, chan->cfgState);
67		}
68
69		// Each outgoing
70		kprintf("\n\tOutGoingFrames\n");
71		DoublyLinkedList<L2capFrame>::Iterator frameIterator
72			= conn->OutGoingFrames.GetIterator();
73		while (frameIterator.HasNext()) {
74			frame = frameIterator.Next();
75			kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
76				frame->channel->scid, frame->code, frame->ident,
77				frame->type, frame->buffer);
78		}
79
80		// Each expected
81		kprintf("\n\tExpectedFrames\n");
82		DoublyLinkedList<L2capFrame>::Iterator frameExpectedIterator
83			= conn->ExpectedResponses.GetIterator();
84
85		while (frameExpectedIterator.HasNext()) {
86			frame = frameExpectedIterator.Next();
87			kprintf("\t\tscid=%x code=%x ident=%x type=%x, buffer=%p\n",
88				frame->channel->scid, frame->code, frame->ident,
89				frame->type, frame->buffer);
90		}
91	}
92
93	return 0;
94}
95
96
97status_t
98PostEvent(bluetooth_device* ndev, void* event, size_t size)
99{
100	struct hci_event_header* outgoingEvent = (struct hci_event_header*) event;
101	status_t err;
102
103	// Take actions on certain type of events.
104	switch (outgoingEvent->ecode) {
105		case HCI_EVENT_CONN_COMPLETE:
106		{
107			struct hci_ev_conn_complete* data
108				= (struct hci_ev_conn_complete*)(outgoingEvent + 1);
109
110			// TODO: XXX parse handle field
111			HciConnection* conn = AddConnection(data->handle, BT_ACL,
112				data->bdaddr, ndev->index);
113
114			if (conn == NULL)
115				panic("no mem for conn desc");
116			conn->ndevice = ndev;
117			TRACE("%s: Registered connection handle=%#x\n", __func__,
118				data->handle);
119			break;
120		}
121
122		case HCI_EVENT_DISCONNECTION_COMPLETE:
123		{
124			struct hci_ev_disconnection_complete_reply* data;
125
126			data = (struct hci_ev_disconnection_complete_reply*)
127				(outgoingEvent + 1);
128
129			RemoveConnection(data->handle, ndev->index);
130			TRACE("%s: unRegistered connection handle=%#x\n", __func__,
131				data->handle);
132			break;
133		}
134
135	}
136
137	// forward to bluetooth server
138	port_id port = find_port(BT_USERLAND_PORT_NAME);
139	if (port != B_NAME_NOT_FOUND) {
140
141		err = write_port_etc(port, PACK_PORTCODE(BT_EVENT, ndev->index, -1),
142			event, size, B_TIMEOUT, 1 * 1000 * 1000);
143
144		if (err != B_OK)
145			ERROR("%s: Error posting userland %s\n", __func__, strerror(err));
146
147	} else {
148		ERROR("%s: bluetooth_server not found for posting!\n", __func__);
149		err = B_NAME_NOT_FOUND;
150	}
151
152	return err;
153}
154
155
156static status_t
157bcd_std_ops(int32 op, ...)
158{
159	status_t status;
160
161	switch (op) {
162		case B_MODULE_INIT:
163			new (&sConnectionList) DoublyLinkedList<HciConnection>;
164			add_debugger_command("btConnections", &DumpHciConnections,
165				"Lists Bluetooth Connections with RemoteDevices & channels");
166
167			status = get_module(NET_BUFFER_MODULE_NAME,
168				(module_info **)&gBufferModule);
169			if (status < B_OK)
170				return status;
171
172			return B_OK;
173
174		break;
175
176		case B_MODULE_UNINIT:
177
178			remove_debugger_command("btConnections", &DumpHciConnections);
179			put_module(NET_BUFFER_MODULE_NAME);
180
181			return B_OK;
182		break;
183	}
184
185	return B_ERROR;
186}
187
188
189bluetooth_core_data_module_info sBCDModule = {
190	{
191		BT_CORE_DATA_MODULE_NAME,
192		0,
193		bcd_std_ops
194	},
195	PostEvent,
196	AddConnection,
197	// RemoveConnection,
198	RemoveConnection,
199
200	RouteConnection,
201
202	SetAclBuffer,
203	SetAclExpectedSize,
204	AclPutting,
205	AclComplete,
206	AclOverFlowed,
207
208	ConnectionByHandle,
209	ConnectionByDestination,
210
211	AddChannel,
212	RemoveChannel,
213	ChannelBySourceID,
214	ChannelAllocateCid,
215	ChannelAllocateIdent,
216
217	SignalByIdent,
218	TimeoutSignal,
219	unTimeoutSignal,
220	SpawmFrame,
221	SpawmSignal,
222	AcknowledgeSignal,
223	QueueSignal,
224
225};
226
227
228module_info* modules[] = {
229	(module_info*)&sBCDModule,
230	NULL
231};
232