[haiku-commits] haiku: hrev45972 - src/add-ons/kernel/drivers/audio/usb_audio src/add-ons/kernel/drivers/audio/usb src/add-ons/kernel/busses/usb headers/os/drivers/usb

  • From: zharik@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 18 Aug 2013 15:14:40 +0200 (CEST)

hrev45972 adds 12 changesets to branch 'master'
old head: 883b8dd0b9be3798b6cf822c9a64470a63fc1afa
new head: a69892cadca9288b901ac66273d342bfb4329373
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=a69892c+%5E883b8dd

----------------------------------------------------------------------------

cf58476: USB OHCI: Support for isochronous transfers
  
  Finishing and refactoring the draft, initially implemented during April-May 
2012
  
  NOTE: startingFrameNumber returned to device contains the number of the
  next free frame right after the last packed of submitted data. For more
  details please Look into corresponding [haiku-development] discussion
  started at 03 Jul 2013.
  
  Partially fixes #1045.

291e40c: USB OHCI: Fix finalizing of STALL-ed control request transfers
  
  In case control transfer is finished with STALL answer from device only
  the setup TD is retired into the Done Queue but other TDs (data and
  status) are left in the ED queue. HC set the endpoint halted - so we
  process such endpoint regardless of it's non-empty queue.
  
  PS: cleanup some trailing spaces.

2cc4703: Fix and force USB audio driver to work with new OHCI module
  
  * some functionality like recording temporarily disabled;
  * set the endpoint speed call added;
  * packet size hard-coded for 48kHz case;
  * draft support for formats and sampling rate handling;
  * implement sampling rate change on the fly;
  * optimized using of starting frame;
  * fix user_memory in buffer exchaqnge call;
  * fix exchanged buffer recoriding processing;
  * debug tweaks, fix current buffer switching;
  * cleanup, cleanup, cleanup...

673ef2c: USB audio: cleanup and codestyle fixes.
  
  * cleanup and codestyle fixes;
  * AudioFunction module contents purged out as unused.

b42544e: USB audio: fInsideNotify guard added to Remote/Close callbacks

1a6d941: USB audio: Use system-wide USB_audio.h instead local one
  
  * switching driver code to use system usb/USB_audio.h header;
  * refactor USB_audio.h specification header for both USB audio specifications.

7ff9cd3: USB audio: Refactor TRACE-es for more configurability

a8066fe: USB audio: dev.entry number should be 1-based, etc
  
  * USB audio device entry number made 1-based instead of 0. According to
    Haiku MultiAudio specs audio device entries should be 1-based but
    0-based;
  * cleanup and refactoring. No functional changes;
  * recording stream activated;
  * fix input channels description report and codestyle issues.

353a4e0: USB audio: Fix function of Selector Unit control
  
  * restore function of Selector Unit that was previously disabled;
  * fix Selector Unit input pin names "Unknwon" case.

743d759: USB audio: Mixer Unit control implementation
  
  * support of Mixer Unit control in UI implemented;
  * improve SetMix/GetMix to support Mixer Unit control type;
  * cleanup and improvements.

14f9200: USB audio: use new(std::nothrow) for allocations
  
  * Use new(std::nothrow) for allocations;
  * Input buffer index counter restored;
  * Improve unsupported UI controls debug info tracing;
  * Some cleanup.

a69892c: Rename driver folder 'usb_audio' to 'usb'
  
  ... just because the source path ./kernel/drivers/audio/usb obviously
  references audio hardware so "_audio" suffix is excessive.
  
  No functional changes.

                                        [ Siarzhuk Zharski <zharik@xxxxxx> ]

----------------------------------------------------------------------------

36 files changed, 5898 insertions(+), 6658 deletions(-)
headers/os/drivers/USB_spec.h                    |   13 +
headers/os/drivers/usb/USB_audio.h               |  500 ++++-
src/add-ons/kernel/busses/usb/ohci.cpp           |  794 ++++++-
src/add-ons/kernel/busses/usb/ohci.h             |   61 +-
src/add-ons/kernel/busses/usb/ohci.rdef          |    2 +-
src/add-ons/kernel/busses/usb/ohci_hardware.h    |   33 +-
src/add-ons/kernel/drivers/audio/Jamfile         |    2 +-
.../drivers/audio/usb/AudioControlInterface.cpp  | 2059 ++++++++++++++++++
.../drivers/audio/usb/AudioControlInterface.h    |  352 +++
.../audio/usb/AudioStreamingInterface.cpp        |  516 +++++
.../drivers/audio/usb/AudioStreamingInterface.h  |  162 ++
src/add-ons/kernel/drivers/audio/usb/Device.cpp  |  667 ++++++
src/add-ons/kernel/drivers/audio/usb/Device.h    |   88 +
.../drivers/audio/{usb_audio => usb}/Driver.cpp  |  118 +-
.../drivers/audio/{usb_audio => usb}/Driver.h    |   29 +-
.../drivers/audio/{usb_audio => usb}/Jamfile     |    7 +-
.../audio/{usb_audio => usb}/Settings.cpp        |   41 +-
src/add-ons/kernel/drivers/audio/usb/Settings.h  |   40 +
src/add-ons/kernel/drivers/audio/usb/Stream.cpp  |  537 +++++
src/add-ons/kernel/drivers/audio/usb/Stream.h    |   74 +
.../kernel/drivers/audio/usb/usb_audio.settings  |   36 +
.../audio/usb_audio/AudioControlInterface.cpp    | 1711 ---------------
.../audio/usb_audio/AudioControlInterface.h      |  319 ---
.../drivers/audio/usb_audio/AudioFunction.cpp    | 1092 ----------
.../drivers/audio/usb_audio/AudioFunction.h      |  349 ---
.../audio/usb_audio/AudioStreamingInterface.cpp  |  406 ----
.../audio/usb_audio/AudioStreamingInterface.h    |  156 --
.../kernel/drivers/audio/usb_audio/Device.cpp    |  778 -------
.../kernel/drivers/audio/usb_audio/Device.h      |  139 --
.../kernel/drivers/audio/usb_audio/Settings.h    |   34 -
.../kernel/drivers/audio/usb_audio/Stream.cpp    |  528 -----
.../kernel/drivers/audio/usb_audio/Stream.h      |   96 -
.../drivers/audio/usb_audio/USB_audio_spec.h     |  497 -----
.../kernel/drivers/audio/usb_audio/audio.h       |  165 --
.../kernel/drivers/audio/usb_audio/makefile      |  127 --
.../drivers/audio/usb_audio/usb_audio.settings   |   28 -

############################################################################

Commit:      cf58476cccdd470c401dd06dec94dc1939e4f3fc
URL:         http://cgit.haiku-os.org/haiku/commit/?id=cf58476
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Sat May 25 18:46:44 2013 UTC

Ticket:      https://dev.haiku-os.org/ticket/1045

USB OHCI: Support for isochronous transfers

Finishing and refactoring the draft, initially implemented during April-May 2012

NOTE: startingFrameNumber returned to device contains the number of the
next free frame right after the last packed of submitted data. For more
details please Look into corresponding [haiku-development] discussion
started at 03 Jul 2013.

Partially fixes #1045.

----------------------------------------------------------------------------

diff --git a/headers/os/drivers/USB_spec.h b/headers/os/drivers/USB_spec.h
index 08fe588..9b94857 100644
--- a/headers/os/drivers/USB_spec.h
+++ b/headers/os/drivers/USB_spec.h
@@ -62,6 +62,19 @@
 #define USB_ENDPOINT_ATTR_INTERRUPT                    0x03
 #define USB_ENDPOINT_ATTR_MASK                         0x03
 
+/* Synchronization - isochrnous endpoints only */
+#define USB_ENDPOINT_ATTR_NO_SYNCHRONIZE       0x00
+#define USB_ENDPOINT_ATTR_ASYNCRONOUS          0x04
+#define USB_ENDPOINT_ATTR_ADAPTIVE_SYNCHRO     0x08
+#define USB_ENDPOINT_ATTR_SYNCHRONOUS          0x0C
+#define USB_ENDPOINT_ATTR_SYNCHRONIZE_MASK     0x0C
+
+/* Usage Type - isochrnous endpoints only */
+#define USB_ENDPOINT_ATTR_DATA_USAGE           0x00
+#define USB_ENDPOINT_ATTR_FEEDBACK_USAGE       0x10
+#define USB_ENDPOINT_ATTR_IMPLICIT_USAGE       0x20
+#define USB_ENDPOINT_ATTR_USAGE_MASK           0x30
+
 #define USB_ENDPOINT_ADDR_DIR_IN                       0x80
 #define USB_ENDPOINT_ADDR_DIR_OUT                      0x00
 
diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp 
b/src/add-ons/kernel/busses/usb/ohci.cpp
index 3a28a49..489a762 100644
--- a/src/add-ons/kernel/busses/usb/ohci.cpp
+++ b/src/add-ons/kernel/busses/usb/ohci.cpp
@@ -1,11 +1,12 @@
 /*
- * Copyright 2005-2008, Haiku Inc. All rights reserved.
+ * Copyright 2005-2013, Haiku Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Jan-Rixt Van Hoye
  *             Salvatore Benedetto <salvatore.benedetto@xxxxxxxxx>
  *             Michael Lotz <mmlr@xxxxxxxx>
+ *             Siarzhuk Zharski <imker@xxxxxx>
  */
 
 #include <module.h>
@@ -74,6 +75,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
                fFinishThread(-1),
                fStopFinishThread(false),
                fProcessingPipe(NULL),
+               fFrameBandwidth(NULL),
                fRootHub(NULL),
                fRootHubAddress(0),
                fPortCount(0),
@@ -312,6 +314,12 @@ OHCI::OHCI(pci_info *info, Stack *stack)
        fPortCount = numberOfPorts;
        TRACE("port count is %d\n", fPortCount);
 
+       // Create the array that will keep bandwidth information
+       fFrameBandwidth = new(std::nothrow) uint16[NUMBER_OF_FRAMES];
+
+       for (int32 i = 0; i < NUMBER_OF_FRAMES; i++)
+               fFrameBandwidth[i] = MAX_AVAILABLE_BANDWIDTH;
+
        // Create semaphore the finisher thread will wait for
        fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
        if (fFinishTransfersSem < B_OK) {
@@ -378,6 +386,7 @@ OHCI::~OHCI()
                        _FreeEndpoint(fInterruptEndpoints[i]);
        }
 
+       delete [] fFrameBandwidth;
        delete [] fInterruptEndpoints;
        delete fRootHub;
 
