usb_audio: Properly separate kernel and userland data.
* Allocate the descriptors array separately from the data area. * Clone the data area for kernel use separately from userland use. Fixes the remaining SMAP problems with this driver.
This commit is contained in:
@@ -24,6 +24,7 @@ Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
|
|||||||
fStreamEndpoint(0),
|
fStreamEndpoint(0),
|
||||||
fIsRunning(false),
|
fIsRunning(false),
|
||||||
fArea(-1),
|
fArea(-1),
|
||||||
|
fKernelArea(-1),
|
||||||
fAreaSize(0),
|
fAreaSize(0),
|
||||||
fDescriptors(NULL),
|
fDescriptors(NULL),
|
||||||
fDescriptorsCount(0),
|
fDescriptorsCount(0),
|
||||||
@@ -40,6 +41,8 @@ Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
|
|||||||
Stream::~Stream()
|
Stream::~Stream()
|
||||||
{
|
{
|
||||||
delete_area(fArea);
|
delete_area(fArea);
|
||||||
|
delete_area(fKernelArea);
|
||||||
|
delete fDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -173,21 +176,21 @@ Stream::_SetupBuffers()
|
|||||||
if (fArea != -1) {
|
if (fArea != -1) {
|
||||||
Stop();
|
Stop();
|
||||||
delete_area(fArea);
|
delete_area(fArea);
|
||||||
|
delete_area(fKernelArea);
|
||||||
|
delete fDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
fAreaSize = (sizeof(usb_iso_packet_descriptor) + fPacketSize)
|
fAreaSize = sampleSize * kSamplesBufferSize;
|
||||||
* sampleSize * 1024 / fPacketSize;
|
|
||||||
TRACE(INF, "estimate fAreaSize:%d\n", fAreaSize);
|
TRACE(INF, "estimate fAreaSize:%d\n", fAreaSize);
|
||||||
|
|
||||||
// round up to B_PAGE_SIZE and create area
|
// round up to B_PAGE_SIZE and create area
|
||||||
fAreaSize = (fAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1);
|
fAreaSize = (fAreaSize + (B_PAGE_SIZE - 1)) &~ (B_PAGE_SIZE - 1);
|
||||||
TRACE(INF, "rounded up fAreaSize:%d\n", fAreaSize);
|
TRACE(INF, "rounded up fAreaSize:%d\n", fAreaSize);
|
||||||
|
|
||||||
fArea = create_area( (fIsInput) ? DRIVER_NAME "_record_area"
|
fArea = create_area(fIsInput ? DRIVER_NAME "_record_area"
|
||||||
: DRIVER_NAME "_playback_area", (void**)&fDescriptors,
|
: DRIVER_NAME "_playback_area", (void**)&fBuffers,
|
||||||
B_ANY_KERNEL_ADDRESS, fAreaSize, B_CONTIGUOUS,
|
B_ANY_ADDRESS, fAreaSize, B_NO_LOCK,
|
||||||
B_READ_AREA | B_WRITE_AREA);
|
B_READ_AREA | B_WRITE_AREA);
|
||||||
|
|
||||||
if (fArea < 0) {
|
if (fArea < 0) {
|
||||||
TRACE(ERR, "Error of creating %#x - "
|
TRACE(ERR, "Error of creating %#x - "
|
||||||
"bytes size buffer area:%#010x\n", fAreaSize, fArea);
|
"bytes size buffer area:%#010x\n", fAreaSize, fArea);
|
||||||
@@ -195,16 +198,22 @@ Stream::_SetupBuffers()
|
|||||||
return fStatus;
|
return fStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The kernel is not allowed to touch userspace areas, so we clone our
|
||||||
|
// area into kernel space.
|
||||||
|
fKernelArea = clone_area("usb_audio cloned area", (void**)&fKernelBuffers,
|
||||||
|
B_ANY_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, fArea);
|
||||||
|
if (fKernelArea < 0) {
|
||||||
|
fStatus = fKernelArea;
|
||||||
|
return fStatus;
|
||||||
|
}
|
||||||
|
|
||||||
TRACE(INF, "Created area id:%d at addr:%#010x size:%#010lx\n",
|
TRACE(INF, "Created area id:%d at addr:%#010x size:%#010lx\n",
|
||||||
fArea, fDescriptors, fAreaSize);
|
fArea, fDescriptors, fAreaSize);
|
||||||
|
|
||||||
// descriptors count
|
fDescriptorsCount = fAreaSize / fPacketSize;
|
||||||
fDescriptorsCount = fAreaSize
|
|
||||||
/ (sizeof(usb_iso_packet_descriptor) + fPacketSize);
|
|
||||||
|
|
||||||
// we need same size sub-buffers. round it
|
// we need same size sub-buffers. round it
|
||||||
fDescriptorsCount /= kSamplesBufferCount;
|
fDescriptorsCount = ROUNDDOWN(fDescriptorsCount, kSamplesBufferCount);
|
||||||
fDescriptorsCount *= kSamplesBufferCount;
|
fDescriptors = new usb_iso_packet_descriptor[fDescriptorsCount];
|
||||||
TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount);
|
TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount);
|
||||||
|
|
||||||
// samples count
|
// samples count
|
||||||
@@ -295,16 +304,14 @@ Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
|
|||||||
size_t bufferSize = format->fNumChannels * format->fSubframeSize;
|
size_t bufferSize = format->fNumChannels * format->fSubframeSize;
|
||||||
bufferSize *= fSamplesCount / kSamplesBufferCount;
|
bufferSize *= fSamplesCount / kSamplesBufferCount;
|
||||||
|
|
||||||
uint8* buffers = (uint8*)(fDescriptors + fDescriptorsCount);
|
|
||||||
|
|
||||||
size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
|
size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
|
||||||
|
|
||||||
TRACE(DTA, "buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n",
|
TRACE(DTA, "buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n",
|
||||||
buffers + bufferSize * queuedBuffer, bufferSize,
|
fKernelBuffers + bufferSize * queuedBuffer, bufferSize,
|
||||||
fDescriptors + queuedBuffer * packetsCount, packetsCount);
|
fDescriptors + queuedBuffer * packetsCount, packetsCount);
|
||||||
|
|
||||||
status_t status = gUSBModule->queue_isochronous(fStreamEndpoint,
|
status_t status = gUSBModule->queue_isochronous(fStreamEndpoint,
|
||||||
buffers + bufferSize * queuedBuffer, bufferSize,
|
fKernelBuffers + bufferSize * queuedBuffer, bufferSize,
|
||||||
fDescriptors + queuedBuffer * packetsCount, packetsCount,
|
fDescriptors + queuedBuffer * packetsCount, packetsCount,
|
||||||
&fStartingFrame, start ? USB_ISO_ASAP : 0,
|
&fStartingFrame, start ? USB_ISO_ASAP : 0,
|
||||||
Stream::_TransferCallback, this);
|
Stream::_TransferCallback, this);
|
||||||
@@ -497,10 +504,9 @@ Stream::GetBuffers(multi_buffer_list* List)
|
|||||||
descs[channel].stride = stride;
|
descs[channel].stride = stride;
|
||||||
|
|
||||||
// init to buffers area begin
|
// init to buffers area begin
|
||||||
descs[channel].base
|
descs[channel].base = (char*)fBuffers;
|
||||||
= (char*)(fDescriptors + fDescriptorsCount);
|
|
||||||
// shift for whole buffer if required
|
// shift for whole buffer if required
|
||||||
size_t bufferSize = fPacketSize/*endpoint->fMaxPacketSize*/
|
size_t bufferSize = fPacketSize
|
||||||
* (fDescriptorsCount / kSamplesBufferCount);
|
* (fDescriptorsCount / kSamplesBufferCount);
|
||||||
descs[channel].base += buffer * bufferSize;
|
descs[channel].base += buffer * bufferSize;
|
||||||
// shift for channel if required
|
// shift for channel if required
|
||||||
@@ -549,4 +555,3 @@ Stream::ExchangeBuffer(multi_buffer_info* Info)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,10 +49,12 @@ protected:
|
|||||||
uint8 fTerminalID;
|
uint8 fTerminalID;
|
||||||
usb_pipe fStreamEndpoint;
|
usb_pipe fStreamEndpoint;
|
||||||
bool fIsRunning;
|
bool fIsRunning;
|
||||||
area_id fArea;
|
area_id fArea, fKernelArea;
|
||||||
size_t fAreaSize;
|
size_t fAreaSize;
|
||||||
usb_iso_packet_descriptor* fDescriptors;
|
usb_iso_packet_descriptor* fDescriptors;
|
||||||
size_t fDescriptorsCount;
|
size_t fDescriptorsCount;
|
||||||
|
uint8* fBuffers;
|
||||||
|
uint8* fKernelBuffers;
|
||||||
size_t fCurrentBuffer;
|
size_t fCurrentBuffer;
|
||||||
uint32 fStartingFrame;
|
uint32 fStartingFrame;
|
||||||
size_t fSamplesCount;
|
size_t fSamplesCount;
|
||||||
|
|||||||
Reference in New Issue
Block a user