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:
parent
140c408d7b
commit
7b2bc8351a
@ -24,6 +24,7 @@ Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
|
||||
fStreamEndpoint(0),
|
||||
fIsRunning(false),
|
||||
fArea(-1),
|
||||
fKernelArea(-1),
|
||||
fAreaSize(0),
|
||||
fDescriptors(NULL),
|
||||
fDescriptorsCount(0),
|
||||
@ -40,6 +41,8 @@ Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
|
||||
Stream::~Stream()
|
||||
{
|
||||
delete_area(fArea);
|
||||
delete_area(fKernelArea);
|
||||
delete fDescriptors;
|
||||
}
|
||||
|
||||
|
||||
@ -173,21 +176,21 @@ Stream::_SetupBuffers()
|
||||
if (fArea != -1) {
|
||||
Stop();
|
||||
delete_area(fArea);
|
||||
delete_area(fKernelArea);
|
||||
delete fDescriptors;
|
||||
}
|
||||
|
||||
fAreaSize = (sizeof(usb_iso_packet_descriptor) + fPacketSize)
|
||||
* sampleSize * 1024 / fPacketSize;
|
||||
fAreaSize = sampleSize * kSamplesBufferSize;
|
||||
TRACE(INF, "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(INF, "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,
|
||||
fArea = create_area(fIsInput ? DRIVER_NAME "_record_area"
|
||||
: DRIVER_NAME "_playback_area", (void**)&fBuffers,
|
||||
B_ANY_ADDRESS, fAreaSize, B_NO_LOCK,
|
||||
B_READ_AREA | B_WRITE_AREA);
|
||||
|
||||
if (fArea < 0) {
|
||||
TRACE(ERR, "Error of creating %#x - "
|
||||
"bytes size buffer area:%#010x\n", fAreaSize, fArea);
|
||||
@ -195,16 +198,22 @@ Stream::_SetupBuffers()
|
||||
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",
|
||||
fArea, fDescriptors, fAreaSize);
|
||||
|
||||
// descriptors count
|
||||
fDescriptorsCount = fAreaSize
|
||||
/ (sizeof(usb_iso_packet_descriptor) + fPacketSize);
|
||||
|
||||
fDescriptorsCount = fAreaSize / fPacketSize;
|
||||
// we need same size sub-buffers. round it
|
||||
fDescriptorsCount /= kSamplesBufferCount;
|
||||
fDescriptorsCount *= kSamplesBufferCount;
|
||||
fDescriptorsCount = ROUNDDOWN(fDescriptorsCount, kSamplesBufferCount);
|
||||
fDescriptors = new usb_iso_packet_descriptor[fDescriptorsCount];
|
||||
TRACE(INF, "descriptorsCount:%d\n", fDescriptorsCount);
|
||||
|
||||
// samples count
|
||||
@ -295,16 +304,14 @@ Stream::_QueueNextTransfer(size_t queuedBuffer, bool start)
|
||||
size_t bufferSize = format->fNumChannels * format->fSubframeSize;
|
||||
bufferSize *= fSamplesCount / kSamplesBufferCount;
|
||||
|
||||
uint8* buffers = (uint8*)(fDescriptors + fDescriptorsCount);
|
||||
|
||||
size_t packetsCount = fDescriptorsCount / kSamplesBufferCount;
|
||||
|
||||
TRACE(DTA, "buffers:%#010x[%#x]\ndescrs:%#010x[%#x]\n",
|
||||
buffers + bufferSize * queuedBuffer, bufferSize,
|
||||
fKernelBuffers + bufferSize * queuedBuffer, bufferSize,
|
||||
fDescriptors + queuedBuffer * packetsCount, packetsCount);
|
||||
|
||||
status_t status = gUSBModule->queue_isochronous(fStreamEndpoint,
|
||||
buffers + bufferSize * queuedBuffer, bufferSize,
|
||||
fKernelBuffers + bufferSize * queuedBuffer, bufferSize,
|
||||
fDescriptors + queuedBuffer * packetsCount, packetsCount,
|
||||
&fStartingFrame, start ? USB_ISO_ASAP : 0,
|
||||
Stream::_TransferCallback, this);
|
||||
@ -497,10 +504,9 @@ Stream::GetBuffers(multi_buffer_list* List)
|
||||
descs[channel].stride = stride;
|
||||
|
||||
// init to buffers area begin
|
||||
descs[channel].base
|
||||
= (char*)(fDescriptors + fDescriptorsCount);
|
||||
descs[channel].base = (char*)fBuffers;
|
||||
// shift for whole buffer if required
|
||||
size_t bufferSize = fPacketSize/*endpoint->fMaxPacketSize*/
|
||||
size_t bufferSize = fPacketSize
|
||||
* (fDescriptorsCount / kSamplesBufferCount);
|
||||
descs[channel].base += buffer * bufferSize;
|
||||
// shift for channel if required
|
||||
@ -510,7 +516,7 @@ Stream::GetBuffers(multi_buffer_list* List)
|
||||
descs[channel].base, descs[channel].stride);
|
||||
}
|
||||
if (!IS_USER_ADDRESS(Buffers[buffer])
|
||||
|| user_memcpy(Buffers[buffer], descs, sizeof(descs)) < B_OK) {
|
||||
|| user_memcpy(Buffers[buffer], descs, sizeof(descs)) < B_OK) {
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
}
|
||||
@ -549,4 +555,3 @@ Stream::ExchangeBuffer(multi_buffer_info* Info)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -49,10 +49,12 @@ protected:
|
||||
uint8 fTerminalID;
|
||||
usb_pipe fStreamEndpoint;
|
||||
bool fIsRunning;
|
||||
area_id fArea;
|
||||
area_id fArea, fKernelArea;
|
||||
size_t fAreaSize;
|
||||
usb_iso_packet_descriptor* fDescriptors;
|
||||
usb_iso_packet_descriptor* fDescriptors;
|
||||
size_t fDescriptorsCount;
|
||||
uint8* fBuffers;
|
||||
uint8* fKernelBuffers;
|
||||
size_t fCurrentBuffer;
|
||||
uint32 fStartingFrame;
|
||||
size_t fSamplesCount;
|
||||
|
Loading…
x
Reference in New Issue
Block a user