usb_hid: Let protocol handlers know of their closing.
On close a flag is set in the cookie of this user of a protocol handler and the device cancels its pending transfer. This wakes up any possible listeners. When the closed flag is set, an error code is returned from _ReadReport() which causes the retry loop to be left. Handlers listening on the same device which were not closed just retry the transfer. This ensures that closing a device will cause pending control requests to complete with a sensible error code.
This commit is contained in:
parent
6653e74873
commit
25f723de85
@ -247,6 +247,9 @@ status_t
|
||||
HIDDevice::Close(ProtocolHandler *handler)
|
||||
{
|
||||
atomic_add(&fOpenCount, -1);
|
||||
gUSBModule->cancel_queued_transfers(fInterruptPipe);
|
||||
// This will wake up any listeners. Whether they should close or retry
|
||||
// is handeled internally by the handlers.
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
@ -337,6 +337,9 @@ JoystickProtocolHandler::_Update()
|
||||
return B_DEV_NOT_READY;
|
||||
}
|
||||
|
||||
if (result == B_CANCELED)
|
||||
return B_CANCELED;
|
||||
|
||||
if (result != B_INTERRUPTED) {
|
||||
// interrupts happen when other reports come in on the same
|
||||
// input as ours
|
||||
|
@ -340,7 +340,7 @@ KeyboardProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
|
||||
|
||||
bigtime_t enterTime = system_time();
|
||||
while (RingBufferReadable() == 0) {
|
||||
status_t result = _ReadReport(fCurrentRepeatDelay);
|
||||
status_t result = _ReadReport(fCurrentRepeatDelay, cookie);
|
||||
if (result != B_OK && result != B_TIMED_OUT)
|
||||
return result;
|
||||
|
||||
@ -459,7 +459,7 @@ KeyboardProtocolHandler::_SetLEDs(uint8 *data)
|
||||
|
||||
|
||||
status_t
|
||||
KeyboardProtocolHandler::_ReadReport(bigtime_t timeout)
|
||||
KeyboardProtocolHandler::_ReadReport(bigtime_t timeout, uint32 *cookie)
|
||||
{
|
||||
status_t result = fInputReport.WaitForReport(timeout);
|
||||
if (result != B_OK) {
|
||||
@ -468,6 +468,9 @@ KeyboardProtocolHandler::_ReadReport(bigtime_t timeout)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if ((*cookie & PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED) != 0)
|
||||
return B_CANCELED;
|
||||
|
||||
if (result != B_TIMED_OUT && result != B_INTERRUPTED) {
|
||||
// we expect timeouts as we do repeat key handling this way,
|
||||
// interrupts happen when other reports come in on the same
|
||||
|
@ -39,7 +39,7 @@ public:
|
||||
private:
|
||||
void _WriteKey(uint32 key, bool down);
|
||||
status_t _SetLEDs(uint8 *data);
|
||||
status_t _ReadReport(bigtime_t timeout);
|
||||
status_t _ReadReport(bigtime_t timeout, uint32 *cookie);
|
||||
|
||||
private:
|
||||
mutex fLock;
|
||||
|
@ -132,7 +132,7 @@ MouseProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
|
||||
return B_BUFFER_OVERFLOW;
|
||||
|
||||
while (true) {
|
||||
status_t result = _ReadReport(buffer);
|
||||
status_t result = _ReadReport(buffer, cookie);
|
||||
if (result != B_INTERRUPTED)
|
||||
return result;
|
||||
}
|
||||
@ -161,7 +161,7 @@ MouseProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
|
||||
|
||||
|
||||
status_t
|
||||
MouseProtocolHandler::_ReadReport(void *buffer)
|
||||
MouseProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
|
||||
{
|
||||
status_t result = fReport.WaitForReport(B_INFINITE_TIMEOUT);
|
||||
if (result != B_OK) {
|
||||
@ -170,6 +170,9 @@ MouseProtocolHandler::_ReadReport(void *buffer)
|
||||
return B_DEV_NOT_READY;
|
||||
}
|
||||
|
||||
if ((*cookie & PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED) != 0)
|
||||
return B_CANCELED;
|
||||
|
||||
if (result != B_INTERRUPTED) {
|
||||
// interrupts happen when other reports come in on the same
|
||||
// input as ours
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
size_t length);
|
||||
|
||||
private:
|
||||
status_t _ReadReport(void *buffer);
|
||||
status_t _ReadReport(void *buffer, uint32 *cookie);
|
||||
|
||||
HIDReport & fReport;
|
||||
|
||||
|
@ -124,6 +124,9 @@ ProtocolHandler::Open(uint32 flags, uint32 *cookie)
|
||||
status_t
|
||||
ProtocolHandler::Close(uint32 *cookie)
|
||||
{
|
||||
*cookie |= PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED;
|
||||
// This lets the handlers know that this user is gone.
|
||||
|
||||
return fDevice->Close(this);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#define PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED 0x80000000
|
||||
|
||||
|
||||
class HIDDevice;
|
||||
class HIDReport;
|
||||
|
||||
|
@ -189,7 +189,7 @@ TabletProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
|
||||
return B_BUFFER_OVERFLOW;
|
||||
|
||||
while (true) {
|
||||
status_t result = _ReadReport(buffer);
|
||||
status_t result = _ReadReport(buffer, cookie);
|
||||
if (result != B_INTERRUPTED)
|
||||
return result;
|
||||
}
|
||||
@ -218,7 +218,7 @@ TabletProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer,
|
||||
|
||||
|
||||
status_t
|
||||
TabletProtocolHandler::_ReadReport(void *buffer)
|
||||
TabletProtocolHandler::_ReadReport(void *buffer, uint32 *cookie)
|
||||
{
|
||||
status_t result = fReport.WaitForReport(B_INFINITE_TIMEOUT);
|
||||
if (result != B_OK) {
|
||||
@ -227,6 +227,9 @@ TabletProtocolHandler::_ReadReport(void *buffer)
|
||||
return B_DEV_NOT_READY;
|
||||
}
|
||||
|
||||
if ((*cookie & PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED) != 0)
|
||||
return B_CANCELED;
|
||||
|
||||
if (result != B_INTERRUPTED) {
|
||||
// interrupts happen when other reports come in on the same
|
||||
// input as ours
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
size_t length);
|
||||
|
||||
private:
|
||||
status_t _ReadReport(void *buffer);
|
||||
status_t _ReadReport(void *buffer, uint32 *cookie);
|
||||
|
||||
HIDReport & fReport;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user