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 
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
repos
dde_linux/src/lib/usb/raw
os/include/usb_session

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

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