USB audio: fInsideNotify guard added to Remote/Close callbacks
This commit is contained in:
parent
673ef2cbaf
commit
b42544e71d
@ -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);
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user