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