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