usb_drv improvements

- send a 'state_change' signal on session creation if the device is
  already attached
- evaluate the status code of a finished asynchronous operation
- return the number of actually transferred bytes for control transfers,
  too

Fixes #1490
This commit is contained in:
Christian Prochaska 2015-04-27 13:00:27 +02:00 committed by Christian Helmuth
parent c1cb3a6642
commit 1001a04883
2 changed files with 31 additions and 10 deletions

View File

@ -95,6 +95,7 @@ class Usb::Worker
Signal_context_capability _sigh_ready;
Routine *_routine = nullptr;
unsigned _p_in_flight = 0;
bool _device_ready = false;
void _ack_packet(Packet_descriptor &p)
{
@ -142,6 +143,7 @@ class Usb::Worker
return;
}
p.control.actual_size = err;
p.succeded = true;
}
@ -159,8 +161,10 @@ class Usb::Worker
p.control.request, p.control.request_type,
p.control.value, p.control.index, buf, p.size(),
p.control.timeout);
if (err >= 0 || err== -EPIPE)
if (err >= 0 || err== -EPIPE) {
p.control.actual_size = err;
p.succeded = true;
}
kfree(buf);
}
@ -176,12 +180,14 @@ class Usb::Worker
void _async_finish(Packet_descriptor &p, urb *urb, bool read)
{
p.transfer.actual_size = urb->actual_length;
p.succeded = true;
if (urb->status == 0) {
p.transfer.actual_size = urb->actual_length;
p.succeded = true;
if (read)
Genode::memcpy(_sink->packet_content(p), urb->transfer_buffer,
urb->actual_length);
if (read)
Genode::memcpy(_sink->packet_content(p), urb->transfer_buffer,
urb->actual_length);
}
_ack_packet(p);
}
@ -386,6 +392,8 @@ class Usb::Worker
if (_sigh_ready.valid())
Signal_transmitter(_sigh_ready).submit(1);
_device_ready = true;
}
/**
@ -421,8 +429,10 @@ class Usb::Worker
void start()
{
if (!_routine)
if (!_routine) {
_routine = Routine::add(run, this, "worker");
Routine::schedule_all();
}
}
void stop()
@ -439,6 +449,8 @@ class Usb::Worker
_device = device;
_sigh_ready = sigh_ready;
}
bool device_ready() { return _device_ready; }
};
@ -488,9 +500,11 @@ class Usb::Session_component : public Session_rpc_object,
_ready_ack(ep, *this, &Session_component::_receive),
_worker(sink())
{
_device = Device::device(_vendor, _product);
if (_device)
Device *device = Device::device(_vendor, _product);
if (device) {
PDBG("Found device");
state_change(DEVICE_ADD, device);
}
/* register signal handlers */
_tx.sigh_packet_avail(_packet_avail);
@ -600,7 +614,13 @@ class Usb::Session_component : public Session_rpc_object,
return false;
}
void sigh_state_change(Signal_context_capability sigh) { _sigh_state_change = sigh; }
void sigh_state_change(Signal_context_capability sigh)
{
_sigh_state_change = sigh;
if (_worker.device_ready())
Signal_transmitter(_sigh_state_change).submit(1);
}
};

View File

@ -53,6 +53,7 @@ struct Usb::Packet_descriptor : Genode::Packet_descriptor
uint8_t request_type;
uint16_t value;
uint16_t index;
int actual_size; /* returned */
int timeout;
} control;