@@ -459,9 +468,6 @@ OHCI::SubmitTransfer(Transfer *transfer)
 status_t
 OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
 {
-       if (pipe->Type() & USB_OBJECT_ISO_PIPE)
-               return _CancelQueuedIsochronousTransfers(pipe, force);
-
        if (!Lock())
                return B_ERROR;
 
@@ -487,6 +493,25 @@ OHCI::CancelQueuedTransfers(Pipe *pipe, bool force)
                                = current->endpoint->tail_physical_descriptor;
 
                        if (!force) {
+                               if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
+                                       ohci_isochronous_td *descriptor
+                                               = (ohci_isochronous_td 
*)current->first_descriptor;
+                                       while (descriptor) {
+                                               uint16 frame = 
OHCI_ITD_GET_STARTING_FRAME(
+                                                       descriptor->flags);
+                                               
_ReleaseIsochronousBandwidth(frame,
+                                                       
OHCI_ITD_GET_FRAME_COUNT(descriptor->flags));
+                                               if (descriptor
+                                                               == 
(ohci_isochronous_td*)current->last_descriptor)
+                                                       // this is the last ITD 
of the transfer
+                                                       break;
+
+                                               descriptor
+                                                       = (ohci_isochronous_td 
*)
+                                                       
descriptor->next_done_descriptor;
+                                       }
+                               }
+
                                // If the transfer is canceled by force, the 
one causing the
                                // cancel is probably not the one who initiated 
the transfer
                                // and the callback is likely not safe anymore
@@ -914,10 +939,55 @@ OHCI::_AddPendingTransfer(Transfer *transfer,
 
 
 status_t
-OHCI::_CancelQueuedIsochronousTransfers(Pipe *pipe, bool force)
+OHCI::_AddPendingIsochronousTransfer(Transfer *transfer,
+       ohci_endpoint_descriptor *endpoint, ohci_isochronous_td 
*firstDescriptor,
+       ohci_isochronous_td *lastDescriptor, bool directionIn)
 {
-       // TODO
-       return B_ERROR;
+       if (!transfer || !endpoint || !lastDescriptor)
+               return B_BAD_VALUE;
+
+       transfer_data *data = new(std::nothrow) transfer_data;
+       if (!data)
+               return B_NO_MEMORY;
+
+       status_t result = transfer->InitKernelAccess();
+       if (result < B_OK) {
+               delete data;
+               return result;
+       }
+
+       data->transfer = transfer;
+       data->endpoint = endpoint;
+       data->incoming = directionIn;
+       data->canceled = false;
+       data->link = NULL;
+
+       // the current tail will become the first descriptor
+       data->first_descriptor = 
(ohci_general_td*)endpoint->tail_logical_descriptor;
+
+       // the data and first descriptors are the same
+       data->data_descriptor = data->first_descriptor;
+
+       // the last and the first descriptor might be the same
+       if (lastDescriptor == firstDescriptor)
+               data->last_descriptor = data->first_descriptor;
+       else
+               data->last_descriptor = (ohci_general_td*)lastDescriptor;
+
+       if (!Lock()) {
+               delete data;
+               return B_ERROR;
+       }
+
+       if (fLastTransfer)
+               fLastTransfer->link = data;
+       else
+               fFirstTransfer = data;
+
+       fLastTransfer = data;
+       Unlock();
+
+       return B_OK;
 }
 
 
@@ -957,10 +1027,20 @@ OHCI::_FinishTransfers()
                        ohci_endpoint_descriptor *endpoint = transfer->endpoint;
                        status_t callbackStatus = B_OK;
 
+                       if (endpoint->flags & OHCI_ENDPOINT_ISOCHRONOUS_FORMAT) 
{
+                               transfer_data *next = transfer->link;
+                               if (_FinishIsochronousTransfer(transfer, 
&lastTransfer)) {
+                                       delete transfer->transfer;
+                                       delete transfer;
+                               }
+                               transfer = next;
+                               continue;
+                       }
+
                        MutexLocker endpointLocker(endpoint->lock);
 
                        if ((endpoint->head_physical_descriptor & 
OHCI_ENDPOINT_HEAD_MASK)
-                               != endpoint->tail_physical_descriptor) {
+                                       != endpoint->tail_physical_descriptor) {
                                // there are still active transfers on this 
endpoint, we need
                                // to wait for all of them to complete, 
otherwise we'd read
                                // a potentially bogus data toggle value below
@@ -991,49 +1071,7 @@ OHCI::_FinishTransfers()
                                                // still ensures that this td 
was handled before).
                                                TRACE_ERROR("td error: 0x%08" 
B_PRIx32 "\n", status);
 
-                                               switch (status) {
-                                                       case 
OHCI_TD_CONDITION_CRC_ERROR:
-                                                       case 
OHCI_TD_CONDITION_BIT_STUFFING:
-                                                       case 
OHCI_TD_CONDITION_TOGGLE_MISMATCH:
-                                                               callbackStatus 
= B_DEV_CRC_ERROR;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_STALL:
-                                                               callbackStatus 
= B_DEV_STALLED;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_NO_RESPONSE:
-                                                               callbackStatus 
= B_TIMED_OUT;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_PID_CHECK_FAILURE:
-                                                               callbackStatus 
= B_DEV_BAD_PID;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_UNEXPECTED_PID:
-                                                               callbackStatus 
= B_DEV_UNEXPECTED_PID;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_DATA_OVERRUN:
-                                                               callbackStatus 
= B_DEV_DATA_OVERRUN;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_DATA_UNDERRUN:
-                                                               callbackStatus 
= B_DEV_DATA_UNDERRUN;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_BUFFER_OVERRUN:
-                                                               callbackStatus 
= B_DEV_FIFO_OVERRUN;
-                                                               break;
-
-                                                       case 
OHCI_TD_CONDITION_BUFFER_UNDERRUN:
-                                                               callbackStatus 
= B_DEV_FIFO_UNDERRUN;
-                                                               break;
-
-                                                       default:
-                                                               callbackStatus 
= B_ERROR;
-                                                               break;
-                                               }
+                                               callbackStatus = 
_GetStatusOfConditionCode(status);
 
                                                transferDone = true;
                                                break;
@@ -1163,6 +1201,141 @@ OHCI::_FinishTransfers()
 }
 
 
+bool
+OHCI::_FinishIsochronousTransfer(transfer_data *transfer,
+       transfer_data **_lastTransfer)
+{
+       status_t callbackStatus = B_OK;
+       size_t actualLength = 0;
+       uint32 packet = 0;
+
+       if (transfer->canceled)
+               callbackStatus = B_CANCELED;
+       else {
+               // at first check if ALL ITDs are retired by HC
+               ohci_isochronous_td *descriptor
+                       = (ohci_isochronous_td *)transfer->first_descriptor;
+               while (descriptor) {
+                       if (OHCI_TD_GET_CONDITION_CODE(descriptor->flags)
+                               == OHCI_TD_CONDITION_NOT_ACCESSED) {
+                               TRACE("ITD %p still active\n", descriptor);
+                               *_lastTransfer = transfer;
+                               return false;
+                       }
+
+                       if (descriptor == 
(ohci_isochronous_td*)transfer->last_descriptor) {
+                               // this is the last ITD of the transfer
+                               descriptor = (ohci_isochronous_td 
*)transfer->first_descriptor;
+                               break;
+                       }
+
+                       descriptor
+                               = (ohci_isochronous_td 
*)descriptor->next_done_descriptor;
+               }
+
+               while (descriptor) {
+                       uint32 status = 
OHCI_TD_GET_CONDITION_CODE(descriptor->flags);
+                       if (status != OHCI_TD_CONDITION_NO_ERROR) {
+                               TRACE_ERROR("ITD error: 0x%08" B_PRIx32 "\n", 
status);
+                               // spec says that in most cases condition code
+                               // of retired ITDs is set to NoError, but for 
the
+                               // time overrun it can be DataOverrun. We assume
+                               // the _first_ occurience of such error as 
status
+                               // reported to the callback
+                               if (callbackStatus == B_OK)
+                                       callbackStatus = 
_GetStatusOfConditionCode(status);
+                       }
+
+                       usb_isochronous_data *isochronousData
+                               = transfer->transfer->IsochronousData();
+
+                       uint32 frameCount = 
OHCI_ITD_GET_FRAME_COUNT(descriptor->flags);
+                       for (size_t i = 0; i < frameCount; i++, packet++) {
+                               usb_iso_packet_descriptor* packet_descriptor
+                                       = 
&isochronousData->packet_descriptors[packet];
+
+                               uint16 offset = 
descriptor->offset[OHCI_ITD_OFFSET_IDX(i)];
+                               uint8 code = 
OHCI_ITD_GET_BUFFER_CONDITION_CODE(offset);
+                               packet_descriptor->status = 
_GetStatusOfConditionCode(code);
+
+                               // not touched by HC - sheduled too late to be 
processed
+                               // in the requested frame - so we ignore it too
+                               if (packet_descriptor->status == B_DEV_TOO_LATE)
+                                       continue;
+
+                               size_t len = OHCI_ITD_GET_BUFFER_LENGTH(offset);
+                               if (!transfer->incoming)
+                                       len = packet_descriptor->request_length 
- len;
+
+                               packet_descriptor->actual_length = len;
+                               actualLength += len;
+                       }
+
+                       uint16 frame = 
OHCI_ITD_GET_STARTING_FRAME(descriptor->flags);
+                       _ReleaseIsochronousBandwidth(frame,
+                               OHCI_ITD_GET_FRAME_COUNT(descriptor->flags));
+
+                       TRACE("ITD %p done\n", descriptor);
+
+                       if (descriptor == 
(ohci_isochronous_td*)transfer->last_descriptor)
+                               break;
+
+                       descriptor
+                               = (ohci_isochronous_td 
*)descriptor->next_done_descriptor;
+               }
+       }
+
+       // remove the transfer from the list first so we are sure
+       // it doesn't get canceled while we still process it
+       if (Lock()) {
+               if (*_lastTransfer)
+                       (*_lastTransfer)->link = transfer->link;
+
+               if (transfer == fFirstTransfer)
+                       fFirstTransfer = transfer->link;
+               if (transfer == fLastTransfer)
+                       fLastTransfer = *_lastTransfer;
+
+               // store the currently processing pipe here so we can wait
+               // in cancel if we are processing something on the target pipe
+               if (!transfer->canceled)
+                       fProcessingPipe = transfer->transfer->TransferPipe();
+
+               transfer->link = NULL;
+               Unlock();
+       }
+
+       // break the descriptor chain on the last descriptor
+       transfer->last_descriptor->next_logical_descriptor = NULL;
+       TRACE("iso.transfer %p done with status 0x%08" B_PRIx32 " len:%ld\n",
+               transfer, callbackStatus, actualLength);
+
+       // if canceled the callback has already been called
+       if (!transfer->canceled) {
+               if (callbackStatus == B_OK && actualLength > 0) {
+                       if (transfer->data_descriptor && transfer->incoming) {
+                               // data to read out
+                               iovec *vector = transfer->transfer->Vector();
+                               size_t vectorCount = 
transfer->transfer->VectorCount();
+
+                               transfer->transfer->PrepareKernelAccess();
+                               _ReadIsochronousDescriptorChain(
+                                       
(ohci_isochronous_td*)transfer->data_descriptor,
+                                       vector, vectorCount);
+                       }
+               }
+
+               transfer->transfer->Finished(callbackStatus, actualLength);
+               fProcessingPipe = NULL;
+       }
+
+       _FreeIsochronousDescriptorChain(
+               (ohci_isochronous_td*)transfer->first_descriptor);
+
+       return true;
+}
+
+
 status_t
 OHCI::_SubmitRequest(Transfer *transfer)
 {
@@ -1307,8 +1480,58 @@ OHCI::_SubmitTransfer(Transfer *transfer)
 status_t
 OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
 {
-       TRACE_ERROR("isochronous transfers not implemented\n");
-       return B_ERROR;
+       Pipe *pipe = transfer->TransferPipe();
+       bool directionIn = (pipe->Direction() == Pipe::In);
+       usb_isochronous_data *isochronousData = transfer->IsochronousData();
+
+       ohci_isochronous_td *firstDescriptor = NULL;
+       ohci_isochronous_td *lastDescriptor = NULL;
+       status_t result = _CreateIsochronousDescriptorChain(&firstDescriptor,
+               &lastDescriptor, transfer);
+
+       if (firstDescriptor == 0 || lastDescriptor == 0)
+               return B_ERROR;
+
+       if (result < B_OK)
+               return result;
+
+       // Set the last descriptor to generate an interrupt
+       lastDescriptor->flags &= ~OHCI_ITD_INTERRUPT_MASK;
+       // let the controller retire last ITD
+       lastDescriptor->flags |= OHCI_ITD_SET_DELAY_INTERRUPT(1);
+
+       // If direction is out set every descriptor data
+       if (pipe->Direction() == Pipe::Out)
+               _WriteIsochronousDescriptorChain(firstDescriptor,
+                       transfer->Vector(), transfer->VectorCount());
+       else
+               // Initialize the packet descriptors
+               for (uint32 i = 0; i < isochronousData->packet_count; i++) {
+                       isochronousData->packet_descriptors[i].actual_length = 
0;
+                       isochronousData->packet_descriptors[i].status = 
B_NO_INIT;
+               }
+
+       // Add to the transfer list
+       ohci_endpoint_descriptor *endpoint
+               = (ohci_endpoint_descriptor *)pipe->ControllerCookie();
+
+       MutexLocker endpointLocker(endpoint->lock);
+       result = _AddPendingIsochronousTransfer(transfer, endpoint,
+               firstDescriptor, lastDescriptor, directionIn);
+       if (result < B_OK) {
+               TRACE_ERROR("failed to add pending iso.transfer:"
+                       "0x%08" B_PRIx32 "\n", result);
+               _FreeIsochronousDescriptorChain(firstDescriptor);
+               return result;
+       }
+
+       // Add the descriptor chain to the endpoint
+       _SwitchIsochronousEndpointTail(endpoint, firstDescriptor, 
lastDescriptor);
+       endpointLocker.Unlock();
+
+       endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
+
+       return B_OK;
 }
 
 
@@ -1353,6 +1576,54 @@ OHCI::_SwitchEndpointTail(ohci_endpoint_descriptor 
*endpoint,
 
 
 void
+OHCI::_SwitchIsochronousEndpointTail(ohci_endpoint_descriptor *endpoint,
+       ohci_isochronous_td *first, ohci_isochronous_td *last)
+{
+       // fill in the information of the first descriptor into the current tail
+       ohci_isochronous_td *tail
+               = (ohci_isochronous_td*)endpoint->tail_logical_descriptor;
+       tail->flags = first->flags;
+       tail->buffer_page_byte_0 = first->buffer_page_byte_0;
+       tail->next_physical_descriptor = first->next_physical_descriptor;
+       tail->last_byte_address = first->last_byte_address;
+       tail->buffer_size = first->buffer_size;
+       tail->buffer_logical = first->buffer_logical;
+       tail->next_logical_descriptor = first->next_logical_descriptor;
+       tail->next_done_descriptor = first->next_done_descriptor;
+
+       // the first descriptor becomes the new tail
+       first->flags = 0;
+       first->buffer_page_byte_0 = 0;
+       first->next_physical_descriptor = 0;
+       first->last_byte_address = 0;
+       first->buffer_size = 0;
+       first->buffer_logical = NULL;
+       first->next_logical_descriptor = NULL;
+       first->next_done_descriptor = NULL;
+
+       for (int i = 0; i < OHCI_ITD_NOFFSET; i++) {
+               tail->offset[i] = first->offset[i];
+               first->offset[i] = 0;
+       }
+
+       if (first == last)
+               _LinkIsochronousDescriptors(tail, first, NULL);
+       else
+               _LinkIsochronousDescriptors(last, first, NULL);
+
+       // update the endpoint tail pointer to reflect the change
+       endpoint->tail_logical_descriptor = first;
+       endpoint->tail_physical_descriptor = (uint32)first->physical_address;
+       TRACE("switched tail from %p to %p\n", tail, first);
+
+#if 0
+       _PrintEndpoint(endpoint);
+       _PrintDescriptorChain(tail);
+#endif
+}
+
+
+void
 OHCI::_RemoveTransferFromEndpoint(transfer_data *transfer)
 {
        // The transfer failed and the endpoint was halted. This means that the
@@ -1515,9 +1786,11 @@ OHCI::_InsertEndpointForPipe(Pipe *pipe)
        if (pipe->Type() & USB_OBJECT_ISO_PIPE) {
                // Set the isochronous bit format
                endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT;
-               // TODO
-               _FreeEndpoint(endpoint);
-               return B_ERROR;
+               ohci_isochronous_td *tail = _CreateIsochronousDescriptor(0);
+               tail->flags = 0;
+               endpoint->tail_logical_descriptor = tail;
+               endpoint->head_physical_descriptor = tail->physical_address;
+               endpoint->tail_physical_descriptor = tail->physical_address;
        } else {
                ohci_general_td *tail = _CreateGeneralDescriptor(0);
                tail->flags = 0;
@@ -1691,6 +1964,191 @@ OHCI::_FreeDescriptorChain(ohci_general_td 
*topDescriptor)
 }
 
 
+ohci_isochronous_td *
+OHCI::_CreateIsochronousDescriptor(size_t bufferSize)
+{
+       ohci_isochronous_td *descriptor = NULL;
+       phys_addr_t physicalAddress;
+
+       if (fStack->AllocateChunk((void **)&descriptor, &physicalAddress,
+               sizeof(ohci_isochronous_td)) != B_OK) {
+               TRACE_ERROR("failed to allocate isochronous descriptor\n");
+               return NULL;
+       }
+
+       descriptor->physical_address = (uint32)physicalAddress;
+       descriptor->next_physical_descriptor = 0;
+       descriptor->next_logical_descriptor = NULL;
+       descriptor->next_done_descriptor = NULL;
+       descriptor->buffer_size = bufferSize;
+       if (bufferSize == 0) {
+               descriptor->buffer_page_byte_0 = 0;
+               descriptor->buffer_logical = NULL;
+               descriptor->last_byte_address = 0;
+               return descriptor;
+       }
+
+       if (fStack->AllocateChunk(&descriptor->buffer_logical,
+               &physicalAddress, bufferSize) != B_OK) {
+               TRACE_ERROR("failed to allocate space for iso.buffer\n");
+               fStack->FreeChunk(descriptor, descriptor->physical_address,
+                       sizeof(ohci_isochronous_td));
+               return NULL;
+       }
+       descriptor->buffer_page_byte_0 = (uint32)physicalAddress;
+       descriptor->last_byte_address
+               = descriptor->buffer_page_byte_0 + bufferSize - 1;
+
+       return descriptor;
+}
+
+
+void
+OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
+{
+       if (!descriptor)
+               return;
+
+       if (descriptor->buffer_logical) {
+               fStack->FreeChunk(descriptor->buffer_logical,
+                       descriptor->buffer_page_byte_0, 
descriptor->buffer_size);
+       }
+
+       fStack->FreeChunk((void *)descriptor, descriptor->physical_address,
+               sizeof(ohci_general_td));
+}
+
+
+status_t
+OHCI::_CreateIsochronousDescriptorChain(ohci_isochronous_td **_firstDescriptor,
+       ohci_isochronous_td **_lastDescriptor, Transfer *transfer)
+{
+       Pipe *pipe = transfer->TransferPipe();
+       usb_isochronous_data *isochronousData = transfer->IsochronousData();
+
+       size_t dataLength = transfer->VectorLength();
+       size_t packet_count = isochronousData->packet_count;
+
+       if (packet_count == 0) {
+               TRACE_ERROR("isochronous packet_count should not be equal to 
zero.");
+               return B_BAD_VALUE;
+       }
+
+       size_t packetSize = dataLength / packet_count;
+       if (dataLength % packet_count != 0)
+               packetSize++;
+
+       if (packetSize > pipe->MaxPacketSize()) {
+               TRACE_ERROR("isochronous packetSize %ld is bigger"
+                       " than pipe MaxPacketSize %ld.", packetSize, 
pipe->MaxPacketSize());
+               return B_BAD_VALUE;
+       }
+
+       uint16 bandwidth = transfer->Bandwidth() / packet_count;
+       if (transfer->Bandwidth() % packet_count != 0)
+               bandwidth++;
+
+       ohci_isochronous_td *firstDescriptor = NULL;
+       ohci_isochronous_td *lastDescriptor = *_firstDescriptor;
+
+       // the frame number currently processed by the host controller
+       uint16 currentFrame = fHcca->current_frame_number & 0xFFFF;
+       uint16 safeFrames = 5;
+
+       // The entry where to start inserting the first Isochronous descriptor
+       // real frame number may differ in case provided one has not bandwidth
+       if (isochronousData->flags & USB_ISO_ASAP ||
+               isochronousData->starting_frame_number == NULL)
+               // We should stay about 5-10 ms ahead of the controller
+               // USB1 frame is equal to 1 ms
+               currentFrame += safeFrames;
+       else
+               currentFrame = *isochronousData->starting_frame_number;
+
+       uint16 packets = packet_count;
+       uint16 frameOffset = 0;
+       while (packets > 0) {
+               // look for up to 8 continous frames with available bandwidth
+               uint16 frameCount = 0;
+               while (frameCount < min_c(OHCI_ITD_NOFFSET, packets)
+                               && _AllocateIsochronousBandwidth(frameOffset + 
currentFrame
+                                       + frameCount, bandwidth))
+                       frameCount++;
+
+               if (frameCount == 0) {
+                       // starting frame has no bandwidth for our transaction 
- try next
+                       if (++frameOffset >= 0xFFFF) {
+                               TRACE_ERROR("failed to allocate bandwidth\n");
+                               
_FreeIsochronousDescriptorChain(firstDescriptor);
+                               return B_NO_MEMORY;
+                       }
+                       continue;
+               }
+
+               ohci_isochronous_td *descriptor = _CreateIsochronousDescriptor(
+                               packetSize * frameCount);
+
+               if (!descriptor) {
+                       TRACE_ERROR("failed to allocate ITD\n");
+                       _ReleaseIsochronousBandwidth(currentFrame + 
frameOffset, frameCount);
+                       _FreeIsochronousDescriptorChain(firstDescriptor);
+                       return B_NO_MEMORY;
+               }
+
+               uint16 pageOffset = descriptor->buffer_page_byte_0 & 0xfff;
+               descriptor->buffer_page_byte_0 &= ~0xfff;
+               for (uint16 i = 0; i < frameCount; i++) {
+                       descriptor->offset[OHCI_ITD_OFFSET_IDX(i)]
+                               = OHCI_ITD_MK_OFFS(pageOffset + packetSize * i);
+               }
+
+               descriptor->flags = OHCI_ITD_SET_FRAME_COUNT(frameCount)
+                               | 
OHCI_ITD_SET_CONDITION_CODE(OHCI_ITD_CONDITION_NOT_ACCESSED)
+                               | 
OHCI_ITD_SET_DELAY_INTERRUPT(OHCI_ITD_INTERRUPT_NONE)
+                               | OHCI_ITD_SET_STARTING_FRAME(currentFrame + 
frameOffset);
+
+               // the last packet may be shorter than other ones in this 
transfer
+               if (packets <= OHCI_ITD_NOFFSET)
+                       descriptor->last_byte_address
+                               += dataLength - packetSize * (packet_count);
+
+               // link to previous
+               if (lastDescriptor)
+                       _LinkIsochronousDescriptors(lastDescriptor, descriptor, 
descriptor);
+
+               lastDescriptor = descriptor;
+               if (!firstDescriptor)
+                       firstDescriptor = descriptor;
+
+               packets -= frameCount;
+
+               frameOffset += frameCount;
+
+               if (packets == 0 && isochronousData->starting_frame_number)
+                       *isochronousData->starting_frame_number = currentFrame 
+ frameOffset;
+       }
+
+       *_firstDescriptor = firstDescriptor;
+       *_lastDescriptor = lastDescriptor;
+
+       return B_OK;
+}
+
+
+void
+OHCI::_FreeIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor)
+{
+       ohci_isochronous_td *current = topDescriptor;
+       ohci_isochronous_td *next = NULL;
+
+       while (current) {
+               next = (ohci_isochronous_td *)current->next_done_descriptor;
+               _FreeIsochronousDescriptor(current);
+               current = next;
+       }
+}
+
+
 size_t
 OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
        size_t vectorCount)
@@ -1747,6 +2205,61 @@ OHCI::_WriteDescriptorChain(ohci_general_td 
*topDescriptor, iovec *vector,
 
 
 size_t
+OHCI::_WriteIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor,
+       iovec *vector, size_t vectorCount)
+{
+       ohci_isochronous_td *current = topDescriptor;
+       size_t actualLength = 0;
+       size_t vectorIndex = 0;
+       size_t vectorOffset = 0;
+       size_t bufferOffset = 0;
+
+       while (current) {
+               if (!current->buffer_logical)
+                       break;
+
+               while (true) {
+                       size_t length = min_c(current->buffer_size - 
bufferOffset,
+                               vector[vectorIndex].iov_len - vectorOffset);
+
+                       TRACE("copying %ld bytes to bufferOffset %ld from"
+                               " vectorOffset %ld at index %ld of %ld\n", 
length, bufferOffset,
+                               vectorOffset, vectorIndex, vectorCount);
+                       memcpy((uint8 *)current->buffer_logical + bufferOffset,
+                               (uint8 *)vector[vectorIndex].iov_base + 
vectorOffset, length);
+
+                       actualLength += length;
+                       vectorOffset += length;
+                       bufferOffset += length;
+
+                       if (vectorOffset >= vector[vectorIndex].iov_len) {
+                               if (++vectorIndex >= vectorCount) {
+                                       TRACE("wrote descriptor chain (%ld 
bytes, no"
+                                               " more vectors)\n", 
actualLength);
+                                       return actualLength;
+                               }
+
+                               vectorOffset = 0;
+                       }
+
+                       if (bufferOffset >= current->buffer_size) {
+                               bufferOffset = 0;
+                               break;
+                       }
+               }
+
+               if (!current->next_logical_descriptor)
+                       break;
+
+               current = (ohci_isochronous_td 
*)current->next_logical_descriptor;
+       }
+
+       TRACE("wrote descriptor chain (%ld bytes)\n", actualLength);
+       return actualLength;
+}
+
+
+size_t
 OHCI::_ReadDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
        size_t vectorCount)
 {
@@ -1805,6 +2318,59 @@ OHCI::_ReadDescriptorChain(ohci_general_td 
*topDescriptor, iovec *vector,
 }
 
 
+void
+OHCI::_ReadIsochronousDescriptorChain(ohci_isochronous_td *topDescriptor,
+       iovec *vector, size_t vectorCount)
+{
+       ohci_isochronous_td *current = topDescriptor;
+       size_t actualLength = 0;
+       size_t vectorIndex = 0;
+       size_t vectorOffset = 0;
+       size_t bufferOffset = 0;
+
+       while (current && OHCI_ITD_GET_CONDITION_CODE(current->flags)
+                       != OHCI_ITD_CONDITION_NOT_ACCESSED) {
+               size_t bufferSize = current->buffer_size;
+               if (current->buffer_logical != NULL && bufferSize > 0) {
+                       while (true) {
+                               size_t length = min_c(bufferSize - bufferOffset,
+                                       vector[vectorIndex].iov_len - 
vectorOffset);
+
+                               TRACE("copying %ld bytes to vectorOffset %ld 
from bufferOffset"
+                                       " %ld at index %ld of %ld\n", length, 
vectorOffset,
+                                       bufferOffset, vectorIndex, vectorCount);
+                               memcpy((uint8 *)vector[vectorIndex].iov_base + 
vectorOffset,
+                                       (uint8 *)current->buffer_logical + 
bufferOffset, length);
+
+                               actualLength += length;
+                               vectorOffset += length;
+                               bufferOffset += length;
+
+                               if (vectorOffset >= 
vector[vectorIndex].iov_len) {
+                                       if (++vectorIndex >= vectorCount) {
+                                               TRACE("read descriptor chain 
(%ld bytes, "
+                                                       "no more vectors)\n", 
actualLength);
+                                               return;
+                                       }
+
+                                       vectorOffset = 0;
+                               }
+
+                               if (bufferOffset >= bufferSize) {
+                                       bufferOffset = 0;
+                                       break;
+                               }
+                       }
+               }
+
+               current = (ohci_isochronous_td *)current->next_done_descriptor;
+       }
+
+       TRACE("read descriptor chain (%ld bytes)\n", actualLength);
+       return;
+}
+
+
 size_t
 OHCI::_ReadActualLength(ohci_general_td *topDescriptor)
 {
@@ -1836,18 +2402,85 @@ OHCI::_LinkDescriptors(ohci_general_td *first, 
ohci_general_td *second)
 }
 
 
-ohci_isochronous_td *
-OHCI::_CreateIsochronousDescriptor()
+void
+OHCI::_LinkIsochronousDescriptors(ohci_isochronous_td *first,
+       ohci_isochronous_td *second, ohci_isochronous_td *nextDone)
 {
-       // TODO
-       return NULL;
+       first->next_physical_descriptor = second->physical_address;
+       first->next_logical_descriptor = second;
+       first->next_done_descriptor = nextDone;
+}
+
+
+bool
+OHCI::_AllocateIsochronousBandwidth(uint16 frame, uint16 size)
+{
+       frame %= NUMBER_OF_FRAMES;
+       if (size > fFrameBandwidth[frame])
+               return false;
+
+       fFrameBandwidth[frame]-= size;
+       return true;
 }
 
 
 void
-OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
+OHCI::_ReleaseIsochronousBandwidth(uint16 startFrame, uint16 frameCount)
 {
-       // TODO
+       for (size_t index = 0; index < frameCount; index++) {
+               uint16 frame = (startFrame + index) % NUMBER_OF_FRAMES;
+               fFrameBandwidth[frame] = MAX_AVAILABLE_BANDWIDTH;
+       }
+}
+
+
+status_t
+OHCI::_GetStatusOfConditionCode(uint8 conditionCode)
+{
+       switch (conditionCode) {
+               case OHCI_TD_CONDITION_NO_ERROR:
+                       return B_OK;
+
+               case OHCI_TD_CONDITION_CRC_ERROR:
+               case OHCI_TD_CONDITION_BIT_STUFFING:
+               case OHCI_TD_CONDITION_TOGGLE_MISMATCH:
+                       return B_DEV_CRC_ERROR;
+
+               case OHCI_TD_CONDITION_STALL:
+                       return B_DEV_STALLED;
+
+               case OHCI_TD_CONDITION_NO_RESPONSE:
+                       return B_TIMED_OUT;
+
+               case OHCI_TD_CONDITION_PID_CHECK_FAILURE:
+                       return B_DEV_BAD_PID;
+
+               case OHCI_TD_CONDITION_UNEXPECTED_PID:
+                       return B_DEV_UNEXPECTED_PID;
+
+               case OHCI_TD_CONDITION_DATA_OVERRUN:
+                       return B_DEV_DATA_OVERRUN;
+
+               case OHCI_TD_CONDITION_DATA_UNDERRUN:
+                       return B_DEV_DATA_UNDERRUN;
+
+               case OHCI_TD_CONDITION_BUFFER_OVERRUN:
+                       return B_DEV_FIFO_OVERRUN;
+
+               case OHCI_TD_CONDITION_BUFFER_UNDERRUN:
+                       return B_DEV_FIFO_UNDERRUN;
+
+               case OHCI_TD_CONDITION_NOT_ACCESSED:
+                       return B_DEV_PENDING;
+
+               case 0x0E:
+                       return B_DEV_TOO_LATE; // PSW: _NOT_ACCESSED
+
+               default:
+                       break;
+       }
+
+       return B_ERROR;
 }
 
 
@@ -1882,7 +2515,7 @@ OHCI::_ReadReg(uint32 reg)
 void
 OHCI::_PrintEndpoint(ohci_endpoint_descriptor *endpoint)
 {
-       TRACE_ALWAYS("endpoint %p\n", endpoint);
+       dprintf("endpoint %p\n", endpoint);
        dprintf("\tflags........... 0x%08" B_PRIx32 "\n", endpoint->flags);
        dprintf("\ttail_physical... 0x%08" B_PRIx32 "\n", 
endpoint->tail_physical_descriptor);
        dprintf("\thead_physical... 0x%08" B_PRIx32 "\n", 
endpoint->head_physical_descriptor);
@@ -1897,7 +2530,7 @@ void
 OHCI::_PrintDescriptorChain(ohci_general_td *topDescriptor)
 {
        while (topDescriptor) {
-               TRACE_ALWAYS("descriptor %p\n", topDescriptor);
+               dprintf("descriptor %p\n", topDescriptor);
                dprintf("\tflags........... 0x%08" B_PRIx32 "\n", 
topDescriptor->flags);
                dprintf("\tbuffer_physical. 0x%08" B_PRIx32 "\n", 
topDescriptor->buffer_physical);
                dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", 
topDescriptor->next_physical_descriptor);
@@ -1910,3 +2543,30 @@ OHCI::_PrintDescriptorChain(ohci_general_td 
*topDescriptor)
                topDescriptor = (ohci_general_td 
*)topDescriptor->next_logical_descriptor;
        }
 }
+
+
+void
+OHCI::_PrintDescriptorChain(ohci_isochronous_td *topDescriptor)
+{
+       while (topDescriptor) {
+               dprintf("iso.descriptor %p\n", topDescriptor);
+               dprintf("\tflags........... 0x%08" B_PRIx32 "\n", 
topDescriptor->flags);
+               dprintf("\tbuffer_pagebyte0 0x%08" B_PRIx32 "\n", 
topDescriptor->buffer_page_byte_0);
+               dprintf("\tnext_physical... 0x%08" B_PRIx32 "\n", 
topDescriptor->next_physical_descriptor);
+               dprintf("\tlast_byte....... 0x%08" B_PRIx32 "\n", 
topDescriptor->last_byte_address);
+               dprintf("\toffset:\n\t0x%04x 0x%04x 0x%04x 0x%04x\n"
+                                                       "\t0x%04x 0x%04x 0x%04x 
0x%04x\n",
+                               topDescriptor->offset[0], 
topDescriptor->offset[1],
+                               topDescriptor->offset[2], 
topDescriptor->offset[3],
+                               topDescriptor->offset[4], 
topDescriptor->offset[5],
+                               topDescriptor->offset[6], 
topDescriptor->offset[7]);
+               dprintf("\tphysical........ 0x%08" B_PRIx32 "\n", 
topDescriptor->physical_address);
+               dprintf("\tbuffer_size..... %lu\n", topDescriptor->buffer_size);
+               dprintf("\tbuffer_logical.. %p\n", 
topDescriptor->buffer_logical);
+               dprintf("\tnext_logical.... %p\n", 
topDescriptor->next_logical_descriptor);
+               dprintf("\tnext_done....... %p\n", 
topDescriptor->next_done_descriptor);
+
+               topDescriptor = (ohci_isochronous_td 
*)topDescriptor->next_done_descriptor;
+       }
+}
+
diff --git a/src/add-ons/kernel/busses/usb/ohci.h 
b/src/add-ons/kernel/busses/usb/ohci.h
index 341e8a4..7327653 100644
--- a/src/add-ons/kernel/busses/usb/ohci.h
+++ b/src/add-ons/kernel/busses/usb/ohci.h
@@ -1,11 +1,12 @@
 /*
- * Copyright 2005-2008, Haiku Inc. All rights reserved.
+ * Copyright 2005-2013, Haiku Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Jan-Rixt Van Hoye
  *             Salvatore Benedetto <salvatore.benedetto@xxxxxxxxx>
  *             Michael Lotz <mmlr@xxxxxxxx>
+ *             Siarzhuk Zharski <imker@xxxxxx>
  */
 #ifndef OHCI_H
 #define OHCI_H
@@ -69,12 +70,20 @@ static      int32                                           
_InterruptHandler(void *data);
                                                                                
ohci_general_td *dataDescriptor,
                                                                                
ohci_general_td *lastDescriptor,
                                                                                
bool directionIn);
-               status_t                                        
_CancelQueuedIsochronousTransfers(
-                                                                               
Pipe *pipe, bool force);
+               status_t                                        
_AddPendingIsochronousTransfer(
+                                                                               
Transfer *transfer,
+                                                                               
ohci_endpoint_descriptor *endpoint,
+                                                                               
ohci_isochronous_td *firstDescriptor,
+                                                                               
ohci_isochronous_td *lastDescriptor,
+                                                                               
bool directionIn);
+
                status_t                                        
_UnlinkTransfer(transfer_data *transfer);
 
 static int32                                           _FinishThread(void 
*data);
                void                                            
_FinishTransfers();
+               bool                                            
_FinishIsochronousTransfer(
+                                                                               
transfer_data *transfer,
+                                                                               
transfer_data **_lastTransfer);
 
                status_t                                        
_SubmitRequest(Transfer *transfer);
                status_t                                        
_SubmitTransfer(Transfer *transfer);
@@ -85,6 +94,11 @@ static       int32                                           
_FinishThread(void *data);
                                                                                
ohci_endpoint_descriptor *endpoint,
                                                                                
ohci_general_td *first,
                                                                                
ohci_general_td *last);
+               void                                            
_SwitchIsochronousEndpointTail(
+                                                                               
ohci_endpoint_descriptor *endpoint,
+                                                                               
ohci_isochronous_td *first,
+                                                                               
ohci_isochronous_td *last);
+
                void                                            
_RemoveTransferFromEndpoint(
                                                                                
transfer_data *transfer);
 
@@ -101,7 +115,6 @@ static      int32                                           
_FinishThread(void *data);
                                                                                
size_t bufferSize);
                void                                            
_FreeGeneralDescriptor(
                                                                                
ohci_general_td *descriptor);
-
                status_t                                        
_CreateDescriptorChain(
                                                                                
ohci_general_td **firstDescriptor,
                                                                                
ohci_general_td **lastDescriptor,
@@ -110,22 +123,48 @@ static    int32                                           
_FinishThread(void *data);
                void                                            
_FreeDescriptorChain(
                                                                                
ohci_general_td *topDescriptor);
 
+               ohci_isochronous_td *           _CreateIsochronousDescriptor(
+                                                                               
size_t bufferSize);
+               void                                            
_FreeIsochronousDescriptor(
+                                                                               
ohci_isochronous_td *descriptor);
+               status_t                                        
_CreateIsochronousDescriptorChain(
+                                                                               
ohci_isochronous_td **firstDescriptor,
+                                                                               
ohci_isochronous_td **lastDescriptor,
+                                                                               
Transfer *transfer);
+               void                                            
_FreeIsochronousDescriptorChain(
+                                                                               
ohci_isochronous_td *topDescriptor);
+
                size_t                                          
_WriteDescriptorChain(
                                                                                
ohci_general_td *topDescriptor,
                                                                                
iovec *vector, size_t vectorCount);
                size_t                                          
_ReadDescriptorChain(
                                                                                
ohci_general_td *topDescriptor,
                                                                                
iovec *vector, size_t vectorCount);
+
+               size_t                                          
_WriteIsochronousDescriptorChain(
+                                                                               
ohci_isochronous_td *topDescriptor,
+                                                                               
iovec *vector, size_t vectorCount);
+               void                                            
_ReadIsochronousDescriptorChain(
+                                                                               
ohci_isochronous_td *topDescriptor,
+                                                                               
iovec *vector, size_t vectorCount);
+
                size_t                                          
_ReadActualLength(
                                                                                
ohci_general_td *topDescriptor);
 
                void                                            
_LinkDescriptors(ohci_general_td *first,
                                                                                
ohci_general_td *second);
-
-               ohci_isochronous_td *           _CreateIsochronousDescriptor();
-               void                                            
_FreeIsochronousDescriptor(
-                                                                               
ohci_isochronous_td *descriptor);
-
+               void                                            
_LinkIsochronousDescriptors(
+                                                                               
ohci_isochronous_td *first,
+                                                                               
ohci_isochronous_td *second,
+                                                                               
ohci_isochronous_td *nextDone);
+
+               bool                                            
_AllocateIsochronousBandwidth(uint16 frame,
+                                                                               
uint16 size);
+               void                                            
_ReleaseIsochronousBandwidth(
+                                                                               
uint16 startFrame, uint16 count);
+
+               status_t                                        
_GetStatusOfConditionCode(
+                                                                               
uint8 conditionCode);
                // Private locking
                bool                                            
_LockEndpoints();
                void                                            
_UnlockEndpoints();
@@ -139,6 +178,8 @@ inline      uint32                                          
_ReadReg(uint32 reg);
                                                                                
ohci_endpoint_descriptor *endpoint);
                void                                            
_PrintDescriptorChain(
                                                                                
ohci_general_td *topDescriptor);
+               void                                            
_PrintDescriptorChain(
+                                                                               
ohci_isochronous_td *topDescriptor);
 
 static pci_module_info *                       sPCIModule;
 static pci_x86_module_info *           sPCIx86Module;
@@ -167,6 +208,8 @@ static      pci_x86_module_info *           sPCIx86Module;
                thread_id                                       fFinishThread;
                bool                                            
fStopFinishThread;
                Pipe *                                          fProcessingPipe;
+               // frame bandwidth watchdogs array
+               uint16 *                                        fFrameBandwidth;
 
                // Root Hub
                OHCIRootHub *                           fRootHub;
diff --git a/src/add-ons/kernel/busses/usb/ohci.rdef 
b/src/add-ons/kernel/busses/usb/ohci.rdef
index a70dc36..be184dd 100644
--- a/src/add-ons/kernel/busses/usb/ohci.rdef
+++ b/src/add-ons/kernel/busses/usb/ohci.rdef
@@ -12,6 +12,6 @@ resource app_version {
        variety = 0,
        internal = 0,
        short_info = "OHCI host controller driver",
-       long_info = "Haiku OHCI HCD - Copyright 2005-2009, Haiku Inc."
+       long_info = "Haiku OHCI HCD - Copyright 2005-2013, Haiku Inc."
 };
 
diff --git a/src/add-ons/kernel/busses/usb/ohci_hardware.h 
b/src/add-ons/kernel/busses/usb/ohci_hardware.h
index 308a27b..4244796 100644
--- a/src/add-ons/kernel/busses/usb/ohci_hardware.h
+++ b/src/add-ons/kernel/busses/usb/ohci_hardware.h
@@ -1,11 +1,12 @@
 /*
- * Copyright 2005-2008, Haiku Inc. All rights reserved.
+ * Copyright 2005-2013, Haiku Inc. All rights reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Jan-Rixt Van Hoye
  *             Salvatore Benedetto <salvatore.benedetto@xxxxxxxxx>
  *             Michael Lotz <mmlr@xxxxxxxx>
+ *             Siarzhuk Zharski <imker@xxxxxx>
  */
 
 #ifndef OHCI_HARDWARE_H
@@ -396,6 +397,8 @@ typedef struct {
        uint16          offset[OHCI_ITD_NOFFSET];       // Buffer offsets
        // Software part
        uint32          physical_address;                       // Physical 
address of this descriptor
+       size_t          buffer_size;                            // Size of the 
buffer
+       void            *buffer_logical;                        // Logical 
pointer to the buffer
        void            *next_logical_descriptor;       // Logical pointer next 
descriptor
        void            *next_done_descriptor;          // Used for collision 
in the hash table
 } ohci_isochronous_td;
@@ -404,11 +407,31 @@ typedef struct {
 #define        OHCI_ITD_SET_STARTING_FRAME(x)                  ((x) & 0xffff)
 #define        OHCI_ITD_GET_DELAY_INTERRUPT(x)                 (((x) >> 21) & 
7)
 #define        OHCI_ITD_SET_DELAY_INTERRUPT(x)                 ((x) << 21)
-#define        OHCI_ITD_NO_INTERRUPT                                   
0x00e00000
+#define        OHCI_ITD_INTERRUPT_MASK                                 
0x00e00000
 #define        OHCI_ITD_GET_FRAME_COUNT(x)                             ((((x) 
>> 24) & 7) + 1)
 #define        OHCI_ITD_SET_FRAME_COUNT(x)                             (((x) - 
