| 413 | | uint32 type = transfer->TransferPipe()->Type(); |
| 414 | | if ((type & USB_OBJECT_CONTROL_PIPE) > 0 |
| 415 | | || (type & USB_OBJECT_BULK_PIPE) > 0) { |
| 416 | | TRACE(("usb_ehci: submitting async transfer\n")); |
| 417 | | return SubmitAsyncTransfer(transfer); |
| 418 | | } |
| 419 | | |
| 420 | | if ((type & USB_OBJECT_INTERRUPT_PIPE) > 0 |
| 421 | | || (type & USB_OBJECT_ISO_PIPE) > 0) { |
| 422 | | TRACE(("usb_ehci: submitting periodic transfer\n")); |
| 423 | | return SubmitPeriodicTransfer(transfer); |
| 424 | | } |
| 425 | | |
| 426 | | TRACE_ERROR(("usb_ehci: tried to submit transfer for unknown pipe type %lu\n", type)); |
| 427 | | return B_ERROR; |
| 428 | | } |
| 429 | | |
| 430 | | |
| 431 | | status_t |
| 432 | | EHCI::SubmitAsyncTransfer(Transfer *transfer) |
| 433 | | { |
| | 413 | Pipe *pipe = transfer->TransferPipe(); |
| | 414 | if (pipe->Type() & USB_OBJECT_ISO_PIPE) { |
| | 415 | // ToDo: implement isochronous transfers... |
| | 416 | return B_ERROR; |
| | 417 | } |
| | 418 | |
| 477 | | TRACE_ERROR(("usb_ehci: failed to link queue head to the async list\n")); |
| 478 | | FreeQueueHead(queueHead); |
| 479 | | return result; |
| 480 | | } |
| 481 | | |
| 482 | | return B_OK; |
| 483 | | } |
| 484 | | |
| 485 | | |
| 486 | | status_t |
| 487 | | EHCI::SubmitPeriodicTransfer(Transfer *transfer) |
| 488 | | { |
| 489 | | Pipe *pipe = transfer->TransferPipe(); |
| 490 | | if ((pipe->Type() & USB_OBJECT_INTERRUPT_PIPE) == 0) |
| 491 | | return B_ERROR; |
| 492 | | |
| 493 | | ehci_qh *queueHead = CreateQueueHead(); |
| 494 | | if (!queueHead) { |
| 495 | | TRACE_ERROR(("usb_ehci: failed to allocate periodic queue head\n")); |
| 496 | | return B_NO_MEMORY; |
| 497 | | } |
| 498 | | |
| 499 | | status_t result = InitQueueHead(queueHead, pipe); |
| 500 | | if (result < B_OK) { |
| 501 | | TRACE_ERROR(("usb_ehci: failed to init queue head\n")); |
| 502 | | FreeQueueHead(queueHead); |
| 503 | | return result; |
| 504 | | } |
| 505 | | |
| 506 | | bool directionIn; |
| 507 | | ehci_qtd *dataDescriptor; |
| 508 | | result = FillQueueWithData(transfer, queueHead, &dataDescriptor, |
| 509 | | &directionIn); |
| 510 | | |
| 511 | | if (result < B_OK) { |
| 512 | | TRACE_ERROR(("usb_ehci: failed to fill transfer queue with data\n")); |
| 513 | | FreeQueueHead(queueHead); |
| 514 | | return result; |
| 515 | | } |
| 516 | | |
| 517 | | result = AddPendingTransfer(transfer, queueHead, dataDescriptor, directionIn); |
| 518 | | if (result < B_OK) { |
| 519 | | TRACE_ERROR(("usb_ehci: failed to add pending transfer\n")); |
| 520 | | FreeQueueHead(queueHead); |
| 521 | | return result; |
| 522 | | } |
| 523 | | |
| 524 | | #ifdef TRACE_USB |
| 525 | | TRACE(("usb_ehci: linking interrupt queue\n")); |
| 526 | | print_queue(queueHead); |
| 527 | | #endif |
| 528 | | |
| 529 | | result = LinkInterruptQueueHead(queueHead, |
| 530 | | ((InterruptPipe *)pipe)->Interval()); |
| 531 | | if (result < B_OK) { |
| 532 | | TRACE_ERROR(("usb_ehci: failed to link queue head to the async list\n")); |
| | 467 | TRACE_ERROR(("usb_ehci: failed to link queue head\n")); |