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),
|
fStatus(B_ERROR),
|
||||||
fOpen(false),
|
fOpen(false),
|
||||||
fRemoved(false),
|
fRemoved(false),
|
||||||
// fInsideNotify(0),
|
|
||||||
fDevice(device),
|
fDevice(device),
|
||||||
fNonBlocking(false),
|
fNonBlocking(false),
|
||||||
fAudioControl(this),
|
fAudioControl(this),
|
||||||
|
@ -93,13 +92,6 @@ Device::Close()
|
||||||
for (int i = 0; i < fStreams.Count(); i++)
|
for (int i = 0; i < fStreams.Count(); i++)
|
||||||
fStreams[i]->Stop();
|
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;
|
fOpen = false;
|
||||||
|
|
||||||
return StopDevice();
|
return StopDevice();
|
||||||
|
@ -220,19 +212,8 @@ Device::Removed()
|
||||||
{
|
{
|
||||||
fRemoved = true;
|
fRemoved = true;
|
||||||
|
|
||||||
// the notify hook is different from the read and write hooks as it does
|
for (int i = 0; i < fStreams.Count(); i++)
|
||||||
// itself schedule traffic (while the other hooks only release a semaphore
|
fStreams[i]->OnRemove();
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -645,33 +626,3 @@ Device::StopDevice()
|
||||||
return result;
|
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;
|
status_t fStatus;
|
||||||
bool fOpen;
|
bool fOpen;
|
||||||
bool fRemoved;
|
bool fRemoved;
|
||||||
// int32 fInsideNotify; // TODO: move to Stream!
|
|
||||||
usb_device fDevice;
|
usb_device fDevice;
|
||||||
uint16 fUSBVersion;
|
uint16 fUSBVersion;
|
||||||
uint16 fVendorID;
|
uint16 fVendorID;
|
||||||
|
|
|
@ -29,7 +29,8 @@ Stream::Stream(Device* device, size_t interface, usb_interface_list* List)
|
||||||
fStartingFrame(0),
|
fStartingFrame(0),
|
||||||
fSamplesCount(0),
|
fSamplesCount(0),
|
||||||
fPacketSize(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
|
status_t
|
||||||
Stream::_SetupBuffers()
|
Stream::_SetupBuffers()
|
||||||
{
|
{
|
||||||
|
@ -252,6 +267,9 @@ status_t
|
||||||
Stream::Stop()
|
Stream::Stop()
|
||||||
{
|
{
|
||||||
if (fIsRunning) {
|
if (fIsRunning) {
|
||||||
|
// wait until possible notification handling finished...
|
||||||
|
while (atomic_add(&fInsideNotify, 0) != 0)
|
||||||
|
snooze(100);
|
||||||
gUSBModule->cancel_queued_transfers(fStreamEndpoint);
|
gUSBModule->cancel_queued_transfers(fStreamEndpoint);
|
||||||
fIsRunning = false;
|
fIsRunning = false;
|
||||||
}
|
}
|
||||||
|
@ -292,13 +310,14 @@ void
|
||||||
Stream::_TransferCallback(void* cookie, int32 status, void* data,
|
Stream::_TransferCallback(void* cookie, int32 status, void* data,
|
||||||
uint32 actualLength)
|
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",
|
TRACE_ALWAYS("Cancelled: c:%p st:%#010x, data:%#010x, len:%d\n",
|
||||||
cookie, status, data, actualLength);
|
cookie, status, data, actualLength);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stream* stream = (Stream*)cookie;
|
|
||||||
|
|
||||||
stream->fCurrentBuffer = (stream->fCurrentBuffer + 1) % kSamplesBufferCount;
|
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_ALWAYS("st:%#010x, len:%d -> %#010x\n", status, actualLength, result);
|
||||||
TRACE("st:%#010x, data:%#010x, len:%d\n", status, data, actualLength);
|
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 Start();
|
||||||
status_t Stop();
|
status_t Stop();
|
||||||
bool IsRunning() { return fIsRunning; }
|
bool IsRunning() { return fIsRunning; }
|
||||||
|
void OnRemove();
|
||||||
|
|
||||||
status_t GetBuffers(multi_buffer_list* List);
|
status_t GetBuffers(multi_buffer_list* List);
|
||||||
|
|
||||||
|
@ -57,6 +58,7 @@ protected:
|
||||||
size_t fSamplesCount;
|
size_t fSamplesCount;
|
||||||
size_t fPacketSize;
|
size_t fPacketSize;
|
||||||
int32 fProcessedBuffers;
|
int32 fProcessedBuffers;
|
||||||
|
int32 fInsideNotify;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _ChooseAlternate();
|
status_t _ChooseAlternate();
|
||||||
|
|
Loading…
Reference in New Issue