1) << 24)
 #define        OHCI_ITD_GET_CONDITION_CODE(x)                  ((x) >> 28)
-#define        OHCI_ITD_NO_CONDITION_CODE                              
0xf0000000
+#define        OHCI_ITD_SET_CONDITION_CODE(x)                  ((x) << 28)
+#define        OHCI_ITD_CONDITION_CODE_MASK                    0xf0000000
+
+#define        OHCI_ITD_OFFSET_IDX(x)                                  (x)
+
+#define OHCI_ITD_INTERRUPT_IMMEDIATE                   0x00
+#define OHCI_ITD_INTERRUPT_NONE                                        0x07
+
+#define OHCI_ITD_CONDITION_NO_ERROR                            0x00
+#define OHCI_ITD_CONDITION_CRC_ERROR                   0x01
+#define OHCI_ITD_CONDITION_BIT_STUFFING                        0x02
+#define OHCI_ITD_CONDITION_TOGGLE_MISMATCH             0x03
+#define OHCI_ITD_CONDITION_STALL                               0x04
+#define OHCI_ITD_CONDITION_NO_RESPONSE                 0x05
+#define OHCI_ITD_CONDITION_PID_CHECK_FAILURE   0x06
+#define OHCI_ITD_CONDITION_UNEXPECTED_PID              0x07
+#define OHCI_ITD_CONDITION_DATA_OVERRUN                        0x08
+#define OHCI_ITD_CONDITION_DATA_UNDERRUN               0x09
+#define OHCI_ITD_CONDITION_BUFFER_OVERRUN              0x0c
+#define OHCI_ITD_CONDITION_BUFFER_UNDERRUN             0x0d
+#define OHCI_ITD_CONDITION_NOT_ACCESSED                        0x0f
 
 // TO FIX
 #define itd_pswn itd_offset                                            // 
