xref: /haiku/src/add-ons/kernel/drivers/bluetooth/h2/h2generic/h2upper.cpp (revision d17092ceb18bf47a96dbaf8a1acf10e6e3070704)
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 #include <string.h>
8 
9 #include <bluetooth/bluetooth.h>
10 #include <bluetooth/HCI/btHCI_transport.h>
11 #include <kernel.h>
12 
13 #include "h2generic.h"
14 #include "h2upper.h"
15 #include "h2transactions.h"
16 #include "snet_buffer.h"
17 
18 #define BT_DEBUG_THIS_MODULE
19 #include <btDebug.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 	debugf("(%p)\n", 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 		flowf("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 				debugf("Unknown packet type for sending %d\n",type);
142 				// TODO: free the net_buffer -> no, allow upper layer
143 				// handle it with the given error
144 				err = B_BAD_VALUE;
145 			break;
146 		}
147 	} else {
148 		flowf("tx sched provoked");
149 	}
150 
151 	// TODO: check if device is actually ready for this
152 	// TODO: unlock device
153 
154 	// sched in any case even if nbuf is null (provoke re-scheduling)
155 	sched_tx_processing(bdev);
156 
157 	return err;
158 }
159 
160 
161 status_t
162 send_command(hci_id hid, snet_buffer* snbuf)
163 {
164 	bt_usb_dev* bdev = fetch_device(NULL, hid);
165 	status_t err = B_OK;
166 
167 	if (bdev == NULL)
168 		return B_ERROR;
169 
170 	// TODO: check if device is actually ready for this
171 	// TODO: mutex
172 
173 	if (snbuf != NULL) {
174 		list_add_item(&bdev->nbuffersTx[BT_COMMAND],snbuf);
175 		bdev->nbuffersPendingTx[BT_COMMAND]++;
176 	} else {
177 		err = B_BAD_VALUE;
178 		flowf("tx sched provoked");
179 	}
180 
181 	// TODO: check if device is actually ready for this
182 	// TODO: mutex
183 
184 	/* sched in All cases even if nbuf is null (hidden way to provoke
185 	 * re-scheduling)
186 	 */
187 	sched_tx_processing(bdev);
188 
189 	return err;
190 }
191