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 "h2transactions.h" 9 10 #include <bluetooth/HCI/btHCI.h> 11 #include <bluetooth/HCI/btHCI_event.h> 12 #include <bluetooth/HCI/btHCI_acl.h> 13 14 #include <ByteOrder.h> 15 #include <kernel.h> 16 #include <string.h> 17 18 #include "h2debug.h" 19 #include "h2generic.h" 20 #include "h2upper.h" 21 #include "h2util.h" 22 23 24 //#define DUMP_BUFFERS 25 26 /* Forward declaration */ 27 28 void acl_tx_complete(void* cookie, status_t status, void* data, size_t actual_len); 29 void acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len); 30 void command_complete(void* cookie, status_t status, void* data, size_t actual_len); 31 void event_complete(void* cookie, status_t status, void* data, size_t actual_len); 32 33 34 static status_t 35 assembly_rx(bt_usb_dev* bdev, bt_packet_t type, void* data, int count) 36 { 37 bdev->stat.bytesRX += count; 38 39 return btDevices->PostTransportPacket(bdev->hdev, type, data, count); 40 41 } 42 43 44 #if 0 45 #pragma mark --- RX Complete --- 46 #endif 47 48 void 49 event_complete(void* cookie, status_t status, void* data, size_t actual_len) 50 { 51 bt_usb_dev* bdev = (bt_usb_dev*)cookie; 52 // bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option 53 status_t error; 54 55 TRACE("%s: cookie@%p status=%s len=%" B_PRIuSIZE "\n", __func__, cookie, 56 strerror(status), actual_len); 57 58 if (bdev == NULL) 59 return; 60 61 if (status == B_CANCELED || status == B_DEV_CRC_ERROR) 62 return; // or not running anymore... 63 64 if (status != B_OK || actual_len == 0) 65 goto resubmit; 66 67 if (assembly_rx(bdev, BT_EVENT, data, actual_len) == B_OK) { 68 bdev->stat.successfulTX++; 69 } else { 70 bdev->stat.errorRX++; 71 } 72 73 resubmit: 74 75 error = usb->queue_interrupt(bdev->intr_in_ep->handle, data, 76 max_c(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in), 77 event_complete, bdev); 78 79 if (error != B_OK) { 80 reuse_room(&bdev->eventRoom, data); 81 bdev->stat.rejectedRX++; 82 ERROR("%s: RX event resubmittion failed %s\n", __func__, 83 strerror(error)); 84 } else { 85 bdev->stat.acceptedRX++; 86 } 87 } 88 89 90 void 91 acl_rx_complete(void* cookie, status_t status, void* data, size_t actual_len) 92 { 93 bt_usb_dev* bdev = (bt_usb_dev*)cookie; 94 // bt_usb_dev* bdev = fetch_device(cookie, 0); -> safer / slower option 95 status_t error; 96 97 if (bdev == NULL) 98 return; 99 100 if (status == B_CANCELED || status == B_DEV_CRC_ERROR) 101 return; // or not running anymore... 102 103 if (status != B_OK || actual_len == 0) 104 goto resubmit; 105 106 if (assembly_rx(bdev, BT_ACL, data, actual_len) == B_OK) { 107 bdev->stat.successfulRX++; 108 } else { 109 bdev->stat.errorRX++; 110 } 111 112 resubmit: 113 114 error = usb->queue_bulk(bdev->bulk_in_ep->handle, data, 115 max_c(HCI_MAX_FRAME_SIZE, bdev->max_packet_size_bulk_in), 116 acl_rx_complete, (void*) bdev); 117 118 if (error != B_OK) { 119 reuse_room(&bdev->aclRoom, data); 120 bdev->stat.rejectedRX++; 121 ERROR("%s: RX acl resubmittion failed %s\n", __func__, strerror(error)); 122 } else { 123 bdev->stat.acceptedRX++; 124 } 125 } 126 127 128 #if 0 129 #pragma mark --- RX --- 130 #endif 131 132 status_t 133 submit_rx_event(bt_usb_dev* bdev) 134 { 135 size_t size = max_c(HCI_MAX_EVENT_SIZE, bdev->max_packet_size_intr_in); 136 void* buf = alloc_room(&bdev->eventRoom, size); 137 status_t status; 138 139 if (buf == NULL) 140 return ENOMEM; 141 142 status = usb->queue_interrupt(bdev->intr_in_ep->handle, buf, size, 143 event_complete, (void*)bdev); 144 145 if (status != B_OK) { 146 reuse_room(&bdev->eventRoom, buf); // reuse allocated one 147 bdev->stat.rejectedRX++; 148 } else { 149 bdev->stat.acceptedRX++; 150 TRACE("%s: Accepted RX Event %d\n", __func__, bdev->stat.acceptedRX); 151 } 152 153 return status; 154 } 155 156 157 status_t 158 submit_rx_acl(bt_usb_dev* bdev) 159 { 160 size_t size = max_c(HCI_MAX_FRAME_SIZE, bdev->max_packet_size_bulk_in); 161 void* buf = alloc_room(&bdev->aclRoom, size); 162 status_t status; 163 164 if (buf == NULL) 165 return ENOMEM; 166 167 status = usb->queue_bulk(bdev->bulk_in_ep->handle, buf, size, 168 acl_rx_complete, bdev); 169 170 if (status != B_OK) { 171 reuse_room(&bdev->aclRoom, buf); // reuse allocated 172 bdev->stat.rejectedRX++; 173 } else { 174 bdev->stat.acceptedRX++; 175 } 176 177 return status; 178 } 179 180 181 status_t 182 submit_rx_sco(bt_usb_dev* bdev) 183 { 184 // not yet implemented 185 return B_ERROR; 186 } 187 188 189 #if 0 190 #pragma mark --- TX Complete --- 191 #endif 192 193 void 194 command_complete(void* cookie, status_t status, void* data, size_t actual_len) 195 { 196 snet_buffer* snbuf = (snet_buffer*)cookie; 197 bt_usb_dev* bdev = (bt_usb_dev*)snb_cookie(snbuf); 198 199 TRACE("%s: len = %" B_PRIuSIZE " @%p\n", __func__, actual_len, data); 200 201 if (status == B_OK) { 202 bdev->stat.successfulTX++; 203 bdev->stat.bytesTX += actual_len; 204 } else { 205 bdev->stat.errorTX++; 206 // the packet has been lost, too late to requeue it 207 } 208 209 snb_park(&bdev->snetBufferRecycleTrash, snbuf); 210 211 #ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS 212 // TODO: check just the empty queues 213 schedTxProcessing(bdev); 214 #endif 215 } 216 217 218 void 219 acl_tx_complete(void* cookie, status_t status, void* data, size_t actual_len) 220 { 221 net_buffer* nbuf = (net_buffer*)cookie; 222 bt_usb_dev* bdev = GET_DEVICE(nbuf); 223 224 //debugf("fetched=%p type %lx %p\n", bdev, nbuf->type, data); 225 226 if (status == B_OK) { 227 bdev->stat.successfulTX++; 228 bdev->stat.bytesTX += actual_len; 229 } else { 230 bdev->stat.errorTX++; 231 // the packet has been lost, too late to requeue it 232 } 233 234 nb_destroy(nbuf); 235 236 #ifdef BT_RESCHEDULING_AFTER_COMPLETITIONS 237 schedTxProcessing(bdev); 238 #endif 239 } 240 241 242 #if 0 243 #pragma mark --- TX --- 244 #endif 245 246 status_t 247 submit_tx_command(bt_usb_dev* bdev, snet_buffer* snbuf) 248 { 249 uint8 bRequestType = bdev->ctrl_req; 250 uint8 bRequest = 0; 251 uint16 wIndex = 0; 252 uint16 value = 0; 253 uint16 wLength = B_HOST_TO_LENDIAN_INT16(snb_size(snbuf)); 254 status_t error; 255 256 if (!GET_BIT(bdev->state, RUNNING)) { 257 return B_DEV_NOT_READY; 258 } 259 260 // set cookie 261 snb_set_cookie(snbuf, bdev); 262 263 TRACE("%s: @%p\n", __func__, snb_get(snbuf)); 264 265 error = usb->queue_request(bdev->dev, bRequestType, bRequest, 266 value, wIndex, wLength, snb_get(snbuf), 267 command_complete, (void*) snbuf); 268 269 if (error != B_OK) { 270 bdev->stat.rejectedTX++; 271 } else { 272 bdev->stat.acceptedTX++; 273 } 274 275 return error; 276 } 277 278 279 status_t 280 submit_tx_acl(bt_usb_dev* bdev, net_buffer* nbuf) 281 { 282 status_t error; 283 284 // set cookie 285 SET_DEVICE(nbuf, bdev->hdev); 286 287 if (!GET_BIT(bdev->state, RUNNING)) { 288 return B_DEV_NOT_READY; 289 } 290 /* 291 debugf("### Outgoing ACL: len = %ld\n", nbuf->size); 292 for (uint32 index = 0 ; index < nbuf->size; index++ ) { 293 dprintf("%x:",((uint8*)nb_get_whole_buffer(nbuf))[index]); 294 } 295 */ 296 297 error = usb->queue_bulk(bdev->bulk_out_ep->handle, nb_get_whole_buffer(nbuf), 298 nbuf->size, acl_tx_complete, (void*)nbuf); 299 300 if (error != B_OK) { 301 bdev->stat.rejectedTX++; 302 } else { 303 bdev->stat.acceptedTX++; 304 } 305 306 return error; 307 } 308 309 310 status_t 311 submit_tx_sco(bt_usb_dev* bdev) 312 { 313 314 if (!GET_BIT(bdev->state, RUNNING)) { 315 return B_DEV_NOT_READY; 316 } 317 318 // not yet implemented 319 return B_ERROR; 320 } 321