From 1001a04883dec6e147d641cfdb77c23820888ab2 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Mon, 27 Apr 2015 13:00:27 +0200 Subject: [PATCH] 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 --- repos/dde_linux/src/lib/usb/raw/raw.cc | 40 ++++++++++++++++------ repos/os/include/usb_session/usb_session.h | 1 + 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/repos/dde_linux/src/lib/usb/raw/raw.cc b/repos/dde_linux/src/lib/usb/raw/raw.cc index 92de72fc4a..c0384194d2 100644 --- a/repos/dde_linux/src/lib/usb/raw/raw.cc +++ b/repos/dde_linux/src/lib/usb/raw/raw.cc @@ -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); + } }; diff --git a/repos/os/include/usb_session/usb_session.h b/repos/os/include/usb_session/usb_session.h index 3ee1fd65b3..c197617c7f 100644 --- a/repos/os/include/usb_session/usb_session.h +++ b/repos/os/include/usb_session/usb_session.h @@ -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;