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