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