Packet Status Word
@@ -419,6 +442,10 @@ typedef struct {
 
 #define OHCI_ISOCHRONOUS_TD_ALIGN 32
 
+// Number of frames
+#define NUMBER_OF_FRAMES               1024
+#define MAX_AVAILABLE_BANDWIDTH        900     // Microseconds
+
 // --------------------------------
 //     Completion Codes (section 4.3.3)
 // --------------------------------

############################################################################

Commit:      291e40c3092eec114393f5463d481375736af6d3
URL:         http://cgit.haiku-os.org/haiku/commit/?id=291e40c
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Sun Aug  4 17:49:41 2013 UTC

USB OHCI: Fix finalizing of STALL-ed control request transfers

In case control transfer is finished with STALL answer from device only
the setup TD is retired into the Done Queue but other TDs (data and
status) are left in the ED queue. HC set the endpoint halted - so we
process such endpoint regardless of it's non-empty queue.

PS: cleanup some trailing spaces.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp 
b/src/add-ons/kernel/busses/usb/ohci.cpp
index 489a762..899280b 100644
--- a/src/add-ons/kernel/busses/usb/ohci.cpp
+++ b/src/add-ons/kernel/busses/usb/ohci.cpp
@@ -217,7 +217,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
        // interrupts during handover. Therefore we disable interrupts before
        // requesting ownership. We have to keep the ownership change interrupt
        // enabled though, as otherwise the SMM will not be notified of the
-       // ownership change request we trigger below.   
+       // ownership change request we trigger below.
        _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS &
                ~OHCI_OWNERSHIP_CHANGE) ;
 
