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