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
7
8#include <bluetooth/bdaddrUtils.h>
9#include <bluetooth/HCI/btHCI_transport.h>
10#include <bluetooth/HCI/btHCI_event.h>
11
12#define BT_DEBUG_THIS_MODULE
13#include <btDebug.h>
14
15
16int32 api_version = B_CUR_DRIVER_API_VERSION;
17
18
19mutex sConnectionListLock = MUTEX_INITIALIZER("bt connection list");
20DoublyLinkedList<HciConnection> sConnectionList;
21net_buffer_module_info* gBufferModule = NULL;
22
23
24inline bool
25ExistConnectionByDestination(const bdaddr_t& destination, hci_id hid = -1)
26{
27	return ConnectionByDestination(destination, hid) != NULL;
28}
29
30
31inline bool
32ExistConnectionByHandle(uint16 handle, hci_id hid)
33{
34	return ConnectionByHandle(handle, hid);
35}
36
37
38status_t
39PostEvent(bluetooth_device* ndev, void* event, size_t size)
40{
41	struct hci_event_header* outgoingEvent = (struct hci_event_header*) event;
42	status_t err;
43
44	// Take actions on certain type of events.
45	switch (outgoingEvent->ecode) {
46		case HCI_EVENT_CONN_COMPLETE:
47		{
48			struct hci_ev_conn_complete* data
49				= (struct hci_ev_conn_complete*)(outgoingEvent + 1);
50
51			// TODO: XXX parse handle field
52			HciConnection* conn = AddConnection(data->handle, BT_ACL,
53				data->bdaddr, ndev->index);
54
55			if (conn == NULL)
56				panic("no mem for conn desc");
57			conn->ndevice = ndev;
58			TRACE("%s: Registered connection handle=%#x\n", __func__,
59				data->handle);
60			break;
61		}
62
63		case HCI_EVENT_DISCONNECTION_COMPLETE:
64		{
65			struct hci_ev_disconnection_complete_reply* data;
66
67			data = (struct hci_ev_disconnection_complete_reply*)
68				(outgoingEvent + 1);
69
70			RemoveConnection(data->handle, ndev->index);
71			TRACE("%s: unRegistered connection handle=%#x\n", __func__,
72				data->handle);
73			break;
74		}
75
76	}
77
78	// forward to bluetooth server
79	port_id port = find_port(BT_USERLAND_PORT_NAME);
80	if (port != B_NAME_NOT_FOUND) {
81
82		err = write_port_etc(port, PACK_PORTCODE(BT_EVENT, ndev->index, -1),
83			event, size, B_TIMEOUT, 1 * 1000 * 1000);
84
85		if (err != B_OK)
86			ERROR("%s: Error posting userland %s\n", __func__, strerror(err));
87
88	} else {
89		ERROR("%s: bluetooth_server not found for posting!\n", __func__);
90		err = B_NAME_NOT_FOUND;
91	}
92
93	return err;
94}
95
96
97static status_t
98bcd_std_ops(int32 op, ...)
99{
100	status_t status;
101
102	switch (op) {
103		case B_MODULE_INIT:
104			new (&sConnectionList) DoublyLinkedList<HciConnection>;
105
106			status = get_module(NET_BUFFER_MODULE_NAME,
107				(module_info **)&gBufferModule);
108			if (status != B_OK)
109				return status;
110
111			return B_OK;
112
113		case B_MODULE_UNINIT:
114			put_module(NET_BUFFER_MODULE_NAME);
115			return B_OK;
116	}
117
118	return B_ERROR;
119}
120
121
122bluetooth_core_data_module_info sBCDModule = {
123	{
124		BT_CORE_DATA_MODULE_NAME,
125		0,
126		bcd_std_ops
127	},
128	PostEvent,
129	AddConnection,
130	// RemoveConnection,
131	RemoveConnection,
132
133	RouteConnection,
134
135	ConnectionByHandle,
136	ConnectionByDestination,
137
138	allocate_command_ident,
139	lookup_command_ident,
140	free_command_ident,
141};
142
143
144module_info* modules[] = {
145	(module_info*)&sBCDModule,
146	NULL
147};
148