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