xref: /haiku/src/add-ons/kernel/bluetooth/btCoreData/BTCoreData.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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 
18 int32 api_version = B_CUR_DRIVER_API_VERSION;
19 
20 
21 DoublyLinkedList<HciConnection> sConnectionList;
22 net_buffer_module_info* gBufferModule = NULL;
23 
24 
25 inline bool
26 ExistConnectionByDestination(const bdaddr_t& destination, hci_id hid = -1)
27 {
28 	return ConnectionByDestination(destination, hid) != NULL;
29 }
30 
31 
32 inline bool
33 ExistConnectionByHandle(uint16 handle, hci_id hid)
34 {
35 	return ConnectionByHandle(handle, hid);
36 }
37 
38 
39 static int
40 DumpHciConnections(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 
97 status_t
98 PostEvent(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 
156 static status_t
157 bcd_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 
189 bluetooth_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 
228 module_info* modules[] = {
229 	(module_info*)&sBCDModule,
230 	NULL
231 };
232