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