1 /* 2 * Copyright 2003-2006, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 * Niels S. Reedijk 8 */ 9 10 #include <util/kernel_cpp.h> 11 #include "usb_p.h" 12 #include <USB_rle.h> 13 14 15 Stack *gUSBStack = NULL; 16 17 18 static int32 19 bus_std_ops(int32 op, ...) 20 { 21 switch (op) { 22 case B_MODULE_INIT: { 23 if (gUSBStack) 24 return B_OK; 25 26 void *address = NULL; 27 area_id shared = find_area("shared usb stack"); 28 if (shared >= B_OK && clone_area("usb stack clone", &address, 29 B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA, shared) >= B_OK) { 30 gUSBStack = *((Stack **)address); 31 return B_OK; 32 } 33 34 #ifdef TRACE_USB 35 set_dprintf_enabled(true); 36 load_driver_symbols("usb"); 37 TRACE(("usb_module: init\n")); 38 #endif 39 Stack *stack = new(std::nothrow) Stack(); 40 if (!stack) 41 return B_NO_MEMORY; 42 43 if (stack->InitCheck() != B_OK) { 44 delete stack; 45 return ENODEV; 46 } 47 48 gUSBStack = stack; 49 shared = create_area("shared usb stack", &address, 50 B_ANY_KERNEL_ADDRESS, B_PAGE_SIZE, B_NO_LOCK, 51 B_KERNEL_WRITE_AREA); 52 if (shared >= B_OK) { 53 *((Stack **)address) = gUSBStack; 54 return B_OK; 55 } 56 break; 57 } 58 59 case B_MODULE_UNINIT: 60 TRACE(("usb_module: uninit\n")); 61 delete gUSBStack; 62 gUSBStack = NULL; 63 break; 64 65 default: 66 return EINVAL; 67 } 68 69 return B_OK; 70 } 71 72 73 status_t 74 register_driver(const char *driverName, 75 const usb_support_descriptor *descriptors, 76 size_t count, const char *optionalRepublishDriverName) 77 { 78 return gUSBStack->RegisterDriver(driverName, descriptors, count, 79 optionalRepublishDriverName); 80 } 81 82 83 status_t 84 install_notify(const char *driverName, const usb_notify_hooks *hooks) 85 { 86 return gUSBStack->InstallNotify(driverName, hooks); 87 } 88 89 90 status_t 91 uninstall_notify(const char *driverName) 92 { 93 return gUSBStack->UninstallNotify(driverName); 94 } 95 96 97 const usb_device_descriptor * 98 get_device_descriptor(usb_device device) 99 { 100 TRACE(("usb_module: get_device_descriptor(%ld)\n", device)); 101 Object *object = gUSBStack->GetObject(device); 102 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 103 return NULL; 104 105 return ((Device *)object)->DeviceDescriptor(); 106 } 107 108 109 const usb_configuration_info * 110 get_nth_configuration(usb_device device, uint index) 111 { 112 TRACE(("usb_module: get_nth_configuration(%ld, %d)\n", device, index)); 113 Object *object = gUSBStack->GetObject(device); 114 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 115 return NULL; 116 117 return ((Device *)object)->ConfigurationAt((int32)index); 118 } 119 120 121 const usb_configuration_info * 122 get_configuration(usb_device device) 123 { 124 TRACE(("usb_module: get_configuration(%ld)\n", device)); 125 Object *object = gUSBStack->GetObject(device); 126 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 127 return NULL; 128 129 return ((Device *)object)->Configuration(); 130 } 131 132 133 status_t 134 set_configuration(usb_device device, 135 const usb_configuration_info *configuration) 136 { 137 TRACE(("usb_module: set_configuration(%ld, 0x%08lx)\n", device, configuration)); 138 Object *object = gUSBStack->GetObject(device); 139 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 140 return B_DEV_INVALID_PIPE; 141 142 return ((Device *)object)->SetConfiguration(configuration); 143 } 144 145 146 status_t 147 set_alt_interface(usb_device device, const usb_interface_info *interface) 148 { 149 TRACE(("usb_module: set_alt_interface(%ld, 0x%08lx)\n", device, interface)); 150 Object *object = gUSBStack->GetObject(device); 151 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 152 return B_DEV_INVALID_PIPE; 153 154 return ((Device *)object)->SetAltInterface(interface); 155 } 156 157 158 status_t 159 set_feature(usb_id handle, uint16 selector) 160 { 161 TRACE(("usb_module: set_feature(%ld, %d)\n", handle, selector)); 162 Object *object = gUSBStack->GetObject(handle); 163 if (!object) 164 return B_DEV_INVALID_PIPE; 165 166 return object->SetFeature(selector); 167 } 168 169 170 status_t 171 clear_feature(usb_id handle, uint16 selector) 172 { 173 TRACE(("usb_module: clear_feature(%ld, %d)\n", handle, selector)); 174 Object *object = gUSBStack->GetObject(handle); 175 if (!object) 176 return B_DEV_INVALID_PIPE; 177 178 return object->ClearFeature(selector); 179 } 180 181 182 status_t 183 get_status(usb_id handle, uint16 *status) 184 { 185 TRACE(("usb_module: get_status(%ld, 0x%08lx)\n", handle, status)); 186 if (!status) 187 return B_BAD_VALUE; 188 189 Object *object = gUSBStack->GetObject(handle); 190 if (!object) 191 return B_DEV_INVALID_PIPE; 192 193 return object->GetStatus(status); 194 } 195 196 197 status_t 198 get_descriptor(usb_device device, uint8 type, uint8 index, uint16 languageID, 199 void *data, size_t dataLength, size_t *actualLength) 200 { 201 TRACE(("usb_module: get_descriptor(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%08lx, %ld, 0x%08lx)\n", device, type, index, languageID, data, dataLength, actualLength)); 202 Object *object = gUSBStack->GetObject(device); 203 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 204 return B_DEV_INVALID_PIPE; 205 206 return ((Device *)object)->GetDescriptor(type, index, languageID, 207 data, dataLength, actualLength); 208 } 209 210 211 status_t 212 send_request(usb_device device, uint8 requestType, uint8 request, 213 uint16 value, uint16 index, uint16 length, void *data, size_t *actualLength) 214 { 215 TRACE(("usb_module: send_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %d, 0x%08lx, 0x%08lx)\n", device, requestType, request, value, index, length, data, actualLength)); 216 Object *object = gUSBStack->GetObject(device); 217 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 218 return B_DEV_INVALID_PIPE; 219 220 return ((Device *)object)->DefaultPipe()->SendRequest(requestType, request, 221 value, index, length, data, length, actualLength); 222 } 223 224 225 status_t 226 queue_request(usb_device device, uint8 requestType, uint8 request, 227 uint16 value, uint16 index, uint16 length, void *data, 228 usb_callback_func callback, void *callbackCookie) 229 { 230 TRACE(("usb_module: queue_request(%ld, 0x%02x, 0x%02x, 0x%04x, 0x%04x, %ld, 0x%08lx, 0x%08lx, 0x%08lx)\n", device, requestType, request, value, index, length, data, callback, callbackCookie)); 231 Object *object = gUSBStack->GetObject(device); 232 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 233 return B_DEV_INVALID_PIPE; 234 235 return ((Device *)object)->DefaultPipe()->QueueRequest(requestType, 236 request, value, index, length, data, length, callback, callbackCookie); 237 } 238 239 240 status_t 241 queue_interrupt(usb_pipe pipe, void *data, size_t dataLength, 242 usb_callback_func callback, void *callbackCookie) 243 { 244 TRACE(("usb_module: queue_interrupt(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, callback, callbackCookie)); 245 Object *object = gUSBStack->GetObject(pipe); 246 if (!object || (object->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) 247 return B_DEV_INVALID_PIPE; 248 249 return ((InterruptPipe *)object)->QueueInterrupt(data, dataLength, callback, 250 callbackCookie); 251 } 252 253 254 status_t 255 queue_bulk(usb_pipe pipe, void *data, size_t dataLength, 256 usb_callback_func callback, void *callbackCookie) 257 { 258 TRACE(("usb_module: queue_bulk(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, callback, callbackCookie)); 259 Object *object = gUSBStack->GetObject(pipe); 260 if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 261 return B_DEV_INVALID_PIPE; 262 263 return ((BulkPipe *)object)->QueueBulk(data, dataLength, callback, 264 callbackCookie); 265 } 266 267 268 status_t 269 queue_bulk_v(usb_pipe pipe, iovec *vector, size_t vectorCount, 270 usb_callback_func callback, void *callbackCookie) 271 { 272 TRACE(("usb_module: queue_bulk(%ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx)\n", pipe, vector, vectorCount, callback, callbackCookie)); 273 Object *object = gUSBStack->GetObject(pipe); 274 if (!object || (object->Type() & USB_OBJECT_BULK_PIPE) == 0) 275 return B_DEV_INVALID_PIPE; 276 277 return ((BulkPipe *)object)->QueueBulkV(vector, vectorCount, callback, 278 callbackCookie); 279 } 280 281 282 status_t 283 queue_isochronous(usb_pipe pipe, void *data, size_t dataLength, 284 usb_iso_packet_descriptor *packetDesc, uint32 packetCount, 285 uint32 *startingFrameNumber, uint32 flags, usb_callback_func callback, 286 void *callbackCookie) 287 { 288 TRACE(("usb_module: queue_isochronous(%ld, 0x%08lx, %ld, 0x%08lx, %ld, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n", pipe, data, dataLength, packetDesc, packetCount, startingFrameNumber, flags, callback, callbackCookie)); 289 Object *object = gUSBStack->GetObject(pipe); 290 if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 291 return B_DEV_INVALID_PIPE; 292 293 return ((IsochronousPipe *)object)->QueueIsochronous(data, dataLength, 294 packetDesc, packetCount, startingFrameNumber, flags, callback, 295 callbackCookie); 296 } 297 298 299 status_t 300 set_pipe_policy(usb_pipe pipe, uint8 maxQueuedPackets, 301 uint16 maxBufferDurationMS, uint16 sampleSize) 302 { 303 TRACE(("usb_module: set_pipe_policy(%ld, %d, %d, %d)\n", pipe, maxQueuedPackets, maxBufferDurationMS, sampleSize)); 304 Object *object = gUSBStack->GetObject(pipe); 305 if (!object || (object->Type() & USB_OBJECT_ISO_PIPE) == 0) 306 return B_DEV_INVALID_PIPE; 307 308 return ((IsochronousPipe *)object)->SetPipePolicy(maxQueuedPackets, 309 maxBufferDurationMS, sampleSize); 310 } 311 312 313 status_t 314 cancel_queued_transfers(usb_pipe pipe) 315 { 316 TRACE(("usb_module: cancel_queued_transfers(%ld)\n", pipe)); 317 Object *object = gUSBStack->GetObject(pipe); 318 if (!object || (object->Type() & USB_OBJECT_PIPE) == 0) 319 return B_DEV_INVALID_PIPE; 320 321 return ((Pipe *)object)->CancelQueuedTransfers(false); 322 } 323 324 325 status_t 326 usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) 327 { 328 TRACE(("usb_module: usb_ioctl(0x%08lx, 0x%08lx, %ld)\n", opcode, buffer, bufferSize)); 329 330 switch (opcode) { 331 case 'DNAM': { 332 Object *object = gUSBStack->GetObject(*(usb_id *)buffer); 333 if (!object || (object->Type() & USB_OBJECT_DEVICE) == 0) 334 return B_BAD_VALUE; 335 336 uint32 index = 0; 337 return ((Device *)object)->BuildDeviceName((char *)buffer, &index, 338 bufferSize, NULL); 339 } 340 } 341 342 return B_DEV_INVALID_IOCTL; 343 } 344 345 346 /* 347 This module exports the USB API v3 348 */ 349 struct usb_module_info gModuleInfoV3 = { 350 // First the bus_manager_info: 351 { 352 { 353 "bus_managers/usb/v3", 354 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 355 bus_std_ops 356 }, 357 NULL // the rescan function 358 }, 359 360 register_driver, // register_driver 361 install_notify, // install_notify 362 uninstall_notify, // uninstall_notify 363 get_device_descriptor, // get_device_descriptor 364 get_nth_configuration, // get_nth_configuration 365 get_configuration, // get_configuration 366 set_configuration, // set_configuration 367 set_alt_interface, // set_alt_interface 368 set_feature, // set_feature 369 clear_feature, // clear_feature 370 get_status, // get_status 371 get_descriptor, // get_descriptor 372 send_request, // send_request 373 queue_interrupt, // queue_interrupt 374 queue_bulk, // queue_bulk 375 queue_bulk_v, // queue_bulk_v 376 queue_isochronous, // queue_isochronous 377 queue_request, // queue_request 378 set_pipe_policy, // set_pipe_policy 379 cancel_queued_transfers, // cancel_queued_transfers 380 usb_ioctl // usb_ioctl 381 }; 382 383 384 // 385 // #pragma mark - 386 // 387 388 389 const usb_device_descriptor * 390 get_device_descriptor_v2(const void *device) 391 { 392 return get_device_descriptor((usb_id)device); 393 } 394 395 396 const usb_configuration_info * 397 get_nth_configuration_v2(const void *device, uint index) 398 { 399 return get_nth_configuration((usb_id)device, index); 400 } 401 402 403 const usb_configuration_info * 404 get_configuration_v2(const void *device) 405 { 406 return get_configuration((usb_id)device); 407 } 408 409 410 status_t 411 set_configuration_v2(const void *device, 412 const usb_configuration_info *configuration) 413 { 414 return set_configuration((usb_id)device, configuration); 415 } 416 417 418 status_t 419 set_alt_interface_v2(const void *device, const usb_interface_info *interface) 420 { 421 return set_alt_interface((usb_id)device, interface); 422 } 423 424 425 status_t 426 set_feature_v2(const void *object, uint16 selector) 427 { 428 return set_feature((usb_id)object, selector); 429 } 430 431 432 status_t 433 clear_feature_v2(const void *object, uint16 selector) 434 { 435 return clear_feature((usb_id)object, selector); 436 } 437 438 439 status_t 440 get_status_v2(const void *object, uint16 *status) 441 { 442 return get_status((usb_id)object, status); 443 } 444 445 446 status_t 447 get_descriptor_v2(const void *device, uint8 type, uint8 index, 448 uint16 languageID, void *data, size_t dataLength, size_t *actualLength) 449 { 450 return get_descriptor((usb_id)device, type, index, languageID, data, 451 dataLength, actualLength); 452 } 453 454 455 status_t 456 send_request_v2(const void *device, uint8 requestType, uint8 request, 457 uint16 value, uint16 index, uint16 length, void *data, 458 size_t /*dataLength*/, size_t *actualLength) 459 { 460 return send_request((usb_id)device, requestType, request, value, index, 461 length, data, actualLength); 462 } 463 464 465 status_t 466 queue_request_v2(const void *device, uint8 requestType, uint8 request, 467 uint16 value, uint16 index, uint16 length, void *data, 468 size_t /*dataLength*/, usb_callback_func callback, void *callbackCookie) 469 { 470 return queue_request((usb_id)device, requestType, request, value, index, 471 length, data, callback, callbackCookie); 472 } 473 474 475 status_t 476 queue_interrupt_v2(const void *pipe, void *data, size_t dataLength, 477 usb_callback_func callback, void *callbackCookie) 478 { 479 return queue_interrupt((usb_id)pipe, data, dataLength, callback, 480 callbackCookie); 481 } 482 483 484 status_t 485 queue_bulk_v2(const void *pipe, void *data, size_t dataLength, 486 usb_callback_func callback, void *callbackCookie) 487 { 488 return queue_bulk((usb_id)pipe, data, dataLength, callback, 489 callbackCookie); 490 } 491 492 493 status_t 494 queue_isochronous_v2(const void *pipe, void *data, size_t dataLength, 495 rlea *rleArray, uint16 bufferDurationMS, usb_callback_func callback, 496 void *callbackCookie) 497 { 498 // ToDo: convert rlea to usb_iso_packet_descriptor 499 // ToDo: use a flag to indicate that the callback shall produce a rlea 500 usb_iso_packet_descriptor *packetDesc = NULL; 501 return queue_isochronous((usb_id)pipe, data, dataLength, packetDesc, 0, 502 NULL, 0, callback, callbackCookie); 503 } 504 505 506 status_t 507 set_pipe_policy_v2(const void *pipe, uint8 maxQueuedPackets, 508 uint16 maxBufferDurationMS, uint16 sampleSize) 509 { 510 return set_pipe_policy((usb_id)pipe, maxQueuedPackets, maxBufferDurationMS, 511 sampleSize); 512 } 513 514 515 status_t 516 cancel_queued_transfers_v2(const void *pipe) 517 { 518 return cancel_queued_transfers((usb_id)pipe); 519 } 520 521 522 struct usb_module_info_v2 { 523 bus_manager_info binfo; 524 status_t (*register_driver)(const char *, const usb_support_descriptor *, size_t, const char *); 525 status_t (*install_notify)(const char *, const usb_notify_hooks *); 526 status_t (*uninstall_notify)(const char *); 527 const usb_device_descriptor *(*get_device_descriptor)(const void *); 528 const usb_configuration_info *(*get_nth_configuration)(const void *, uint); 529 const usb_configuration_info *(*get_configuration)(const void *); 530 status_t (*set_configuration)(const void *, const usb_configuration_info *); 531 status_t (*set_alt_interface)(const void *, const usb_interface_info *); 532 status_t (*set_feature)(const void *, uint16); 533 status_t (*clear_feature)(const void *, uint16); 534 status_t (*get_status)(const void *, uint16 *); 535 status_t (*get_descriptor)(const void *, uint8, uint8, uint16, void *, size_t, size_t *); 536 status_t (*send_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, size_t *); 537 status_t (*queue_interrupt)(const void *, void *, size_t, usb_callback_func, void *); 538 status_t (*queue_bulk)(const void *, void *, size_t, usb_callback_func, void *); 539 status_t (*queue_isochronous)(const void *, void *, size_t, rlea *, uint16, usb_callback_func, void *); 540 status_t (*queue_request)(const void *, uint8, uint8, uint16, uint16, uint16, void *, size_t, usb_callback_func, void *); 541 status_t (*set_pipe_policy)(const void *, uint8, uint16, uint16); 542 status_t (*cancel_queued_transfers)(const void *); 543 status_t (*usb_ioctl)(uint32 opcode, void *,size_t); 544 }; 545 546 547 /* 548 This module exports the USB API v2 549 */ 550 struct usb_module_info_v2 gModuleInfoV2 = { 551 // First the bus_manager_info: 552 { 553 { 554 "bus_managers/usb/v2", 555 B_KEEP_LOADED, // Keep loaded, even if no driver requires it 556 bus_std_ops 557 }, 558 NULL // the rescan function 559 }, 560 561 register_driver, // register_driver 562 install_notify, // install_notify 563 uninstall_notify, // uninstall_notify 564 get_device_descriptor_v2, // get_device_descriptor 565 get_nth_configuration_v2, // get_nth_configuration 566 get_configuration_v2, // get_configuration 567 set_configuration_v2, // set_configuration 568 set_alt_interface_v2, // set_alt_interface 569 set_feature_v2, // set_feature 570 clear_feature_v2, // clear_feature 571 get_status_v2, // get_status 572 get_descriptor_v2, // get_descriptor 573 send_request_v2, // send_request 574 queue_interrupt_v2, // queue_interrupt 575 queue_bulk_v2, // queue_bulk 576 queue_isochronous_v2, // queue_isochronous 577 queue_request_v2, // queue_request 578 set_pipe_policy_v2, // set_pipe_policy 579 cancel_queued_transfers_v2, // cancel_queued_transfers 580 usb_ioctl // usb_ioctl 581 }; 582 583 584 // 585 // #pragma mark - 586 // 587 588 589 module_info *modules[] = { 590 (module_info *)&gModuleInfoV2, 591 (module_info *)&gModuleInfoV3, 592 NULL 593 }; 594