xref: /haiku/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2upper.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
1 /*
2  * Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
3  * Copyright 2008 Mika Lindqvist, monni1995_at_gmail.com
4  * All rights reserved. Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "h2upper.h"
9 
10 #include <string.h>
11 
12 #include <bluetooth/bluetooth.h>
13 #include <bluetooth/HCI/btHCI_transport.h>
14 #include <kernel.h>
15 
16 #include "h2debug.h"
17 #include "h2generic.h"
18 #include "h2transactions.h"
19 #include "snet_buffer.h"
20 
21 
22 // TODO: split for commands and comunication (ACL & SCO)
23 void
24 sched_tx_processing(bt_usb_dev* bdev)
25 {
26 	net_buffer* nbuf;
27 	snet_buffer* snbuf;
28 	status_t err;
29 
30 	TRACE("%s: (%p)\n", __func__, bdev);
31 
32 	if (!TEST_AND_SET(&bdev->state, PROCESSING)) {
33 		// We are not processing in another thread so... START!!
34 
35 		do {
36 			/* Do while this bit is on... so someone should set it before we
37 			 * stop the iterations
38 			 */
39 			bdev->state = CLEAR_BIT(bdev->state, SENDING);
40 			// check Commands
41 	#ifdef EMPTY_COMMAND_QUEUE
42 			while (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND])) {
43 	#else
44 			if (!list_is_empty(&bdev->nbuffersTx[BT_COMMAND])) {
45 	#endif
46 				snbuf = (snet_buffer*)
47 					list_remove_head_item(&bdev->nbuffersTx[BT_COMMAND]);
48 				err = submit_tx_command(bdev, snbuf);
49 				if (err != B_OK) {
50 					// re-head it
51 					list_insert_item_before(&bdev->nbuffersTx[BT_COMMAND],
52 						list_get_first_item(&bdev->nbuffersTx[BT_COMMAND]),
53 						snbuf);
54 				}
55 			}
56 
57 			// check ACl
58 	#define EMPTY_ACL_QUEUE
59 	#ifdef EMPTY_ACL_QUEUE
60 			while (!list_is_empty(&bdev->nbuffersTx[BT_ACL])) {
61 	#else
62 			if (!list_is_empty(&bdev->nbuffersTx[BT_ACL])) {
63 	#endif
64 				nbuf = (net_buffer*)
65 					list_remove_head_item(&bdev->nbuffersTx[BT_ACL]);
66 				err = submit_tx_acl(bdev, nbuf);
67 				if (err != B_OK) {
68 					// re-head it
69 					list_insert_item_before(&bdev->nbuffersTx[BT_ACL],
70 							list_get_first_item(&bdev->nbuffersTx[BT_ACL]),
71 							nbuf);
72 				}
73 			}
74 
75 			if (!list_is_empty(&bdev->nbuffersTx[BT_SCO])) {
76 				// TODO to be implemented
77 			}
78 
79 		} while (GET_BIT(bdev->state, SENDING));
80 
81 		bdev->state = CLEAR_BIT(bdev->state, PROCESSING);
82 
83 	} else {
84 		// We are processing so MARK that we need to still go on with that
85 		bdev->state = SET_BIT(bdev->state, SENDING);
86 	}
87 }
88 
89 
90 #if 0
91 // DEPRECATED
92 status_t
93 post_packet_up(bt_usb_dev* bdev, bt_packet_t type, void* buf)
94 {
95 	status_t err = B_ERROR;
96 
97 	debugf("Frame up type=%d\n", type);
98 
99 	if (type == BT_EVENT) {
100 		snet_buffer* snbuf = (snet_buffer*)buf;
101 		btCoreData->PostEvent(bdev->ndev, snb_get(snbuf),
102 			(size_t)snb_size(snbuf));
103 		snb_park(&bdev->snetBufferRecycleTrash, snbuf);
104 		debugf("to btDataCore len=%d\n", snb_size(snbuf));
105 	} else {
106 		net_buffer* nbuf = (net_buffer*) buf;
107 		// No need to free the buffer at allocation is gonna be reused
108 		btDevices->receive_data(bdev->ndev, &nbuf);
109 		TRACE("to net_device\n");
110 	}
111 
112 	return err;
113 }
114 #endif
115 
116 
117 status_t
118 send_packet(hci_id hid, bt_packet_t type, net_buffer* nbuf)
119 {
120 	bt_usb_dev* bdev = fetch_device(NULL, hid);
121 	status_t err = B_OK;
122 
123 	if (bdev == NULL)
124 		return B_ERROR;
125 
126 	// TODO: check if device is actually ready for this
127 	// TODO: Lock Device
128 
129 	if (nbuf != NULL) {
130 		if (type != nbuf->protocol) // a bit strict maybe
131 			panic("Upper layer has not filled correctly a packet");
132 
133 		switch (type) {
134 			case BT_COMMAND:
135 			case BT_ACL:
136 			case BT_SCO:
137 				list_add_item(&bdev->nbuffersTx[type], nbuf);
138 				bdev->nbuffersPendingTx[type]++;
139 			break;
140 			default:
141 				ERROR("%s: Unknown packet type for sending %d\n", __func__,
142 					type);
143 				// TODO: free the net_buffer -> no, allow upper layer
144 				// handle it with the given error
145 				err = B_BAD_VALUE;
146 			break;
147 		}
148 	} else {
149 		TRACE("%s: tx sched provoked", __func__);
150 	}
151 
152 	// TODO: check if device is actually ready for this
153 	// TODO: unlock device
154 
155 	// sched in any case even if nbuf is null (provoke re-scheduling)
156 	sched_tx_processing(bdev);
157 
158 	return err;
159 }
160 
161 
162 status_t
163 send_command(hci_id hid, snet_buffer* snbuf)
164 {
165 	bt_usb_dev* bdev = fetch_device(NULL, hid);
166 	status_t err = B_OK;
167 
168 	if (bdev == NULL)
169 		return B_ERROR;
170 
171 	// TODO: check if device is actually ready for this
172 	// TODO: mutex
173 
174 	if (snbuf != NULL) {
175 		list_add_item(&bdev->nbuffersTx[BT_COMMAND], snbuf);
176 		bdev->nbuffersPendingTx[BT_COMMAND]++;
177 	} else {
178 		err = B_BAD_VALUE;
179 		TRACE("%s: tx sched provoked", __func__);
180 	}
181 
182 	// TODO: check if device is actually ready for this
183 	// TODO: mutex
184 
185 	/* sched in All cases even if nbuf is null (hidden way to provoke
186 	 * re-scheduling)
187 	 */
188 	sched_tx_processing(bdev);
189 
190 	return err;
191 }
192