@@ -234,7 +234,7 @@ OHCI::OHCI(pci_info *info, Stack *stack)
 
                if ((control & OHCI_INTERRUPT_ROUTING) != 0) {
                        TRACE_ERROR("smm does not respond.\n");
-                       
+
                        // TODO: Enable this reset as soon as the non-specified
                        // reset a few lines later is replaced by a better 
solution.
                        //_WriteReg(OHCI_CONTROL, 
OHCI_HC_FUNCTIONAL_STATE_RESET);
@@ -1040,7 +1040,9 @@ OHCI::_FinishTransfers()
                        MutexLocker endpointLocker(endpoint->lock);
 
                        if ((endpoint->head_physical_descriptor & 
OHCI_ENDPOINT_HEAD_MASK)
-                                       != endpoint->tail_physical_descriptor) {
+                                       != endpoint->tail_physical_descriptor
+                                               && 
(endpoint->head_physical_descriptor
+                                                       & OHCI_ENDPOINT_HALTED) 
== 0) {
                                // there are still active transfers on this 
endpoint, we need
                                // to wait for all of them to complete, 
otherwise we'd read
                                // a potentially bogus data toggle value below

############################################################################

Commit:      2cc4703b91929ece9a3d95942a37363ff32344c7
URL:         http://cgit.haiku-os.org/haiku/commit/?id=2cc4703
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Mon May 28 16:14:05 2012 UTC

Fix and force USB audio driver to work with new OHCI module

* some functionality like recording temporarily disabled;
* set the endpoint speed call added;
* packet size hard-coded for 48kHz case;
* draft support for formats and sampling rate handling;
* implement sampling rate change on the fly;
* optimized using of starting frame;
* fix user_memory in buffer exchaqnge call;
* fix exchanged buffer recoriding processing;
* debug tweaks, fix current buffer switching;
* cleanup, cleanup, cleanup...

----------------------------------------------------------------------------

diff --git 
a/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.cpp 
b/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.cpp
index 0c91140..653dfae 100644
--- a/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.cpp
+++ b/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.cpp
@@ -11,6 +11,29 @@
 #include "audio.h"
 
 
+static struct RatePair {
+       uint32 rate;
+       uint32 rateId;
+} ratesMap[] = {
+       { 8000, B_SR_8000 },
+       { 11025, B_SR_11025 },
+       { 12000, B_SR_12000 },
+       { 16000, B_SR_16000 },
+       { 22050, B_SR_22050 },
+       { 24000, B_SR_24000 },
+       { 32000, B_SR_32000 },
+       { 44100, B_SR_44100 },
+       { 48000, B_SR_48000 },
+       { 64000, B_SR_64000 },
+       { 88200, B_SR_88200 },
+       { 96000, B_SR_96000 },
+       { 176400, B_SR_176400 },
+       { 192000, B_SR_192000 },
+       { 384000, B_SR_384000 },
+       { 1536000, B_SR_1536000 }
+};
+
+
 //
 //     Audio Stream information entities
 //
@@ -44,28 +67,31 @@ ASInterfaceDescriptor::~ASInterfaceDescriptor()
 ASEndpointDescriptor::ASEndpointDescriptor(usb_endpoint_descriptor* Endpoint,
                                        usb_as_cs_endpoint_descriptor* 
Descriptor)
                        :
-                       fAttributes(0),
+                       fCSAttributes(0),
                        fLockDelayUnits(0),
                        fLockDelay(0),
                        fMaxPacketSize(0),
-                       fEndpointAddress(0)
+                       fEndpointAddress(0),
+                       fEndpointAttributes(0)
 {
 //     usb_audiocontrol_header_descriptor *Header
 //             = (usb_audiocontrol_header_descriptor *)Interface->generic[i];
 
-       fAttributes = Descriptor->attributes;
+       fCSAttributes = Descriptor->attributes;
        fLockDelayUnits = Descriptor->lock_delay_units;
        fLockDelay = Descriptor->lock_delay;
 
 //     usb_endpoint_descriptor* endpoint = Interface->endpoint[0]->descr;
+       fEndpointAttributes = Endpoint->attributes;
        fEndpointAddress = Endpoint->endpoint_address;
        fMaxPacketSize = Endpoint->max_packet_size;
 
-       TRACE("fAttributes:%d\n", fAttributes);
+       TRACE("fCSAttributes:%d\n", fCSAttributes);
        TRACE("fLockDelayUnits:%d\n", fLockDelayUnits);
        TRACE("fLockDelay:%d\n", fLockDelay);
        TRACE("fMaxPacketSize:%d\n", fMaxPacketSize);
        TRACE("fEndpointAddress:%#02x\n", fEndpointAddress);
+       TRACE("fEndpointAttributes:%d\n", fEndpointAttributes);
 }
 
 
@@ -186,8 +212,10 @@ AudioStreamAlternate::AudioStreamAlternate(size_t 
alternate,
                        fAlternate(alternate),
                        fInterface(interface),
                        fEndpoint(endpoint),
-                       fFormat(format)
+                       fFormat(format),
+                       fSamplingRate(0)
 {
+       // SetSamplingRate(0); // init to default (max) sampling rate
 }
 
 
@@ -199,6 +227,166 @@ AudioStreamAlternate::~AudioStreamAlternate()
 }
 
 
+status_t
+AudioStreamAlternate::SetSamplingRate(uint32 newRate)
+{
+       TypeIFormatDescriptor* format
+               = static_cast<TypeIFormatDescriptor*>(Format());
+
+       if (format == NULL) {
+               TRACE_ALWAYS("Format not set for active alternate\n");
+               return B_NO_INIT;
+       }
+       
+       Vector<uint32>& frequencies = format->fSampleFrequencies;
+       bool continuous = format->fSampleFrequencyType == 0;
+       
+       if (newRate == 0) { // by default select max available
+               fSamplingRate = 0;
+               if (continuous)
+                       fSamplingRate = max_c(frequencies[0], frequencies[1]);
+               else
+                       for (int i = 0; i < frequencies.Count(); i++)
+                               fSamplingRate = max_c(fSamplingRate, 
frequencies[i]);
+       } else {
+               if (continuous) {
+                       uint32 min = min_c(frequencies[0], frequencies[1]);
+                       uint32 max = max_c(frequencies[0], frequencies[1]);
+                       if (newRate < min || newRate > max) {
+                               TRACE_ALWAYS("Rate %d outside of %d - %d 
ignored.\n",
+                                       newRate, min, max);
+                               return B_BAD_INDEX;
+                       }
+                       fSamplingRate = newRate;
+               } else {
+                       for (int i = 0; i < frequencies.Count(); i++)
+                               if (newRate == frequencies[i]) {
+                                       fSamplingRate = newRate;
+                                       return B_OK;
+                               }
+                               TRACE_ALWAYS("Rate %d not found - ignore 
it.\n", newRate);
+                               return B_BAD_INDEX;
+               }
+       }
+
+//     newRate = fSamplingRate;
+       return B_OK;
+}
+
+
+uint32
+AudioStreamAlternate::GetSamplingRateId(uint32 rate)
+{
+       if (rate == 0)
+               rate = fSamplingRate;
+
+       for (size_t i = 0; i < _countof(ratesMap); i++)
+               if (ratesMap[i].rate == rate)
+                       return ratesMap[i].rateId;
+
+       TRACE_ALWAYS("Ignore unsupported sample rate %d.\n", rate);
+       return 0;
+}
+
+
+uint32
+AudioStreamAlternate::GetSamplingRateIds()
+{
+       TypeIFormatDescriptor* format
+               = static_cast<TypeIFormatDescriptor*>(Format());
+
+       if (format == NULL) {
+               TRACE_ALWAYS("Format not set for active alternate\n");
+               return 0;
+       }
+       
+       uint32 rates = 0;
+       Vector<uint32>& frequencies = format->fSampleFrequencies;
+       if (format->fSampleFrequencyType == 0) { // continuous frequencies
+               uint32 min = min_c(frequencies[0], frequencies[1]);
+               uint32 max = max_c(frequencies[0], frequencies[1]);
+
+               for (int i = 0; i < frequencies.Count(); i++) {
+                       if (frequencies[i] < min || frequencies[i] > max)
+                               continue;
+                       rates |= GetSamplingRateId(frequencies[i]);
+               }
+       } else
+               for (int i = 0; i < frequencies.Count(); i++)
+                       rates |= GetSamplingRateId(frequencies[i]);
+
+       return rates;
+}
+
+
+uint32
+AudioStreamAlternate::GetFormatId()
+{
+       TypeIFormatDescriptor* format
+               = static_cast<TypeIFormatDescriptor*>(Format());
+
+       if (format == NULL || Interface() == NULL) {
+               TRACE_ALWAYS("Ignore alternate due format "
+                       "%#08x or interface %#08x null.\n", format, 
Interface());
+               return 0;
+       }
+
+       uint32 formats = 0;
+       switch (Interface()->fFormatTag) {
+               case UAF_PCM8: formats = B_FMT_8BIT_U; break;
+               case UAF_IEEE_FLOAT: formats = B_FMT_FLOAT; break;
+               case UAF_PCM:
+                       switch(format->fBitResolution) {
+                               case 8: formats = B_FMT_8BIT_S; break;
+                               case 16: formats = B_FMT_16BIT; break;
+                               case 18: formats = B_FMT_18BIT; break;
+                               case 20: formats = B_FMT_20BIT; break;
+                               case 24: formats = B_FMT_24BIT; break;
+                               case 32: formats = B_FMT_32BIT; break;
+                               default:
+                                       TRACE_ALWAYS("Ignore unsupported "
+                                               "bit resolution %d for 
alternate.\n",
+                                               format->fBitResolution);
+                                       break;
+                       }
+                       break;
+               default:
+                       TRACE_ALWAYS("Ignore unsupported "
+                               "format bit resolution %d for alternate.\n",
+                               Interface()->fFormatTag);
+                       break;
+       }
+       
+       return formats;
+}
+
+
+uint32
+AudioStreamAlternate::SamplingRateFromId(uint32 id)
+{
+       for (size_t i = 0; i < _countof(ratesMap); i++)
+               if (ratesMap[i].rateId == id)
+                       return ratesMap[i].rate;
+
+       TRACE_ALWAYS("Unknown sample rate id: %d.\n", id);
+       return 0;
+}
+
+
+status_t
+AudioStreamAlternate::SetSamplingRateById(uint32 newId)
+{
+       return SetSamplingRate(SamplingRateFromId(newId));
+}
+
+
+status_t
+AudioStreamAlternate::SetFormatId(uint32 /*newFormatId*/)
+{
+       return B_OK; // TODO
+}
+
+
 AudioStreamingInterface::AudioStreamingInterface(
                                        AudioControlInterface*  
controlInterface,
                                        size_t interface, usb_interface_list 
*List)
@@ -329,9 +517,8 @@ 
AudioStreamingInterface::GetFormatsAndRates(multi_description *Description)
        Description->interface_flags
                |= fIsInput ? B_MULTI_INTERFACE_RECORD : 
B_MULTI_INTERFACE_PLAYBACK;
 
-       uint32 rates = 0;
-       uint32 formats = 0;
-
+//     uint32 rates = 0;
+/*
        TypeIFormatDescriptor* format
                = static_cast<TypeIFormatDescriptor*>(
                                fAlternates[fActiveAlternate]->Format());
@@ -373,27 +560,9 @@ 
AudioStreamingInterface::GetFormatsAndRates(multi_description *Description)
                        }
                }
        }
-
-       switch (fAlternates[fActiveAlternate]->Interface()->fFormatTag) {
-               case UAF_PCM8:                  formats = B_FMT_8BIT_U; break;
-               case UAF_IEEE_FLOAT:    formats = B_FMT_FLOAT;  break;
-               case UAF_PCM:
-                       switch(format->fBitResolution) {
-                               case 8: formats = B_FMT_8BIT_S; break;
-                               case 16: formats = B_FMT_16BIT; break;
-                               case 18: formats = B_FMT_18BIT; break;
-                               case 20: formats = B_FMT_20BIT; break;
-                               case 24: formats = B_FMT_24BIT; break;
-                               case 32: formats = B_FMT_32BIT; break;
-                                       break;
-                               default:
-                                       TRACE_ALWAYS("Ignore unsupported "
-                                                       "bit resolution %d for 
alternate %d.\n",
-                                               format->fBitResolution, 
fActiveAlternate);
-                                       break;
-                       }
-                       break;
-       }
+*/
+       uint32 rates = fAlternates[fActiveAlternate]->GetSamplingRateIds();
+       uint32 formats = fAlternates[fActiveAlternate]->GetFormatId();
 
        if (fIsInput) {
                Description->input_rates = rates;
diff --git 
a/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.h 
b/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.h
index 5e89f5b..0815c9e 100644
--- a/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.h
+++ b/src/add-ons/kernel/drivers/audio/usb_audio/AudioStreamingInterface.h
@@ -40,11 +40,12 @@ public:
                                                        ~ASEndpointDescriptor();
 
 // protected:
-               uint8                           fAttributes;
+               uint8                           fCSAttributes;
                uint8                           fLockDelayUnits;
                uint16                          fLockDelay;
                uint16                          fMaxPacketSize;
                uint8                           fEndpointAddress;
+               uint8                           fEndpointAttributes;
 };
 
 
@@ -113,11 +114,22 @@ public:
                ASEndpointDescriptor*   Endpoint()      { return fEndpoint;     
 }
                _ASFormatDescriptor*    Format()        { return fFormat;       
 }
 
+               status_t                                SetSamplingRate(uint32 
newRate);
+               status_t                                
SetSamplingRateById(uint32 newId);
+               uint32                                  GetSamplingRate() { 
return fSamplingRate; }
+               uint32                                  
GetSamplingRateId(uint32 rate);
+               uint32                                  GetSamplingRateIds();
+               uint32                                  GetFormatId();
+               status_t                                SetFormatId(uint32 
newFormatId);
+               uint32                                  
SamplingRateFromId(uint32 id);
+
 protected:
+
                size_t                                  fAlternate;
                ASInterfaceDescriptor*  fInterface;
                ASEndpointDescriptor*   fEndpoint;
                _ASFormatDescriptor*    fFormat;
+               uint32                                  fSamplingRate;
 };
 
 
diff --git a/src/add-ons/kernel/drivers/audio/usb_audio/Device.cpp 
b/src/add-ons/kernel/drivers/audio/usb_audio/Device.cpp
index 16000ab..8bc2055 100644
--- a/src/add-ons/kernel/drivers/audio/usb_audio/Device.cpp
+++ b/src/add-ons/kernel/drivers/audio/usb_audio/Device.cpp
@@ -23,9 +23,9 @@ Device::Device(usb_device device)
                        fDevice(device),
                        fNonBlocking(false),
                        fAudioControl(this),
-                       fControlEndpoint(0),
-                       fInStreamEndpoint(0),
-                       fOutStreamEndpoint(0),
+               //      fControlEndpoint(0),
+               //      fInStreamEndpoint(0),
+               //      fOutStreamEndpoint(0),
                        fNotifyReadSem(-1),
                        fNotifyWriteSem(-1),
                        fNotifyBuffer(NULL),
@@ -42,6 +42,7 @@ Device::Device(usb_device device)
 
        fVendorID = deviceDescriptor->vendor_id;
        fProductID = deviceDescriptor->product_id;
+       fUSBVersion = deviceDescriptor->usb_version;
 
        fNotifyReadSem = create_sem(0, DRIVER_NAME"_notify_read");
        if (fNotifyReadSem < B_OK) {
@@ -155,9 +156,9 @@ Device::Close()
        // wait until possible notification handling finished...
        while (atomic_add(&fInsideNotify, 0) != 0)
                snooze(100);
-       gUSBModule->cancel_queued_transfers(fControlEndpoint);
-       gUSBModule->cancel_queued_transfers(fInStreamEndpoint);
-       gUSBModule->cancel_queued_transfers(fOutStreamEndpoint);
+//     gUSBModule->cancel_queued_transfers(fControlEndpoint);
+//     gUSBModule->cancel_queued_transfers(fInStreamEndpoint);
+//     gUSBModule->cancel_queued_transfers(fOutStreamEndpoint);
 
        fOpen = false;
 
@@ -289,9 +290,9 @@ Device::Removed()
        while (atomic_add(&fInsideNotify, 0) != 0)
                snooze(100);
 
-       gUSBModule->cancel_queued_transfers(fControlEndpoint);
-       gUSBModule->cancel_queued_transfers(fInStreamEndpoint);
-       gUSBModule->cancel_queued_transfers(fOutStreamEndpoint);
+//     gUSBModule->cancel_queued_transfers(fControlEndpoint);
+//     gUSBModule->cancel_queued_transfers(fInStreamEndpoint);
+//     gUSBModule->cancel_queued_transfers(fOutStreamEndpoint);
 /*
        if (fLinkStateChangeSem >= B_OK)
                release_sem_etc(fLinkStateChangeSem, 1, B_DO_NOT_RESCHEDULE);
@@ -415,7 +416,7 @@ Device::_MultiGetDescription(multi_description 
*multiDescription)
        TraceMultiDescription(&Description, Channels);
 
        if (user_memcpy(multiDescription, &Description,
-                               sizeof(multi_description)) != B_OK) {
+               sizeof(multi_description)) != B_OK) {
                return B_BAD_ADDRESS;
        }
 
@@ -555,6 +556,10 @@ Device::_MultiGetBuffers(multi_buffer_list* List)
                List->request_record_channels,
                List->request_record_buffer_size);
 
+       List->flags = 0;
+       List->return_playback_channels = 0;
+       List->return_record_channels = 0;
+       
        for (int i = 0; i < fStreams.Count() && status == B_OK; i++) {
                status = fStreams[i]->GetBuffers(List);
        }
@@ -564,18 +569,23 @@ Device::_MultiGetBuffers(multi_buffer_list* List)
 
 
 status_t
-Device::_MultiBufferExchange(multi_buffer_info* Info)
+Device::_MultiBufferExchange(multi_buffer_info* multiInfo)
 {
+       multi_buffer_info Info;
+       if (user_memcpy(&Info, multiInfo, sizeof(multi_buffer_info)) != B_OK)
+               return B_BAD_ADDRESS;
+
        for (int i = 0; i < fStreams.Count(); i++) {
                if (!fStreams[i]->IsRunning()) {
                        fStreams[i]->Start();
                }
        }
 
-       TRACE_ALWAYS("Exchange!\n");
+//     TRACE_ALWAYS("Exchange!\n");
+/*
        snooze(1000000);
        return B_OK;
-
+*/
        status_t status = B_ERROR;
        bool anyBufferProcessed = false;
        for (int i = 0; i < fStreams.Count() && !anyBufferProcessed; i++) {
@@ -586,10 +596,13 @@ Device::_MultiBufferExchange(multi_buffer_info* Info)
                        break;
                }
 
-               anyBufferProcessed = fStreams[i]->ExchangeBuffer(Info);
+               anyBufferProcessed = fStreams[i]->ExchangeBuffer(&Info);
                status = anyBufferProcessed ? B_OK : B_ERROR;
        }
 
+       if (user_memcpy(multiInfo, &Info, sizeof(multi_buffer_info)) != B_OK)
+               return B_BAD_ADDRESS;
+
        return status;
 }
 
