USB audio: fInsideNotify guard added to Remote/Close callbacks

This commit is contained in:
Siarzhuk Zharski 2013-06-27 16:14:02 +02:00
parent 673ef2cbaf
commit b42544e71d
4 changed files with 29 additions and 56 deletions

View File

@ -17,7 +17,6 @@ Device::Device(usb_device device)
fStatus(B_ERROR),
fOpen(false),
fRemoved(false),
// fInsideNotify(0),
fDevice(device),
fNonBlocking(false),
fAudioControl(this),
@ -93,13 +92,6 @@ Device::Close()
for (int i = 0; i < fStreams.Count(); i++)
fStreams[i]->Stop();
// 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);
fOpen = false;
return StopDevice();
@ -220,19 +212,8 @@ Device::Removed()
{
fRemoved = true;
// the notify hook is different from the read and write hooks as it does
// itself schedule traffic (while the other hooks only release a semaphore
// to notify another thread which in turn safly checks for the removed
// case) - so we must ensure that we are not inside the notify hook anymore
// before returning, as we would otherwise violate the promise not to use
// any of the pipes after returning from the removed hook
// TODO??????
// while (atomic_add(&fInsideNotify, 0) != 0)
// snooze(100);
// gUSBModule->cancel_queued_transfers(fControlEndpoint);
// gUSBModule->cancel_queued_transfers(fInStreamEndpoint);
// gUSBModule->cancel_queued_transfers(fOutStreamEndpoint);
for (int i = 0; i < fStreams.Count(); i++)
fStreams[i]->OnRemove();
}
@ -645,33 +626,3 @@ Device::StopDevice()
return result;
}
/*void
Device::_NotifyCallback(void* cookie, int32 status, void* data,
uint32 actualLength)
{
Device* device = (Device*)cookie;
atomic_add(&device->fInsideNotify, 1);
if (status == B_CANCELED || device->fRemoved) {
atomic_add(&device->fInsideNotify, -1);
return;
}
/ * 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);
}
* /
// parse data in overriden class
// device->OnNotify(actualLength);
// schedule next notification buffer
// gUSBModule->queue_interrupt(device->fNotifyEndpoint, device->fNotifyBuffer,
// device->fNotifyBufferLength, _NotifyCallback, device);
atomic_add(&device->fInsideNotify, -1);
}
*/

View File

@ -57,7 +57,6 @@ private:
status_t fStatus;
bool fOpen;
bool fRemoved;
// int32 fInsideNotify; // TODO: move to Stream!
usb_device fDevice;
uint16 fUSBVersion;
uint16 fVendorID;

View File

@ -29,7 +29,8 @@ Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
fStartingFrame(0),
fSamplesCount(0),
fPacketSize(0),
fProcessedBuffers(0)
fProcessedBuffers(0),
fInsideNotify(0)
{
}
@ -129,6 +130,20 @@ Stream::Init()
}
void
Stream::OnRemove()
{
// the transfer callback schedule traffic - so we must ensure that we are
// not inside the callback anymore before returning, as we would otherwise
// violate the promise not to use any of the pipes after returning from the
// removed callback
while (atomic_add(&fInsideNotify, 0) != 0)
snooze(100);
gUSBModule->cancel_queued_transfers(fStreamEndpoint);
}
status_t
Stream::_SetupBuffers()
{
@ -252,6 +267,9 @@ status_t
Stream::Stop()
{
if (fIsRunning) {
// wait until possible notification handling finished...
while (atomic_add(&fInsideNotify, 0) != 0)
snooze(100);
gUSBModule->cancel_queued_transfers(fStreamEndpoint);
fIsRunning = false;
}
@ -292,13 +310,14 @@ void
Stream::_TransferCallback(void* cookie, int32 status, void* data,
uint32 actualLength)
{
if (status == B_CANCELED) {
Stream* stream = (Stream*)cookie;
atomic_add(&stream->fInsideNotify, 1);
if (status == B_CANCELED || stream->fDevice->fRemoved) {
atomic_add(&stream->fInsideNotify, -1);
TRACE_ALWAYS("Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n",
cookie, status, data, actualLength);
return;
}
Stream* stream = (Stream*)cookie;
stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount;
@ -313,6 +332,8 @@ Stream::_TransferCallback(void* cookie, int32 status, void* data,
// TRACE_ALWAYS("st:%#010x, len:%d -> %#010x\n", status, actualLength, result);
TRACE("st:%#010x, data:%#010x, len:%d\n", status, data, actualLength);
atomic_add(&stream->fInsideNotify, -1);
}

View File

@ -26,6 +26,7 @@ public:
status_t Start();
status_t Stop();
bool IsRunning() { return fIsRunning; }
void OnRemove();
status_t GetBuffers(multi_buffer_list* List);
@ -57,6 +58,7 @@ protected:
size_t fSamplesCount;
size_t fPacketSize;
int32 fProcessedBuffers;
int32 fInsideNotify;
private:
status_t _ChooseAlternate();