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