@@ -713,7 +726,7 @@ Device::_SetupEndpoints()
 status_t
 Device::StopDevice()
 {
-       status_t result = B_OK; // WriteRXControlRegister(0);
+       status_t result = B_OK;
 
        if (result != B_OK) {
                TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, 
result);
diff --git a/src/add-ons/kernel/drivers/audio/usb_audio/Device.h 
b/src/add-ons/kernel/drivers/audio/usb_audio/Device.h
index e40991d..facf389 100644
--- a/src/add-ons/kernel/drivers/audio/usb_audio/Device.h
+++ b/src/add-ons/kernel/drivers/audio/usb_audio/Device.h
@@ -81,6 +81,7 @@ virtual       status_t                        StopDevice();
                bool                            fRemoved;
                vint32                          fInsideNotify;
                usb_device                      fDevice;
+               uint16                          fUSBVersion;
                uint16                          fVendorID;
                uint16                          fProductID;
 const  char *                          fDescription;
@@ -116,9 +117,9 @@ protected:
 //             uint16                          fFrameSize;
 
                // pipes for notifications and data io
-               usb_pipe                        fControlEndpoint;
-               usb_pipe                        fInStreamEndpoint;
-               usb_pipe                        fOutStreamEndpoint;
+//             usb_pipe                        fControlEndpoint;
+//             usb_pipe                        fInStreamEndpoint;
+//             usb_pipe                        fOutStreamEndpoint;
 
                // data stores for async usb transfers
                uint32                          fActualLengthRead;
diff --git a/src/add-ons/kernel/drivers/audio/usb_audio/Stream.cpp 
b/src/add-ons/kernel/drivers/audio/usb_audio/Stream.cpp
index 9ea21dc..6bf20f0 100644
--- a/src/add-ons/kernel/drivers/audio/usb_audio/Stream.cpp
+++ b/src/add-ons/kernel/drivers/audio/usb_audio/Stream.cpp
@@ -21,18 +21,16 @@ Stream::Stream(Device *device, size_t interface, 
usb_interface_list *List
                        fStreamEndpoint(0),
                        fIsRunning(false),
                        fArea(-1),
-                       fDescriptors(0),
+                       fAreaSize(0),
+                       fDescriptors(NULL),
                        fDescriptorsCount(0),
                        fCurrentBuffer(0),
                        fStartingFrame(0),
                        fSamplesCount(0),
-                       fProcessedBuffers(0)/*,
-                       fBuffersPhysAddress(0)/ *,
-                       fRealTime(0),
-                       fFramesCount(0),
-                       fBufferCycle(0)*/
+                       fPacketSize(0),
+                       fProcessedBuffers(0)
 {
-
+       memset(&fFormat, 0, sizeof(_multi_format));
 }
 
 
@@ -43,7 +41,7 @@ Stream::~Stream()
 
 
 status_t
-Stream::Init()
+Stream::_ChooseAlternate()
 {
        // lookup alternate with maximal (ch * 100 + resolution)
        uint16 maxChxRes = 0;
@@ -80,6 +78,12 @@ Stream::Init()
                TypeIFormatDescriptor* format
                                = 
static_cast<TypeIFormatDescriptor*>(fAlternates[i]->Format());
 
+               if (format->fNumChannels > 2) {
+                       TRACE("Ignore alternate %d - channel count %d "
+                                       "is not supported.\n", i, 
format->fNumChannels);
+                       continue;
+               }
+
                if (fAlternates[i]->Interface()->fFormatTag == UAF_PCM) {
                        switch(format->fBitResolution) {
                                default:
@@ -100,80 +104,94 @@ Stream::Init()
 
        if (maxChxRes <= 0) {
                TRACE("No compatible alternate found. Stream initialization 
failed.\n");
-               return fStatus;
+               return B_NO_INIT;
        }
+
        const ASEndpointDescriptor* endpoint = fAlternates[
                                                                                
                fActiveAlternate]->Endpoint();
        fIsInput = (endpoint->fEndpointAddress & USB_ENDPOINT_ADDR_DIR_IN)
                                                                                
                        == USB_ENDPOINT_ADDR_DIR_IN;
-       TRACE("Alternate %d selected!\n", fActiveAlternate);
+       TRACE("Alternate %d EP:%x selected for %s!\n",
+               fActiveAlternate, endpoint->fEndpointAddress,
+               fIsInput ? "recording" : "playback");
 
-       TypeIFormatDescriptor* format
-               = static_cast<TypeIFormatDescriptor*>(fAlternates[
-                                                                               
                fActiveAlternate]->Format());
+       return B_OK;
+}
 
-       size_t bufferSize = format->fNumChannels * format->fSubframeSize;
-       TRACE("bufferSize:%d\n", bufferSize);
-
-       bufferSize *= kSamplesBufferSize;
-       TRACE("bufferSize:%d\n", bufferSize);
-
-       bufferSize *= (sizeof(usb_iso_packet_descriptor) + 
endpoint->fMaxPacketSize); 
-       TRACE("bufferSize:%d\n", bufferSize);
-
-       bufferSize /= endpoint->fMaxPacketSize;
-       TRACE("bufferSize:%d\n", bufferSize);
-
-       bufferSize = (bufferSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1);
-       TRACE("bufferSize:%d\n", bufferSize);
-
-       fArea = create_area( (fIsInput) ? DRIVER_NAME "_record_area" :
-                                                                               
        DRIVER_NAME "_playback_area",
-                                                               
(void**)&fDescriptors, B_ANY_KERNEL_ADDRESS,
-                                                                       
bufferSize, B_CONTIGUOUS,
-                                                                               
B_READ_AREA | B_WRITE_AREA);
-       if (fArea < 0) {
-               TRACE_ALWAYS("Error of creating %#x - bytes size buffer 
area:%#010x\n",
-                                                                               
                bufferSize, fArea);
-               fStatus = fArea;
-               return fStatus;
-       }
 
-       physical_entry PhysEntry;
-       get_memory_map(fDescriptors, bufferSize, &PhysEntry, 1);
+status_t
+Stream::Init()
+{
+       fStatus = _ChooseAlternate();
+       //if (fStatus != B_OK)
+       return fStatus;
+}
 
-       TRACE_ALWAYS("Created area id: "
-                       "%d\naddress:%#010x[phys:%#010x]\nsize:%#010x\n",
-                       fArea, fDescriptors, PhysEntry.address, bufferSize);
 
-       fDescriptorsCount = bufferSize;
-       fDescriptorsCount /= (sizeof(usb_iso_packet_descriptor)
-                                                                               
                + endpoint->fMaxPacketSize);
+status_t
+Stream::_SetupBuffers()
+{
+       // allocate buffer for worst (maximal size) case
+       TypeIFormatDescriptor* format = static_cast<TypeIFormatDescriptor*>(
+               fAlternates[fActiveAlternate]->Format());
+       
+       uint32 samplingRate = fAlternates[fActiveAlternate]->GetSamplingRate();
+       uint32 sampleSize = format->fNumChannels * format->fSubframeSize;
+       
+       // data size pro 1 ms USB 1 frame or 1/8 ms USB 2 microframe
+       fPacketSize = samplingRate * sampleSize
+               / (fDevice->fUSBVersion < 0x0200 ? 1000 : 8000);
+       TRACE("packetSize:%ld\n", fPacketSize);
+
+       if (fArea == -1) {
+               fAreaSize = (sizeof(usb_iso_packet_descriptor) + fPacketSize)
+                       * sampleSize * 1024 / fPacketSize;
+               TRACE("estimate fAreaSize:%d\n", fAreaSize);
+
+               // round up to B_PAGE_SIZE and create area
+               fAreaSize = (fAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 
1);
+               TRACE("rounded up fAreaSize:%d\n", fAreaSize);
+
+               fArea = create_area( (fIsInput) ? DRIVER_NAME "_record_area"
+                       : DRIVER_NAME "_playback_area", (void**)&fDescriptors,
+                       B_ANY_KERNEL_ADDRESS, fAreaSize, B_CONTIGUOUS,
+                       B_READ_AREA | B_WRITE_AREA);
+               
+               if (fArea < 0) {
+                       TRACE_ALWAYS("Error of creating %#x - bytes size buffer 
area:%#010x\n",
+                                                                               
                        fAreaSize, fArea);
+                       fStatus = fArea;
+                       return fStatus;
+               }
+
+       //      physical_entry PhysEntry;
+       //      get_memory_map(fDescriptors, fAreaSize, &PhysEntry, 1);
+
+               TRACE_ALWAYS("Created area id:%d at addr:%#010x size:%#010lx\n",
+                       fArea, fDescriptors, fAreaSize);
+       }
+
+       // descriptors count
+       fDescriptorsCount = fAreaSize
+               / (sizeof(usb_iso_packet_descriptor) + fPacketSize);
+       
+       // we need same size sub-buffers. round it
        fDescriptorsCount /= kSamplesBufferCount;
-       // we need same size buffers. round it!
        fDescriptorsCount *= kSamplesBufferCount;
+       TRACE("descriptorsCount:%d\n", fDescriptorsCount);
 
-       fSamplesCount = fDescriptorsCount * endpoint->fMaxPacketSize;
-       TRACE("samplesCount:%d\n", fSamplesCount);
-
-       fSamplesCount /= format->fNumChannels * format->fSubframeSize;
+       // samples count
+       fSamplesCount = fDescriptorsCount * fPacketSize / sampleSize;
        TRACE("samplesCount:%d\n", fSamplesCount);
 
+       // initialize descriptors array
        for (size_t i = 0; i < fDescriptorsCount; i++) {
-               fDescriptors[i].request_length = endpoint->fMaxPacketSize;
+               fDescriptors[i].request_length = fPacketSize;
                fDescriptors[i].actual_length = 0;
                fDescriptors[i].status = B_OK;
        }
 
-/*     uint32* b = (uint32*)(fDescriptors + fDescriptorsCount);
-       for (size_t i = 0; i < fSamplesCount; i++) {
-               b[i] = i * 10;
-       }*/
-
-       TRACE_ALWAYS("Descriptors count:%d\nsample size:%d\nchannels:%d:%d\n",
-                       fDescriptorsCount, format->fSubframeSize, 
format->fNumChannels,
-                               sizeof(usb_iso_packet_descriptor));
-       return fStatus = B_OK;
+       return fStatus;
 }
 
 
@@ -193,14 +211,32 @@ Stream::OnSetConfiguration(usb_device device,
                return B_ERROR;
        }
 
-       /*status_t status =*/ gUSBModule->set_alt_interface(device, interface);
+       status_t status = gUSBModule->set_alt_interface(device, interface);
        uint8 address = 
fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress;
 
+       TRACE_ALWAYS("set_alt_interface %x\n", status);
+
        for (size_t i = 0; i < interface->endpoint_count; i++) {
                if (address == interface->endpoint[i].descr->endpoint_address) {
                        fStreamEndpoint = interface->endpoint[i].handle;
                        TRACE("%s Stream Endpoint [address %#04x] handle is: 
%#010x.\n",
                                        fIsInput ? "Input" : "Output", address, 
fStreamEndpoint);
+/*                     
+                       size_t actualLength = 0;
+                       uint32 speed = 48000;
+                       uint8 data[3];
+                       data[0] = 0xFF & speed;
+                       data[1] = (uint8) 0xFF & speed >> 8;
+                       data[2] = (uint8) 0xFF & speed >> 16;
+       
+                       status_t status = gUSBModule->send_request(device,
+                                       USB_REQTYPE_CLASS | 
USB_REQTYPE_ENDPOINT_OUT,
+                                       UAS_SET_CUR, UAS_SAMPLING_FREQ_CONTROL 
<< 8,
+                                       address, 3, data, &actualLength);
+                       
+                       TRACE_ALWAYS("set_speed for ep %#x %d: %x\n",
+                                       address, actualLength, status);
+*/                     
                        return B_OK;
                }
        }
@@ -216,12 +252,9 @@ Stream::Start()
 {
        status_t result = B_BUSY;
        if (!fIsRunning) {
-               if (!fIsInput) {
-                       // for (size_t i = 0; i < kSamplesBufferCount; i++)
-                       //      result = _QueueNextTransfer(i);
-                       // TODO
-                       //      result = _QueueNextTransfer(0);
-                       result = B_OK;
+               if (!fIsInput) { // TODO: recording
+                       for (size_t i = 0; i < kSamplesBufferCount; i++)
+                               result = _QueueNextTransfer(i, true);
                } else
                        result = B_OK;
                fIsRunning = result == B_OK;
@@ -243,7 +276,7 @@ Stream::Stop()
 
 
 status_t
-Stream::_QueueNextTransfer(size_t queuedBuffer)
+Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
 {
        TypeIFormatDescriptor* format
                = static_cast<TypeIFormatDescriptor*>(fAlternates[
@@ -259,14 +292,35 @@ Stream::_QueueNextTransfer(size_t queuedBuffer)
        TRACE("buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n",
                        buffers + bufferSize * queuedBuffer, bufferSize,
                        fDescriptors + queuedBuffer * packetsCount, 
packetsCount);
+#if 0
+{      
+       static int16 sin[24] = { 0, 4277, 8481, 12540, 16384, 19948, 23170, 
25996,
+               28378, 30273, 31651, 32487, 32767, 32487, 31651, 30273, 28378, 
25996,
+               23170, 19948, 16384, 12540, 8481, 4277 };
+       static uint16 sample = 0;
+       static bool sign = true;
+                       
+                       uint16* b = (uint16*)(buffers + bufferSize * 
queuedBuffer);
+                       size_t length = bufferSize;
+                       for (size_t u = 0; u < length / 2; u += 2) {
+                               b[u] = b[u + 1] = sign ? sin[sample] : 
-sin[sample];
+                               sample ++;
+                               if (sample == 24) {
+                                       sample = 0;
+                                       sign = !sign;
+                               }
+                       }
+}
+#endif
 
-       return gUSBModule->queue_isochronous(fStreamEndpoint,
+       status_t status = gUSBModule->queue_isochronous(fStreamEndpoint,
                        buffers + bufferSize * queuedBuffer, bufferSize,
                        fDescriptors + queuedBuffer * packetsCount, 
packetsCount,
-                       NULL/*&fStartingFrame*/, USB_ISO_ASAP,
+                       &fStartingFrame, start ? USB_ISO_ASAP : 0,
                        Stream::_TransferCallback, this);
 
-       return B_OK;
+       TRACE("frame:%#010x\n", fStartingFrame);
+       return status; // B_OK;
 }
 
 
@@ -274,48 +328,39 @@ void
 Stream::_TransferCallback(void *cookie, int32 status, void *data,
        uint32 actualLength)
 {
-       Stream *stream = (Stream *)cookie;
-
-       stream->fCurrentBuffer++;
-       if (stream->fCurrentBuffer >= kSamplesBufferCount) {
-               stream->fCurrentBuffer = 0;
+       if (status == B_CANCELED) {
+               TRACE_ALWAYS("Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n",
+                          cookie, status, data, actualLength);
+               return;
        }
 
-       stream->_DumpDescriptors();
+       Stream *stream = (Stream *)cookie;
+       
+       stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % 
kSamplesBufferCount;
 
        stream->_DumpDescriptors();
 
-       /*
-       status_t result = stream->_QueueNextTransfer(stream->fCurrentBuffer);
+       /*status_t result =*/ 
stream->_QueueNextTransfer(stream->fCurrentBuffer, false);
 
        if (atomic_add(&stream->fProcessedBuffers, 1) > 
(int32)kSamplesBufferCount) {
                TRACE_ALWAYS("Processed buffers overflow:%d\n", 
stream->fProcessedBuffers);
        }
-*/
+
        release_sem_etc(stream->fDevice->fBuffersReadySem, 1, 
B_DO_NOT_RESCHEDULE);
 
        // TRACE_ALWAYS("st:%#010x, len:%d -> %#010x\n", status, actualLength, 
result);
-       TRACE_ALWAYS("st:%#010x, data:%#010x, len:%d\n", status, data, 
actualLength);
-
-/*     if (status != B_OK) {
-               TRACE_ALWAYS("Device status error:%#010x\n", status);
-               status_t result = 
gUSBModule->clear_feature(device->fControLeNDPOint,
-                                                                               
                        USB_FEATURE_ENDPOINT_HALT);
-               if (result != B_OK)
-                       TRACE_ALWAYS("Error during clearing of HALT 
state:%#010x.\n", result);
-       }
-*/
+       TRACE("st:%#010x, data:%#010x, len:%d\n", status, data, actualLength);
 }
 
 
 void
 Stream::_DumpDescriptors()
 {
-       size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
+       //size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
        size_t from = /*fCurrentBuffer > 0 ? packetsCount :*/ 0 ;
        size_t to   = /*fCurrentBuffer > 0 ?*/ fDescriptorsCount /*: 
packetsCount*/ ;
        for (size_t i = from; i < to; i++) {
-               TRACE_ALWAYS("%d:req_len:%d; act_len:%d; stat:%#010x\n", i,
+               TRACE("%d:req_len:%d; act_len:%d; stat:%#010x\n", i,
                        fDescriptors[i].request_length, 
fDescriptors[i].actual_length,
                        fDescriptors[i].status);
        }
@@ -359,18 +404,13 @@ Stream::SetEnabledChannels(uint32& offset, 
multi_channel_enable *Enable)
 status_t
 Stream::GetGlobalFormat(multi_format_info *Format)
 {
-       if (IsInput()) {
-               // TODO
-               Format->input.rate = B_SR_48000;
-               Format->input.cvsr = 48000;
-               Format->input.format = B_FMT_16BIT;
-       } else {
-               // TODO
-               Format->output.rate = B_SR_48000;
-               Format->output.cvsr = 48000;
-               Format->output.format = B_FMT_16BIT;
-       }
-
+       _multi_format* format = fIsInput ? &Format->input : &Format->output;
+       format->cvsr = fAlternates[fActiveAlternate]->GetSamplingRate();
+       format->rate = fAlternates[fActiveAlternate]->GetSamplingRateId(0);
+       format->format = fAlternates[fActiveAlternate]->GetFormatId();
+       TRACE("%s.rate:%d cvsr:%f format:%#08x\n",
+               fIsInput ? "input" : "ouput",
+               format->rate, format->cvsr, format->format);
        return B_OK;
 }
 
@@ -378,19 +418,49 @@ Stream::GetGlobalFormat(multi_format_info *Format)
 status_t
 Stream::SetGlobalFormat(multi_format_info *Format)
 {
-       if (IsInput()) {
-               // TODO
-               TRACE("input.rate:%d\n",                Format->input.rate);
-               TRACE("input.cvsr:%f\n",                Format->input.cvsr);
-               TRACE("input.format:%#08x\n",   Format->input.format);
-       } else {
-               // TODO
-               TRACE("output.rate:%d\n",               Format->output.rate);
-               TRACE("output.cvsr:%f\n",               Format->output.cvsr);
-               TRACE("output.format:%#08x\n",  Format->output.format);
+       _multi_format* format = fIsInput ? &Format->input : &Format->output;
+       AudioStreamAlternate* alternate = fAlternates[fActiveAlternate];
+       if (format->rate == alternate->GetSamplingRateId(0)
+               && format->format == alternate->GetFormatId()) {
+               TRACE("No changes required\n");
+               return B_OK;
        }
 
-       return B_OK;
+       alternate->SetSamplingRateById(format->rate);
+       alternate->SetFormatId(format->format);
+       TRACE("%s.rate:%d cvsr:%f format:%#08x\n",
+               fIsInput ? "input" : "ouput",
+               format->rate, format->cvsr, format->format);
+
+       // cancel data flow - it will be rewaked at next buffer exchange call
+       Stop();
+
+       // TODO: wait for cancelling?
+
+       // layout of buffers should be adjusted after changing sampling 
rate/format
+       status_t status = _SetupBuffers();
+
+       if (status != B_OK)
+               return status;
+
+       // set endpoint speed   
+       uint32 samplingRate = fAlternates[fActiveAlternate]->GetSamplingRate();
+       size_t actualLength = 0;
+       uint8 data[3];
+       data[0] = 0xFF & samplingRate;
+       data[1] = 0xFF & samplingRate >> 8;
+       data[2] = 0xFF & samplingRate >> 16;
+       uint8 address = 
fAlternates[fActiveAlternate]->Endpoint()->fEndpointAddress;
+
+       status = gUSBModule->send_request(fDevice->fDevice,
+                       USB_REQTYPE_CLASS | USB_REQTYPE_ENDPOINT_OUT,
+                       UAS_SET_CUR, UAS_SAMPLING_FREQ_CONTROL << 8,
+                       address, 3, data, &actualLength);
+       
+       TRACE_ALWAYS("set_speed %02x%02x%02x for ep %#x %d: %x\n",
+                       data[0], data[1], data[2], 
+                       address, actualLength, status);
+       return status;
 }
 
 
@@ -398,6 +468,8 @@ status_t
 Stream::GetBuffers(multi_buffer_list* List)
 {
 // TODO: check the available buffers count!
+       if (fAreaSize == 0)
+               return B_NO_INIT;
 
        int32 startChannel = List->return_playback_channels;
        buffer_desc** Buffers = List->playback_buffers;
@@ -425,8 +497,8 @@ Stream::GetBuffers(multi_buffer_list* List)
        TypeIFormatDescriptor* format
                = static_cast<TypeIFormatDescriptor*>(
                                                
fAlternates[fActiveAlternate]->Format());
-       const ASEndpointDescriptor* endpoint
-                                       = 
fAlternates[fActiveAlternate]->Endpoint();
+//     const ASEndpointDescriptor* endpoint
+//                                     = 
fAlternates[fActiveAlternate]->Endpoint();
 
        // [buffer][channel] init buffers
        for (size_t buffer = 0; buffer < kSamplesBufferCount; buffer++) {
@@ -443,7 +515,7 @@ Stream::GetBuffers(multi_buffer_list* List)
                        Buffers[buffer][channel].base
                                                                        = 
(char*)(fDescriptors + fDescriptorsCount);
                        // shift for whole buffer if required
-                       size_t bufferSize = endpoint->fMaxPacketSize
+                       size_t bufferSize = 
fPacketSize/*endpoint->fMaxPacketSize*/
                                                                        * 
(fDescriptorsCount / kSamplesBufferCount);
                        Buffers[buffer][channel].base += buffer * bufferSize;
                        // shift for channel if required
@@ -467,29 +539,6 @@ Stream::GetBuffers(multi_buffer_list* List)
 }
 
 
-/*
-int32
-Stream::InterruptHandler(uint32 SignaledChannelsMask)
-{
-       uint32 ChannelMask = 1 << fHWChannel;
-       if ((SignaledChannelsMask & ChannelMask) == 0) {
-               return B_UNHANDLED_INTERRUPT;
-       }
-
-       uint32 CurrentSamplePositionFlag = fDevice->ReadPCI32(TrCurSPFBReg);
-
-       fRealTime = system_time();
-       fFramesCount += fBufferSize;
-       fBufferCycle = ((CurrentSamplePositionFlag & ChannelMask) == 
ChannelMask) ? 1 : 0;
-
-fCSP = CurrentSamplePositionFlag;
-
-       release_sem_etc(fDevice->fBuffersReadySem, 1, B_DO_NOT_RESCHEDULE);
-
-       return B_HANDLED_INTERRUPT;
-}*/
-
-
 bool
 Stream::ExchangeBuffer(multi_buffer_info* Info)
 {
@@ -499,12 +548,15 @@ Stream::ExchangeBuffer(multi_buffer_info* Info)
                return false;
        }
 
-       Info->played_real_time = system_time();// TODO fRealTime;
-       Info->played_frames_count += fSamplesCount / kSamplesBufferCount;
-       Info->playback_buffer_cycle = fCurrentBuffer;
-
-       fCurrentBuffer++;
-       fCurrentBuffer %= kSamplesBufferCount;
+       if (fIsInput) {
+               Info->recorded_real_time = system_time();// TODO fRealTime;
+               Info->recorded_frames_count += fSamplesCount / 
kSamplesBufferCount;
+               Info->record_buffer_cycle = fCurrentBuffer;
+       } else {
+               Info->played_real_time = system_time();// TODO fRealTime;
+               Info->played_frames_count += fSamplesCount / 
kSamplesBufferCount;
+               Info->playback_buffer_cycle = fCurrentBuffer;
+       }
 
        atomic_add(&fProcessedBuffers, -1);
 
diff --git a/src/add-ons/kernel/drivers/audio/usb_audio/Stream.h 
b/src/add-ons/kernel/drivers/audio/usb_audio/Stream.h
index 960ef9c..927e08b 100644
--- a/src/add-ons/kernel/drivers/audio/usb_audio/Stream.h
+++ b/src/add-ons/kernel/drivers/audio/usb_audio/Stream.h
@@ -62,22 +62,21 @@ protected:
                uint8                           fTerminalID;
                usb_pipe                        fStreamEndpoint;
                bool                            fIsRunning;
-/*             uint32                          fHWChannel;*/
                area_id                         fArea;
+               size_t                          fAreaSize;
                usb_iso_packet_descriptor*      fDescriptors;
                size_t                                          
fDescriptorsCount;
                size_t                          fCurrentBuffer;
                uint32                          fStartingFrame;
                size_t                          fSamplesCount;
+               size_t                          fPacketSize;
                int32                           fProcessedBuffers;
-//             void*                           fBuffersPhysAddress;
-/*             bigtime_t                       fRealTime;
-               bigtime_t                       fFramesCount;
-               int32                           fBufferCycle;
-public:
-               uint32                          fCSP; */
+               _multi_format           fFormat;
+
 private:
-               status_t                        _QueueNextTransfer(size_t 
buffer);
+               status_t                        _ChooseAlternate();
+               status_t                        _SetupBuffers();
+               status_t                        _QueueNextTransfer(size_t 
buffer, bool start);
 static void                            _TransferCallback(void *cookie, int32 
status,
                                                                void *data, 
uint32 actualLength);
                void                            _DumpDescriptors();

############################################################################

Commit:      673ef2cbafb7291204d1cfcb79466ea7fe799beb
URL:         http://cgit.haiku-os.org/haiku/commit/?id=673ef2c
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Sun Jun 23 19:05:20 2013 UTC

USB audio: cleanup and codestyle fixes.

* cleanup and codestyle fixes;
* AudioFunction module contents purged out as unused.

----------------------------------------------------------------------------

diff --git 
a/src/add-ons/kernel/drivers/audio/usb_audio/AudioControlInterface.cpp 
b/src/add-ons/kernel/drivers/audio/usb_audio/AudioControlInterface.cpp
index 417a4b0..3bf0b52 100644
--- a/src/add-ons/kernel/drivers/audio/usb_audio/AudioControlInterface.cpp
+++ b/src/add-ons/kernel/drivers/audio/usb_audio/AudioControlInterface.cpp
@@ -1,14 +1,16 @@
 /*
  *     Driver for USB Audio Device Class devices.
- *     Copyright (c) 2009,10,12 S.Zharski <imker@xxxxxx>
+ *     Copyright (c) 2009-13 S.Zharski <imker@xxxxxx>
  *     Distributed under the tems of the MIT license.
  *
  */
 
 #include "AudioControlInterface.h"
-#include "Settings.h"
-#include "Device.h"
+
 #include "audio.h"
+#include "Device.h"
+#include "Driver.h"
+#include "Settings.h"
 
 
 enum TerminalTypes {
@@ -185,14 +187,14 @@ GetTerminalDescription(uint16 TerminalType)
 
 
 _AudioControl::_AudioControl(AudioControlInterface*    interface,
-                                       usb_audiocontrol_header_descriptor* 
Header)
-                       :
-                       fStatus(B_NO_INIT),
-                       fInterface(interface),
-                       fSubType(Header->descriptor_subtype),
-                       fID(0),
-                       fSourceID(0),
-                       fStringIndex(0)
+               usb_audiocontrol_header_descriptor* Header)
+       :
+       fStatus(B_NO_INIT),
+       fInterface(interface),
+       fSubType(Header->descriptor_subtype),
+       fID(0),
+       fSourceID(0),
+       fStringIndex(0)
 {
 }
 
@@ -205,51 +207,45 @@ _AudioControl::~_AudioControl()
 AudioChannelCluster*
 _AudioControl::OutCluster()
 {
-       if (SourceID() == 0 || fInterface == NULL) {
+       if (SourceID() == 0 || fInterface == NULL)
                return NULL;
-       }
 
        _AudioControl* control = fInterface->Find(SourceID());
-       if (control == NULL) {
+       if (control == NULL)
                return NULL;
-       }
 
        return control->OutCluster();
 }
 
 
 AudioChannelCluster::AudioChannelCluster()
-                       :
-                       fOutChannelsNumber(0),
-                       fChannelsConfig(0),
-                       fChannelNames(0)
+       :
+       fOutChannelsNumber(0),
+       fChannelsConfig(0),
+       fChannelNames(0)
 {
-
 }
 
 
 AudioChannelCluster::~AudioChannelCluster()
 {
-
 }
 
 
 _Terminal::_Terminal(AudioControlInterface*    interface,
-                                       usb_audiocontrol_header_descriptor* 
Header)
-                       :
-                       _AudioControl(interface, Header),
-                       fTerminalType(0),
-                       fAssociatedTerminal(0),
-                       fClockSourceId(0),
-                       fControlsBitmap(0)
+       usb_audiocontrol_header_descriptor* Header)
+       :
+       _AudioControl(interface, Header),
+       fTerminalType(0),
+       fAssociatedTerminal(0),
+       fClockSourceId(0),
+       fControlsBitmap(0)
 {
-
 }
 
 
 _Terminal::~_Terminal()
 {
-
 }
 
 
@@ -268,9 +264,9 @@ _Terminal::IsUSBIO()
 
 
 InputTerminal::InputTerminal(AudioControlInterface*    interface,
-                                       usb_audiocontrol_header_descriptor* 
Header)
-                       :
-                       _AudioChannelCluster<_Terminal>(interface, Header)
+               usb_audiocontrol_header_descriptor* Header)
+       :
+       _AudioChannelCluster<_Terminal>(interface, Header)
 {
        usb_input_terminal_descriptor_r1* Terminal
                = (usb_input_terminal_descriptor_r1*) Header;
@@ -280,7 +276,7 @@ InputTerminal::InputTerminal(AudioControlInterface* 
interface,
 
        TRACE("Input Terminal ID:%d >>>\n",     fID);
        TRACE("Terminal type:%s (%#06x)\n",
-                               GetTerminalDescription(fTerminalType), 
fTerminalType);
+               GetTerminalDescription(fTerminalType), fTerminalType);
        TRACE("Assoc.terminal:%d\n",    fAssociatedTerminal);
 
        if (fInterface->SpecReleaseNumber() < 0x200) {
@@ -317,9 +313,9 @@ InputTerminal::~InputTerminal()
 
 
 OutputTerminal::OutputTerminal(AudioControlInterface*  interface,
-                                       usb_audiocontrol_header_descriptor* 
Header)
-                       :
-                       _Terminal(interface, Header)
+               usb_audiocontrol_header_descriptor* Header)
+       :
+       _Terminal(interface, Header)
 {
        usb_output_terminal_descriptor_r1* Terminal
                = (usb_output_terminal_descriptor_r1*) Header;
@@ -331,7 +327,7 @@ OutputTerminal::OutputTerminal(AudioControlInterface*       
interface,
 
        TRACE("Output Terminal ID:%d >>>\n",    fID);
        TRACE("Terminal type:%s (%#06x)\n",
-                               GetTerminalDescription(fTerminalType), 
fTerminalType);
+               GetTerminalDescription(fTerminalType), fTerminalType);
        TRACE("Assoc.terminal:%d\n",            fAssociatedTerminal);
        TRACE("Source ID:%d\n",                         fSourceID);
 
@@ -361,10 +357,10 @@ OutputTerminal::~OutputTerminal()
 
 
 MixerUnit::MixerUnit(AudioControlInterface*    interface,
-                                       usb_audiocontrol_header_descriptor* 
Header)
-                       :
-                       _AudioChannelCluster<_AudioControl>(interface, Header),
-                       fControlsBitmap(0)
+               usb_audiocontrol_header_descriptor* Header)
+       :
+       _AudioChannelCluster<_AudioControl>(interface, Header),
+       fControlsBitmap(0)
 {
        usb_mixer_unit_descriptor* Mixer
                = (usb_mixer_unit_descriptor*) Header;
@@ -384,7 +380,7 @@ MixerUnit::MixerUnit(AudioControlInterface* interface,
        if (fInterface->SpecReleaseNumber() < 0x200) {
                usb_output_channels_descriptor_r1* OutChannels
                        = (usb_output_channels_descriptor_r1*)
-                               &Mixer->input_pins[Mixer->num_input_pins];
+                       &Mixer->input_pins[Mixer->num_input_pins];
 
                fOutChannelsNumber      = OutChannels->num_output_pins;
                fChannelsConfig         = OutChannels->channel_config;
@@ -396,7 +392,7 @@ MixerUnit::MixerUnit(AudioControlInterface* interface,
        } else {
                usb_output_channels_descriptor* OutChannels
                        = (usb_output_channels_descriptor*)
-                               &Mixer->input_pins[Mixer->num_input_pins];
+                       &Mixer->input_pins[Mixer->num_input_pins];
 
                fOutChannelsNumber      = OutChannels->num_output_pins;
                fChannelsConfig         = OutChannels->channel_config;
@@ -432,10 +428,10 @@ MixerUnit::~MixerUnit()
 
 
 SelectorUnit::SelectorUnit(AudioControlInterface*      interface,
-                                       usb_audiocontrol_header_descriptor* 
Header)
-                       :
-                       _AudioControl(interface, Header),
-                       fControlsBitmap(0)
+               usb_audiocontrol_header_descriptor* Header)
+       :
+       _AudioControl(interface, Header),
+       fControlsBitmap(0)
 {
        usb_selector_unit_descriptor* Selector
                = (usb_selector_unit_descriptor*) Header;
@@ -450,10 +446,8 @@ SelectorUnit::SelectorUnit(AudioControlInterface*  
interface,
        }
 
        if (fInterface->SpecReleaseNumber() < 0x200) {
-
                fStringIndex = Selector->input_pins[Selector->num_input_pins];
        } else {
-
                fControlsBitmap = 
Selector->input_pins[Selector->num_input_pins];
                fStringIndex = Selector->input_pins[Selector->num_input_pins + 
1];
 
@@ -474,19 +468,16 @@ SelectorUnit::~SelectorUnit()
 AudioChannelCluster*
 SelectorUnit::OutCluster()
 {
-       if (fInterface == NULL) {
+       if (fInterface == NULL)
                return NULL;
-       }
 
        for (int i = 0; i < fInputPins.Count(); i++) {
                _AudioControl* control = fInterface->Find(fInputPins[i]);
-               if (control == NULL) {
+               if (control == NULL)
                        continue;
-               }
 
-               if (control->OutCluster() != NULL) {
+               if (control->OutCluster() != NULL)
                        return control->OutCluster();
-               }
        }
 
        return NULL;
@@ -494,9 +485,9 @@ SelectorUnit::OutCluster()
 
 
 FeatureUnit::FeatureUnit(AudioControlInterface*        interface,
-                                       usb_audiocontrol_header_descriptor* 
Header)

[ *** diff truncated: 5358 lines dropped *** ]


############################################################################

Commit:      b42544e71d4ccb28fec64112b8facaddf91a94f5
URL:         http://cgit.haiku-os.org/haiku/commit/?id=b42544e
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Thu Jun 27 14:14:02 2013 UTC

USB audio: fInsideNotify guard added to Remote/Close callbacks

----------------------------------------------------------------------------

############################################################################

Commit:      1a6d941d1dea2ab1d924983cb1b09b0360c5e8bf
URL:         http://cgit.haiku-os.org/haiku/commit/?id=1a6d941
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Tue Jun 25 21:05:56 2013 UTC

USB audio: Use system-wide USB_audio.h instead local one

* switching driver code to use system usb/USB_audio.h header;
* refactor USB_audio.h specification header for both USB audio specifications.

----------------------------------------------------------------------------

############################################################################

Commit:      7ff9cd33a9d13b3993a60817482dd83df10bee8b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=7ff9cd3
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Thu Jun 27 19:22:54 2013 UTC

USB audio: Refactor TRACE-es for more configurability

----------------------------------------------------------------------------

############################################################################

Commit:      a8066fe34aa482e529b7afcedec1456c8fd7bd02
URL:         http://cgit.haiku-os.org/haiku/commit/?id=a8066fe
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Fri Jun 28 13:19:11 2013 UTC

USB audio: dev.entry number should be 1-based, etc

* USB audio device entry number made 1-based instead of 0. According to
  Haiku MultiAudio specs audio device entries should be 1-based but
  0-based;
* cleanup and refactoring. No functional changes;
* recording stream activated;
* fix input channels description report and codestyle issues.

----------------------------------------------------------------------------

############################################################################

Commit:      353a4e04d132525d1d2ce39e57971eed83267c9d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=353a4e0
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Wed Jul 17 05:12:00 2013 UTC

USB audio: Fix function of Selector Unit control

* restore function of Selector Unit that was previously disabled;
* fix Selector Unit input pin names "Unknwon" case.

----------------------------------------------------------------------------

############################################################################

Commit:      743d75946f1b6ca948107bf8c2a5b115ad9f33de
URL:         http://cgit.haiku-os.org/haiku/commit/?id=743d759
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Wed Jul 17 20:09:13 2013 UTC

USB audio: Mixer Unit control implementation

* support of Mixer Unit control in UI implemented;
* improve SetMix/GetMix to support Mixer Unit control type;
* cleanup and improvements.

----------------------------------------------------------------------------

############################################################################

Commit:      14f92002e1f4542a8afc6d43a2fd145eabc7519d
URL:         http://cgit.haiku-os.org/haiku/commit/?id=14f9200
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Tue Aug  6 04:14:28 2013 UTC

USB audio: use new(std::nothrow) for allocations

* Use new(std::nothrow) for allocations;
* Input buffer index counter restored;
* Improve unsupported UI controls debug info tracing;
* Some cleanup.

----------------------------------------------------------------------------

############################################################################

Revision:    hrev45972
Commit:      a69892cadca9288b901ac66273d342bfb4329373
URL:         http://cgit.haiku-os.org/haiku/commit/?id=a69892c
Author:      Siarzhuk Zharski <zharik@xxxxxx>
Date:        Sat Aug 17 19:22:52 2013 UTC

Rename driver folder 'usb_audio' to 'usb'

... just because the source path ./kernel/drivers/audio/usb obviously
references audio hardware so "_audio" suffix is excessive.

No functional changes.

----------------------------------------------------------------------------


Other related posts:

  • » [haiku-commits] haiku: hrev45972 - src/add-ons/kernel/drivers/audio/usb_audio src/add-ons/kernel/drivers/audio/usb src/add-ons/kernel/busses/usb headers/os/drivers/usb - zharik