Mir

Merge lp:~andreas-pokorny/mir/libinput-input-device-provider into lp:mir

Proposed by Andreas Pokorny
Status: Work in progress
Proposed branch: lp:~andreas-pokorny/mir/libinput-input-device-provider
Merge into: lp:mir
Diff against target: 1806 lines (+1628/-7)
27 files modified
src/include/server/mir/input/input_device.h (+40/-0)
src/include/server/mir/input/input_device_factory.h (+50/-0)
src/server/input/CMakeLists.txt (+3/-0)
src/server/input/android/CMakeLists.txt (+1/-0)
src/server/input/android/input_device_provider.cpp (+47/-0)
src/server/input/android/input_device_provider.h (+42/-0)
src/server/input/evdev_device_info.cpp (+209/-0)
src/server/input/evdev_device_info.h (+54/-0)
src/server/input/evdev_input_device_factory.cpp (+52/-0)
src/server/input/evdev_input_device_factory.h (+52/-0)
src/server/input/input_device_info.h (+66/-0)
src/server/input/input_device_provider.h (+59/-0)
src/server/input/libinput/CMakeLists.txt (+10/-0)
src/server/input/libinput/input_device_provider.cpp (+61/-0)
src/server/input/libinput/input_device_provider.h (+42/-0)
tests/include/mir_test_doubles/stub_input_device_info.h (+56/-0)
tests/mir_test_framework/udev_recordings/joystick-detection.ioctl (+25/-0)
tests/mir_test_framework/udev_recordings/joystick-detection.umockdev (+351/-0)
tests/mir_test_framework/udev_recordings/mt-screen-detection.ioctl (+28/-0)
tests/mir_test_framework/udev_recordings/mt-screen-detection.umockdev (+44/-0)
tests/mir_test_framework/udev_recordings/synaptics-touchpad.ioctl (+0/-7)
tests/unit-tests/input/CMakeLists.txt (+3/-0)
tests/unit-tests/input/android/CMakeLists.txt (+1/-0)
tests/unit-tests/input/android/test_android_input_device_provider.cpp (+71/-0)
tests/unit-tests/input/test_evdev_device_info.cpp (+83/-0)
tests/unit-tests/input/test_evdev_input_device_factory.cpp (+103/-0)
tests/unit-tests/input/test_libinput_device_provider.cpp (+75/-0)
To merge this branch: bzr merge lp:~andreas-pokorny/mir/libinput-input-device-provider
Reviewer Review Type Date Requested Status
Alan Griffiths Abstain
PS Jenkins bot (community) continuous-integration Approve
Chris Halse Rogers Needs Fixing
Robert Carr (community) Needs Fixing
Alexandros Frantzis (community) Needs Fixing
Review via email: mp+241951@code.launchpad.net

Commit message

Adds InputDeviceFactory and InputDeviceProvider for interfacing with the input stacks and probing support for specific devices.

Description of the change

This change adds an InputDeviceProvider interface and two implementations for android input stack and libinput. The interface is used for querying whether the specific stack provides support for certain input devices. This is needed since libinput does not yet handle touch screens well, and is limited to two axis.

This change adds borrows some of the device detection logic found in the
android input stack and libinput to identify input devices as needed.

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

The tests look more like integration tests than unit tests.

(Which reminds me that we don't really have the "acceptance test" story sorted for input devices - a way to mock input from a plugin instead of hooking into internals would be great.)

~~~~

1650 + * Authored by: Christopher Halse Rogers <email address hidden>

Is that the correct attribution?

~~~~

29 === added file 'src/include/server/mir/input/input_device_detection.h'

This file is only useful in input: does it need to be in a shared directory?

~~~~

65 +class InputDeviceDetection
66 +{
67 +public:
68 + explicit InputDeviceDetection(const char* devpath);
69 + bool has_touchpad() const;
70 + bool has_multi_touch_screen() const;
71 + bool has_joystick() const;
72 + int num_joystick_axes() const;
73 +private:
74 + Fd input_device;
75 + std::unique_ptr<libevdev, void(*)(libevdev *)> evdev_ptr;
76 +};

Given the above, this might be an implementation detail. But, if not, it would useful to split the interface from the implementation to facilitate unit testing any dependent code.

~~~~

515 +#include <mir/input/input_device_factory.h>

Wrong include type

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> The tests look more like integration tests than unit tests.
>
> (Which reminds me that we don't really have the "acceptance test" story sorted
> for input devices - a way to mock input from a plugin instead of hooking into
> internals would be great.)

Hmm I thought those as unit tests since I only test the implementation of one thing. Only the means necessary are bigger than usual.

> ~~~~
>
> 1650 + * Authored by: Christopher Halse Rogers
> <email address hidden>
>
> Is that the correct attribution?

Yes this branch started with the changes in .. lp:~raof/mir/eventhub-must-die

> ~~~~
>
> 29 === added file 'src/include/server/mir/input/input_device_detection.h'
>
> This file is only useful in input: does it need to be in a shared directory?

I moved it there to avoid "../input_device_detection.h" within android/ and libinput/ folders.

> ~~~~
>
> 65 +class InputDeviceDetection
> 66 +{
> 67 +public:
> 68 + explicit InputDeviceDetection(const char* devpath);
> 69 + bool has_touchpad() const;
> 70 + bool has_multi_touch_screen() const;
> 71 + bool has_joystick() const;
> 72 + int num_joystick_axes() const;
> 73 +private:
> 74 + Fd input_device;
> 75 + std::unique_ptr<libevdev, void(*)(libevdev *)> evdev_ptr;
> 76 +};
>
> Given the above, this might be an implementation detail. But, if not, it would
> useful to split the interface from the implementation to facilitate unit
> testing any dependent code.

Yes the information that I have to query from the evdevs is an implementation detail related to the different input stacks.

>
> ~~~~
>
> 515 +#include <mir/input/input_device_factory.h>
>
> Wrong include type

ack

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> > 29 === added file
> 'src/include/server/mir/input/input_device_detection.h'
> >
> > This file is only useful in input: does it need to be in a shared directory?
>
> I moved it there to avoid "../input_device_detection.h" within android/ and
> libinput/ folders.
..
> Yes the information that I have to query from the evdevs is an implementation
> detail related to the different input stacks.

I would prefer "../input_device_detection.h" in android/ and libinput/ folders (there are precedents). But won't block on it.

review: Abstain
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

181 + virtual ~InputDeviceProvider() noexcept {}

Isn't "= default" enough here?

313 +mia::InputDeviceProvider::~InputDeviceProvider()
314 +{
315 +}

Could also be mia::InputDeviceProvider::~InputDeviceProvider() = default;

406 +int get_num_abs_axes(libevdev * evdev, std::initializer_list<int> axes_list)

"libevdev*"

354 + InputDeviceProvider();
357 + ~InputDeviceProvider();

Not needed.

526 + {

Alignment.

657 + InputDeviceProvider();
660 + ~InputDeviceProvider();

Not needed.

599 + if (detector.has_touchpad())
600 + return best;
601 + else if (detector.has_joystick() &&
602 + detector.num_joystick_axes() > joystick_axes_exposed_by_libinput)
603 + return unsupported;
604 + else if (detector.has_multi_touch_screen())
605 + return unsupported;
606 + else
607 + return supported;

The code would be more readable with braces (because of the first "else if").

448 + bool has_keys = libevdev_has_event_type(evdev_ptr.get(), EV_KEY);
... and below

Could be const.

512 +mi::InputDeviceFactory::InputDeviceFactory(std::initializer_list<std::shared_ptr<mi::InputDeviceProvider>> providers)

Will the passed providers be decided at runtime? If so, using an initializer_list may cause issues.

review: Needs Fixing
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

@alf:ack

setting it to wip - there is something odd going on with umock on armhf.. putting it back to wip

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> 512 +mi::InputDeviceFactory::InputDeviceFactory(std::initializer_list<std:
> :shared_ptr<mi::InputDeviceProvider>> providers)
>
> Will the passed providers be decided at runtime? If so, using an
> initializer_list may cause issues.

not yet planed.. I thought about moving InputDeviceFactory as a whole into the input platform later

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

It looks like this is still work in progress? I can't find anywhere the new InputDeviceFactory is used (and it seems mi::InputDevice is still only a forward declared type).

Are you looking for advance review before preceding further or trying to land this as an intermediate step? From your perspective what is the next step?

My guess would be something like:
1. Modify EventHub to use InputDevice factory
2. Expand InputDevice interface to pull event reading in to interface
3. Move event hub code in to android InputDeviceImpl,add libinput device impl.

Is this where you are heading? Lets sync up and then ill review the rest! Things are looking sound so far.

review: Needs Information
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> Are you looking for advance review before preceding further or trying to land
> this as an intermediate step? From your perspective what is the next step?
>
> My guess would be something like:
> 1. Modify EventHub to use InputDevice factory
> 2. Expand InputDevice interface to pull event reading in to interface
> 3. Move event hub code in to android InputDeviceImpl,add libinput device impl.
>
> Is this where you are heading? Lets sync up and then ill review the rest!
> Things are looking sound so far.

This is an intermediate step that can land, since it is not wired to the rest of the system. Yes pretty much what you wrote above but maybe a few more smaller steps, and a final step to activate the new code path.

.. create something that uses udev monitor to listen to new devices ..
.. make it use InputDeviceFactory to create InputDevice
.. make it maintain those InputDevices .. maybe provide some observer functionality
.. add event processing functionality to InputDevice
.. connect event processing with input reader
.. flip the switch and replace EventHub with the new InputDeviceHub thing.

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> Are you looking for advance review before preceding further or trying to land
> this as an intermediate step? From your perspective what is the next step?
>
> My guess would be something like:
> 1. Modify EventHub to use InputDevice factory
> 2. Expand InputDevice interface to pull event reading in to interface
> 3. Move event hub code in to android InputDeviceImpl,add libinput device impl.
>
> Is this where you are heading? Lets sync up and then ill review the rest!
> Things are looking sound so far.

This is an intermediate step that can land, since it is not wired to the rest of the system. Yes pretty much what you wrote above but maybe a few more smaller steps, and a final step to activate the new code path.

.. create something that uses udev monitor to listen to new devices ..
.. make it use InputDeviceFactory to create InputDevice
.. make it maintain those InputDevices .. maybe provide some observer functionality
.. add event processing functionality to InputDevice
.. connect event processing with input reader
.. flip the switch and replace EventHub with the new InputDeviceHub thing.

Revision history for this message
Robert Carr (robertcarr) wrote :

I see, somehow I was expecting that we would keep the EventHub as an intermediate stage and instead port it to use our new InputDevice impl (which would be refactored to include the event reading logic, enabling lib input to perform its magic). Replacing EventHub also sounds possible and desirable in the long run...

Revision history for this message
Robert Carr (robertcarr) wrote :

I see the implementation for InputDeviceDetection but I can't find any declaration?

What is the InputDeviceDetection class? Given that it opens a device (and owns an FD to such), and is used to query device properties...maybe it's just "InputDevice"? InputDeviceDetection doesnt make sense to me though.

review: Needs Fixing
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

good catch, forgot to remove it..

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> I see, somehow I was expecting that we would keep the EventHub as an
> intermediate stage and instead port it to use our new InputDevice impl (which
> would be refactored to include the event reading logic, enabling lib input to
> perform its magic). Replacing EventHub also sounds possible and desirable in
> the long run...

Yes also reasonable.. Maybe even a better way.

Another thing that I try achieve by driving those changes is to shape a platform interface for input. So that everything that depends on accessing devices and handling those is provided by the platform. At the moment it looks like that the new EventHub could live outside that platform. Currently I think of nested and evdev as two different platforms... As it stands right now the input platform would provide something like:
  create_input_device_info(char const*) -> unique_ptr<InputDeviceInfo>
  create_input_device_monitor() -> unique_ptr<DeviceMonior>
  create_input_device_factory() -> unique_ptr<InputDeviceFactory>

I hope this plays well along or can be reasonably combined with the client side parts...

Still makes sense?

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

38 +class InputDeviceFactory
39 +{
40 +public:
41 + InputDeviceFactory(std::initializer_list<std::shared_ptr<InputDeviceProvider>> providers);
42 +
43 + std::shared_ptr<InputDevice> create_device(InputDeviceInfo const& info);
44 +
45 +private:
46 + std::vector<std::shared_ptr<InputDeviceProvider>> providers;
47 +};

This seems like a poorly named abstraction. Also, as it lacks an interface class it will be difficult to unit test any code that uses it. Fortunately(?) there is only test code that uses it.

~~~~

561 + return std::shared_ptr<mi::InputDevice>();

It isn't clear how create_device() is intended to be used, but in general a NullObject or an exception should be preferred to a null pointer.

~~~~

1548 +TEST(InputDeviceFactoryTest, ProbesAllProviders)

"Test" adds nothing, ProbesAllProviders is not project style.

e.g. "InputDeviceFactory.probes_all_providers_when_creating_a_device"

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

On an overall level I'm not sure that InputDeviceInfo/InputDeviceIdentifier is a good abstraction; it seems like a thin wrapper around what you can get from evdev. This doesn't seem friendly to platforms that aren't directly tied to the hardware, like nested or (hopefully!) X11.

Hm. Having said that, I guess this MP is actually the start of the implementation for the hardware/evdev platform, and won't be loaded in nested situations. In that case I'd probably use Udev::Device as the device identifier to pass to the InputDeviceProvider/InputDeviceFactory; that's what you'll be getting out of the monitor.

The fun thing here is that we've really got two levels of ‘platform’ - there's the connect-to-the-rest-of-Mir input platform layer, but on the hardware/evdev platform there's *also* a platformish interface. We'll have AndroidInput/libinput as two consumers of the hardware/evdev interface, and we may well want a dynamic-loading interface so third parties can ship things like Wacom drivers or whatever.

Code-related comments below:

Lots of std::runtime_error that should be std::system_error.

655 + enum DeviceClasses
656 + {
657 + cursor = 0x00000001,
658 + keyboard = 0x00000002,
659 + touchpad = 0x00000004,
660 + touchscreen = 0x00000008,
661 + gamepad = 0x00000010,
662 + joystick = 0x00000020,
663 + };

Hm. I usually find the idiom
cursor = 1<<0,
keyboard = 1<<1,
touchpad = 1<<2,

as more obvious for bitfields. Do we have any other bitfields in our code ATM? What's our current style?

726 + virtual Priority get_support(InputDeviceInfo const& info) const = 0;

get_support seems like it could be better named. Maybe probe() is better?

review: Needs Fixing
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

> On an overall level I'm not sure that InputDeviceInfo/InputDeviceIdentifier is
> a good abstraction; it seems like a thin wrapper around what you can get from
> evdev. This doesn't seem friendly to platforms that aren't directly tied to
> the hardware, like nested or (hopefully!) X11.
>
> Hm. Having said that, I guess this MP is actually the start of the
> implementation for the hardware/evdev platform, and won't be loaded in nested
> situations. In that case I'd probably use Udev::Device as the device
> identifier to pass to the InputDeviceProvider/InputDeviceFactory; that's what
> you'll be getting out of the monitor.

Hmm that was the idea, but I assume(d) that I can keep a reworked Input Device Hub out of the platform. So have a platform defined DeviceMonitor, and when a new device is 'found' let it use something like InputDeviceIdentifier/InputDeviceInfo as a creation parameter to the InputDeviceFactory. And all that in the non hardware scenarios too.

In the nested mir case we would probably expose the same information and have a different interpretation for the term path?

> The fun thing here is that we've really got two levels of ‘platform’ - there's
> the connect-to-the-rest-of-Mir input platform layer, but on the hardware/evdev
> platform there's *also* a platformish interface. We'll have
> AndroidInput/libinput as two consumers of the hardware/evdev interface, and we
> may well want a dynamic-loading interface so third parties can ship things
> like Wacom drivers or whatever.

I think support for that is in the making for libinput. But changing the current EdevInputDeviceFactory to have loadable providers will work too..

> Code-related comments below:
>
> Lots of std::runtime_error that should be std::system_error.
>
> 655 + enum DeviceClasses
> 656 + {
> 657 + cursor = 0x00000001,
> 658 + keyboard = 0x00000002,
> 659 + touchpad = 0x00000004,
> 660 + touchscreen = 0x00000008,
> 661 + gamepad = 0x00000010,
> 662 + joystick = 0x00000020,
> 663 + };
>
> Hm. I usually find the idiom
> cursor = 1<<0,
> keyboard = 1<<1,
> touchpad = 1<<2,
> …
> as more obvious for bitfields. Do we have any other bitfields in our code ATM?
> What's our current style?

I dont know, but 1<<n is nicer to read..

> 726 + virtual Priority get_support(InputDeviceInfo const& info) const =
> 0;
>
> get_support seems like it could be better named. Maybe probe() is better?

When I switched from mir::udev::Device to InputDeviceInfo I also renamed prope_device to get_support, since probing already took place before that..

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
2059. By Andreas Pokorny

runtime_error -> system_error

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :
Download full text (3.6 KiB)

On Mon, Nov 24, 2014 at 7:01 PM, Andreas Pokorny
<email address hidden> wrote:
>> On an overall level I'm not sure that
>> InputDeviceInfo/InputDeviceIdentifier is
>> a good abstraction; it seems like a thin wrapper around what you
>> can get from
>> evdev. This doesn't seem friendly to platforms that aren't directly
>> tied to
>> the hardware, like nested or (hopefully!) X11.
>>
>> Hm. Having said that, I guess this MP is actually the start of the
>> implementation for the hardware/evdev platform, and won't be loaded
>> in nested
>> situations. In that case I'd probably use Udev::Device as the device
>> identifier to pass to the InputDeviceProvider/InputDeviceFactory;
>> that's what
>> you'll be getting out of the monitor.
>
> Hmm that was the idea, but I assume(d) that I can keep a reworked
> Input Device Hub out of the platform. So have a platform defined
> DeviceMonitor, and when a new device is 'found' let it use something
> like InputDeviceIdentifier/InputDeviceInfo as a creation parameter to
> the InputDeviceFactory. And all that in the non hardware scenarios
> too.
>
> In the nested mir case we would probably expose the same information
> and have a different interpretation for the term path?

Right, something like that, yes. But why let the
InputDeviceIdentifier/InputDeviceInfo leak out of the platform? I'd
expect DeviceMonitor to have a notification fd and a
process_events(TheOutOfPlatformInputHub) method that would add/remove
the InputDevices that changed to the hub.

InputDeviceIdentifier is strongly tied to evdev. Of those fields, only
the name and the device node are exposed to X11 clients. Those fields
are pretty much the greatest-common-divisor of input devices; more and
we're close to implicitly saying that all input devices are evdev
devices.

>
>> The fun thing here is that we've really got two levels of
>> ‘platform’ - there's
>> the connect-to-the-rest-of-Mir input platform layer, but on the
>> hardware/evdev
>> platform there's *also* a platformish interface. We'll have
>> AndroidInput/libinput as two consumers of the hardware/evdev
>> interface, and we
>> may well want a dynamic-loading interface so third parties can ship
>> things
>> like Wacom drivers or whatever.
>
> I think support for that is in the making for libinput. But changing
> the current EdevInputDeviceFactory to have loadable providers will
> work too..
>
>> Code-related comments below:
>>
>> Lots of std::runtime_error that should be std::system_error.
>>
>> 655 + enum DeviceClasses
>> 656 + {
>> 657 + cursor = 0x00000001,
>> 658 + keyboard = 0x00000002,
>> 659 + touchpad = 0x00000004,
>> 660 + touchscreen = 0x00000008,
>> 661 + gamepad = 0x00000010,
>> 662 + joystick = 0x00000020,
>> 663 + };
>>
>> Hm. I usually find the idiom
>> cursor = 1<<0,
>> keyboard = 1<<1,
>> touchpad = 1<<2,
>> …
>> as more obvious for bitfields. Do we have any other bitfields in
>> our code ATM?
>> What's our current style?
>
> I dont know, but 1<<n is nicer to read..
>
>> 726 + virtua...

Read more...

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I don't really have my head around how this will be used yet, but meanwhile here are a few nits:

20 + * Authored by: Christopher Halse Rogers <email address hidden>
21 + * Andreas Pokorny <email address hidden>
..
32 +class InputDevice
33 +{
34 +public:
35 + InputDevice() = default;
36 + virtual ~InputDevice() = default;
37 +};

I suppose this will get filled out later, but is it intended as an interface or as a value class? It can be instantiated and copied (which suggests value-like behavior) but has a virtual destructor (which suggests interface like usage).

PS It took two of you to come up with this?!

~~~~

735 + virtual Priority get_support(InputDeviceInfo const& info) const = 0;

I'm not the first to mention this, but the name is not clear. How about "assess_support()"?

~~~~

725 + enum Priority
726 + {
727 + unsupported = 0,
728 + supported = 100,
729 + best = 255,
730 + };

We try to use enum classes where possible. Using a non-class enum inside a type with a long name (like InputDeviceProvider) is not easy on user code that needs to refer to the values.

review: Abstain
Revision history for this message
Robert Carr (robertcarr) wrote :

*throws hat in naming convention*

s/get_support/support_for/

SupportLevel support_for(device_identifier) reads nice I think

You use the support level to decide priority.

Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

ok.. thanks for the suggestions.. this needs another round of rework.

Unmerged revisions

2059. By Andreas Pokorny

runtime_error -> system_error

2058. By Andreas Pokorny

smaller review findings fixed

2057. By Andreas Pokorny

review findings

2056. By Andreas Pokorny

rename-and-file-move-o-rama

2055. By Andreas Pokorny

remove old file

2054. By Andreas Pokorny

Adds the last recording to the evdev test

2053. By Andreas Pokorny

removing evdev dependency again

2052. By Andreas Pokorny

reworked input device handling again

separated input device interpretation into a separate class InputDeviceInfo with
logic borrowed from anroid stack. This makes evdev interactions mostly device
independent again.

synaptics-touchpad.ioctl is edited with this change. Several of the ioctl results
where duplicate and contain inconsistent information.

2051. By Andreas Pokorny

merged lp:mir

2050. By Andreas Pokorny

review findings fixed

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'src/include/server/mir/input/input_device.h'
2--- src/include/server/mir/input/input_device.h 1970-01-01 00:00:00 +0000
3+++ src/include/server/mir/input/input_device.h 2014-11-24 16:32:54 +0000
4@@ -0,0 +1,40 @@
5+/*
6+ * Copyright © 2013-2014 Canonical Ltd.
7+ *
8+ * This program is free software: you can redistribute it and/or modify it
9+ * under the terms of the GNU General Public License version 3,
10+ * as published by the Free Software Foundation.
11+ *
12+ * This program is distributed in the hope that it will be useful,
13+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+ * GNU General Public License for more details.
16+ *
17+ * You should have received a copy of the GNU General Public License
18+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
19+ *
20+ * Authored by: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
21+ * Andreas Pokorny <andreas.pokorny@canonical.com>
22+ */
23+
24+#ifndef MIR_INPUT_INPUT_DEVICE_H_
25+#define MIR_INPUT_INPUT_DEVICE_H_
26+
27+namespace mir
28+{
29+namespace input
30+{
31+
32+class InputDevice
33+{
34+public:
35+ InputDevice() = default;
36+ virtual ~InputDevice() = default;
37+};
38+
39+}
40+} // namespace mir
41+
42+#endif // MIR_INPUT_INPUT_DEVICE_H_
43+
44+
45
46=== added file 'src/include/server/mir/input/input_device_factory.h'
47--- src/include/server/mir/input/input_device_factory.h 1970-01-01 00:00:00 +0000
48+++ src/include/server/mir/input/input_device_factory.h 2014-11-24 16:32:54 +0000
49@@ -0,0 +1,50 @@
50+/*
51+ * Copyright © 2013-2014 Canonical Ltd.
52+ *
53+ * This program is free software: you can redistribute it and/or modify it
54+ * under the terms of the GNU General Public License version 3,
55+ * as published by the Free Software Foundation.
56+ *
57+ * This program is distributed in the hope that it will be useful,
58+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
59+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60+ * GNU General Public License for more details.
61+ *
62+ * You should have received a copy of the GNU General Public License
63+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
64+ *
65+ * Authored by: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
66+ * Andreas Pokorny <andreas.pokorny@canonical.com>
67+ */
68+
69+#ifndef MIR_INPUT_INPUT_DEVICE_FACTORY_H_
70+#define MIR_INPUT_INPUT_DEVICE_FACTORY_H_
71+
72+#include <memory>
73+
74+namespace mir
75+{
76+namespace input
77+{
78+class InputDeviceInfo;
79+class InputDevice;
80+
81+class InputDeviceFactory
82+{
83+public:
84+ InputDeviceFactory() = default;
85+ virtual ~InputDeviceFactory() = default;
86+
87+ virtual std::unique_ptr<InputDevice> create_device(InputDeviceInfo const& info) = 0;
88+
89+protected:
90+ InputDeviceFactory(InputDeviceFactory const&) = delete;
91+ InputDeviceFactory& operator=(InputDeviceFactory const&) = delete;
92+};
93+
94+}
95+} // namespace mir
96+
97+#endif // MIR_INPUT_INPUT_DEVICE_FACTORY_H_
98+
99+
100
101=== modified file 'src/server/input/CMakeLists.txt'
102--- src/server/input/CMakeLists.txt 2014-10-29 06:21:10 +0000
103+++ src/server/input/CMakeLists.txt 2014-11-24 16:32:54 +0000
104@@ -16,9 +16,12 @@
105 xcursor_loader.cpp
106 builtin_cursor_images.cpp
107 touchspot_controller.cpp
108+ evdev_device_info.cpp
109+ evdev_input_device_factory.cpp
110 )
111
112 add_subdirectory(android)
113+add_subdirectory(libinput)
114
115 add_library(
116 mirinput OBJECT
117
118=== modified file 'src/server/input/android/CMakeLists.txt'
119--- src/server/input/android/CMakeLists.txt 2014-10-29 06:21:10 +0000
120+++ src/server/input/android/CMakeLists.txt 2014-11-24 16:32:54 +0000
121@@ -16,6 +16,7 @@
122 ${CMAKE_CURRENT_SOURCE_DIR}/input_channel_factory.cpp
123 ${CMAKE_CURRENT_SOURCE_DIR}/input_translator.cpp
124 ${CMAKE_CURRENT_SOURCE_DIR}/input_sender.cpp
125+ ${CMAKE_CURRENT_SOURCE_DIR}/input_device_provider.cpp
126 )
127
128 set(
129
130=== added file 'src/server/input/android/input_device_provider.cpp'
131--- src/server/input/android/input_device_provider.cpp 1970-01-01 00:00:00 +0000
132+++ src/server/input/android/input_device_provider.cpp 2014-11-24 16:32:54 +0000
133@@ -0,0 +1,47 @@
134+/*
135+ * Copyright © 2014 Canonical Ltd.
136+ *
137+ * This program is free software: you can redistribute it and/or modify it
138+ * under the terms of the GNU General Public License version 3,
139+ * as published by the Free Software Foundation.
140+ *
141+ * This program is distributed in the hope that it will be useful,
142+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
143+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144+ * GNU General Public License for more details.
145+ *
146+ * You should have received a copy of the GNU General Public License
147+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
148+ *
149+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
150+ */
151+
152+#include "input_device_provider.h"
153+
154+#include "../input_device_info.h"
155+
156+#include "mir/input/input_device.h"
157+
158+namespace mi = mir::input;
159+namespace mia = mi::android;
160+
161+mi::InputDeviceProvider::Priority mia::InputDeviceProvider::get_support(mi::InputDeviceInfo const& device) const
162+{
163+ auto device_classes = device.device_classes();
164+ if (device_classes & InputDeviceInfo::touchscreen)
165+ return best;
166+
167+ if (device_classes & InputDeviceInfo::touchpad)
168+ return unsupported;
169+
170+ if (device_classes == 0)
171+ return unsupported;
172+
173+ return supported;
174+}
175+
176+std::unique_ptr<mi::InputDevice> mia::InputDeviceProvider::create_device(mi::InputDeviceInfo const& /*device*/) const
177+{
178+ return std::unique_ptr<mi::InputDevice>();
179+}
180+
181
182=== added file 'src/server/input/android/input_device_provider.h'
183--- src/server/input/android/input_device_provider.h 1970-01-01 00:00:00 +0000
184+++ src/server/input/android/input_device_provider.h 2014-11-24 16:32:54 +0000
185@@ -0,0 +1,42 @@
186+/*
187+ * Copyright © 2014 Canonical Ltd.
188+ *
189+ * This program is free software: you can redistribute it and/or modify it
190+ * under the terms of the GNU General Public License version 3,
191+ * as published by the Free Software Foundation.
192+ *
193+ * This program is distributed in the hope that it will be useful,
194+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
195+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
196+ * GNU General Public License for more details.
197+ *
198+ * You should have received a copy of the GNU General Public License
199+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
200+ *
201+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
202+ */
203+
204+#ifndef MIR_INPUT_ANDROID_INPUT_DEVICE_PROVIDER_H_
205+#define MIR_INPUT_ANDROID_INPUT_DEVICE_PROVIDER_H_
206+
207+#include "../input_device_provider.h"
208+
209+namespace mir
210+{
211+namespace input
212+{
213+namespace android
214+{
215+
216+class InputDeviceProvider : public input::InputDeviceProvider
217+{
218+public:
219+ Priority get_support(input::InputDeviceInfo const& device) const override;
220+ std::unique_ptr<InputDevice> create_device(input::InputDeviceInfo const& device) const override;
221+};
222+
223+}
224+}
225+}
226+
227+#endif // MIR_INPUT_ANDROID_INPUT_DEVICE_PROVIDER_H_
228
229=== added file 'src/server/input/evdev_device_info.cpp'
230--- src/server/input/evdev_device_info.cpp 1970-01-01 00:00:00 +0000
231+++ src/server/input/evdev_device_info.cpp 2014-11-24 16:32:54 +0000
232@@ -0,0 +1,209 @@
233+/*
234+ * Copyright © 2014 Canonical Ltd.
235+ *
236+ * This program is free software: you can redistribute it and/or modify it
237+ * under the terms of the GNU General Public License version 3,
238+ * as published by the Free Software Foundation.
239+ *
240+ * This program is distributed in the hope that it will be useful,
241+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
242+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
243+ * GNU General Public License for more details.
244+ *
245+ * You should have received a copy of the GNU General Public License
246+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
247+ *
248+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
249+ */
250+
251+#include "evdev_device_info.h"
252+
253+#include "mir/fd.h"
254+
255+#include <boost/exception/errinfo_errno.hpp>
256+#include <boost/exception/errinfo_file_name.hpp>
257+#include <boost/throw_exception.hpp>
258+
259+#include <sys/types.h>
260+#include <sys/stat.h>
261+#include <fcntl.h>
262+
263+#include <cstring>
264+#include <system_error>
265+
266+namespace mi = mir::input;
267+
268+
269+namespace
270+{
271+constexpr size_t index_of_bit(size_t bit)
272+{
273+ return (bit + 7) / 8;
274+}
275+inline bool get_bit(uint8_t const* array, size_t bit)
276+{
277+ return array[bit/8] & (1<<(bit%8));
278+}
279+
280+inline size_t get_num_bits(uint8_t const* array, std::initializer_list<size_t> bits)
281+{
282+ size_t ret = 0;
283+ for( auto const bit : bits)
284+ ret += get_bit(array, bit);
285+ return ret;
286+}
287+
288+void fill_identifier(int fd, mi::InputDeviceIdentifier &id)
289+{
290+ char buffer[80];
291+ if (ioctl(fd, EVIOCGNAME(sizeof buffer - 1), &buffer) < 1)
292+ BOOST_THROW_EXCEPTION(
293+ std::system_error(std::error_code(errno, std::system_category()),
294+ "Failed to get device name"));
295+
296+ buffer[sizeof(buffer) - 1] = '\0';
297+ id.name = buffer;
298+
299+ input_id device_input_id;
300+ if (ioctl(fd, EVIOCGID, &device_input_id) < 0)
301+ BOOST_THROW_EXCEPTION(
302+ std::system_error(std::error_code(errno, std::system_category()),
303+ "Failed to get device input id"));
304+
305+ id.bus = device_input_id.bustype;
306+ id.product = device_input_id.product;
307+ id.vendor = device_input_id.vendor;
308+ id.version = device_input_id.version;
309+
310+ if (ioctl(fd, EVIOCGPHYS(sizeof buffer - 1), &buffer))
311+ {
312+ // rarely supported, especially for builtin devices.
313+ buffer[sizeof(buffer) - 1] = '\0';
314+ id.location = buffer;
315+ }
316+
317+ if (ioctl(fd, EVIOCGUNIQ(sizeof buffer - 1), &buffer)) // rarely supported, especially for builtin devices.
318+ {
319+ buffer[sizeof(buffer) - 1] = '\0';
320+ id.unique_id = buffer;
321+ }
322+}
323+}
324+
325+mi::EvdevDeviceInfo::EvdevDeviceInfo(const char* devpath)
326+ : device_path(devpath)
327+{
328+ try
329+ {
330+ std::memset(key_bit_mask, 0, sizeof key_bit_mask);
331+ std::memset(abs_bit_mask, 0, sizeof abs_bit_mask);
332+ std::memset(rel_bit_mask, 0, sizeof rel_bit_mask);
333+ std::memset(sw_bit_mask, 0, sizeof sw_bit_mask);
334+ std::memset(led_bit_mask, 0, sizeof led_bit_mask);
335+ std::memset(ff_bit_mask, 0, sizeof ff_bit_mask);
336+ std::memset(property_bit_mask, 0, sizeof property_bit_mask);
337+
338+ mir::Fd input_device(::open(devpath, O_RDONLY|O_NONBLOCK));
339+ if (input_device < 0)
340+ BOOST_THROW_EXCEPTION(
341+ std::system_error(std::error_code(errno, std::system_category()),
342+ "Failed to open input device"));
343+
344+ // Figure out the kinds of events the device reports.
345+ auto const get_bitmask = [&](int bit, size_t size, uint8_t* buf) -> void
346+ {
347+ if(ioctl(input_device, EVIOCGBIT(bit, size), buf) < 1)
348+ BOOST_THROW_EXCEPTION(
349+ std::system_error(std::error_code(errno, std::system_category()),
350+ "Failed to query input device"));
351+ };
352+ get_bitmask(EV_KEY, sizeof key_bit_mask, key_bit_mask);
353+ get_bitmask(EV_REL, sizeof rel_bit_mask, rel_bit_mask);
354+ get_bitmask(EV_ABS, sizeof abs_bit_mask, abs_bit_mask);
355+ get_bitmask(EV_SW, sizeof sw_bit_mask, sw_bit_mask);
356+ get_bitmask(EV_LED, sizeof led_bit_mask, led_bit_mask);
357+ get_bitmask(EV_FF, sizeof ff_bit_mask, ff_bit_mask);
358+
359+ if (ioctl(input_device, EVIOCGPROP(sizeof property_bit_mask), property_bit_mask) < 1)
360+ BOOST_THROW_EXCEPTION(
361+ std::system_error(std::error_code(errno, std::system_category()),
362+ "Failed to query devices properties"));
363+
364+ fill_identifier(input_device, identifier);
365+
366+ device_class = evaluate_device_class();
367+ }
368+ catch (boost::exception& e)
369+ {
370+ e << boost::errinfo_file_name(devpath);
371+ throw;
372+ }
373+}
374+
375+std::string mi::EvdevDeviceInfo::path() const
376+{
377+ return device_path;
378+}
379+
380+uint32_t mi::EvdevDeviceInfo::device_classes() const
381+{
382+ return device_class;
383+}
384+
385+mi::InputDeviceIdentifier mi::EvdevDeviceInfo::id() const
386+{
387+ return identifier;
388+}
389+
390+uint32_t mi::EvdevDeviceInfo::evaluate_device_class() const
391+{
392+ uint32_t classes = 0;
393+ auto const contains_non_zero = [](uint8_t const* array, int first, int last) -> bool
394+ {
395+ return std::any_of(array + first, array + last, [](uint8_t item) { return item!=0;});
396+ };
397+
398+ bool const has_keys = contains_non_zero(key_bit_mask, 0, index_of_bit(BTN_MISC))
399+ || contains_non_zero(key_bit_mask, index_of_bit(KEY_OK), sizeof key_bit_mask);
400+ bool const has_gamepad_buttons =
401+ contains_non_zero(key_bit_mask, index_of_bit(BTN_MISC), index_of_bit(BTN_MOUSE))
402+ || contains_non_zero(key_bit_mask, index_of_bit(BTN_JOYSTICK), index_of_bit(BTN_DIGI));
403+
404+ if (has_keys || has_gamepad_buttons)
405+ classes |= keyboard;
406+
407+ if (get_bit(key_bit_mask, BTN_MOUSE) && get_bit(rel_bit_mask, REL_X) && get_bit(rel_bit_mask, REL_Y))
408+ classes |= cursor;
409+
410+ bool const has_coordinates = get_bit(abs_bit_mask, ABS_X) &&
411+ get_bit(abs_bit_mask, ABS_Y);
412+ bool const has_mt_coordinates = get_bit(abs_bit_mask, ABS_MT_POSITION_X) &&
413+ get_bit(abs_bit_mask, ABS_MT_POSITION_Y);
414+ bool const is_direct = get_bit(property_bit_mask, INPUT_PROP_DIRECT);
415+ bool const finger_but_no_pen = get_bit(key_bit_mask, BTN_TOOL_FINGER)
416+ && !get_bit(key_bit_mask, BTN_TOOL_PEN);
417+ bool const has_touch = get_bit(key_bit_mask, BTN_TOUCH);
418+
419+ if (finger_but_no_pen && !is_direct && (has_coordinates|| has_mt_coordinates))
420+ classes |= touchpad;
421+ else if (has_touch && ((has_mt_coordinates && !has_gamepad_buttons)
422+ || has_coordinates))
423+ classes |= touchscreen;
424+
425+
426+ bool const has_joystick_axis = 0 < get_num_bits(
427+ abs_bit_mask, {ABS_Z,
428+ ABS_RX, ABS_RY, ABS_RZ,
429+ ABS_THROTTLE, ABS_RUDDER, ABS_WHEEL, ABS_GAS, ABS_BRAKE,
430+ ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y, ABS_HAT3X, ABS_HAT3Y,
431+ ABS_TILT_X, ABS_TILT_Y
432+ });
433+
434+ if (has_joystick_axis || (!has_touch && has_coordinates))
435+ classes |= joystick;
436+
437+ if (has_gamepad_buttons)
438+ classes |= gamepad;
439+
440+ return classes;
441+}
442
443=== added file 'src/server/input/evdev_device_info.h'
444--- src/server/input/evdev_device_info.h 1970-01-01 00:00:00 +0000
445+++ src/server/input/evdev_device_info.h 2014-11-24 16:32:54 +0000
446@@ -0,0 +1,54 @@
447+/*
448+ * Copyright © 2014 Canonical Ltd.
449+ *
450+ * This program is free software: you can redistribute it and/or modify it
451+ * under the terms of the GNU General Public License version 3,
452+ * as published by the Free Software Foundation.
453+ *
454+ * This program is distributed in the hope that it will be useful,
455+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
456+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
457+ * GNU General Public License for more details.
458+ *
459+ * You should have received a copy of the GNU General Public License
460+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
461+ *
462+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
463+ */
464+
465+#ifndef MIR_INPUT_EVDEV_DEVICE_INFO_H_
466+#define MIR_INPUT_EVDEV_DEVICE_INFO_H_
467+
468+#include "input_device_info.h"
469+#include <linux/input.h>
470+
471+namespace mir
472+{
473+namespace input
474+{
475+
476+class EvdevDeviceInfo : public InputDeviceInfo
477+{
478+public:
479+ EvdevDeviceInfo(char const* devicepath);
480+ std::string path() const override;
481+ uint32_t device_classes() const override;
482+ InputDeviceIdentifier id() const override;
483+private:
484+ uint32_t evaluate_device_class() const;
485+ std::string device_path;
486+ uint32_t device_class;
487+ InputDeviceIdentifier identifier;
488+ uint8_t key_bit_mask[(KEY_MAX+1)/8];
489+ uint8_t abs_bit_mask[(ABS_MAX+1)/8];
490+ uint8_t rel_bit_mask[(REL_MAX+1)/8];
491+ uint8_t sw_bit_mask[(SW_MAX+1)/8];
492+ uint8_t led_bit_mask[(LED_MAX+1)/8];
493+ uint8_t ff_bit_mask[(FF_MAX+1)/8];
494+ uint8_t property_bit_mask[(INPUT_PROP_MAX+1)/8];
495+};
496+
497+}
498+}
499+
500+#endif
501
502=== added file 'src/server/input/evdev_input_device_factory.cpp'
503--- src/server/input/evdev_input_device_factory.cpp 1970-01-01 00:00:00 +0000
504+++ src/server/input/evdev_input_device_factory.cpp 2014-11-24 16:32:54 +0000
505@@ -0,0 +1,52 @@
506+/*
507+ * Copyright © 2013-2014 Canonical Ltd.
508+ *
509+ * This program is free software: you can redistribute it and/or modify
510+ * it under the terms of the GNU General Public License version 3 as
511+ * published by the Free Software Foundation.
512+ *
513+ * This program is distributed in the hope that it will be useful,
514+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
515+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
516+ * GNU General Public License for more details.
517+ *
518+ * You should have received a copy of the GNU General Public License
519+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
520+ *
521+ * Authored by: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
522+ * Andreas Pokorny <andreas.pokorny@canonical.com>
523+ */
524+
525+#include "evdev_input_device_factory.h"
526+#include "input_device_info.h"
527+#include "input_device_provider.h"
528+
529+#include "mir/input/input_device.h"
530+
531+namespace mi = mir::input;
532+
533+mi::EvdevInputDeviceFactory::EvdevInputDeviceFactory(std::initializer_list<std::shared_ptr<mi::InputDeviceProvider>> providers)
534+ : providers(providers)
535+{
536+}
537+
538+std::unique_ptr<mi::InputDevice> mi::EvdevInputDeviceFactory::create_device(mi::InputDeviceInfo const& info)
539+{
540+ InputDeviceProvider::Priority best_prio = mi::InputDeviceProvider::unsupported;
541+ InputDeviceProvider* best_provider = nullptr;
542+
543+ for (auto& provider : providers)
544+ {
545+ auto prio = provider->get_support(info);
546+ if (prio > best_prio)
547+ {
548+ best_prio = prio;
549+ best_provider = provider.get();
550+ }
551+ }
552+
553+ if (best_provider != nullptr)
554+ return std::move(best_provider->create_device(info));
555+
556+ return std::unique_ptr<mi::InputDevice>();
557+}
558
559=== added file 'src/server/input/evdev_input_device_factory.h'
560--- src/server/input/evdev_input_device_factory.h 1970-01-01 00:00:00 +0000
561+++ src/server/input/evdev_input_device_factory.h 2014-11-24 16:32:54 +0000
562@@ -0,0 +1,52 @@
563+/*
564+ * Copyright © 2013-2014 Canonical Ltd.
565+ *
566+ * This program is free software: you can redistribute it and/or modify it
567+ * under the terms of the GNU General Public License version 3,
568+ * as published by the Free Software Foundation.
569+ *
570+ * This program is distributed in the hope that it will be useful,
571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
573+ * GNU General Public License for more details.
574+ *
575+ * You should have received a copy of the GNU General Public License
576+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
577+ *
578+ * Authored by: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
579+ * Andreas Pokorny <andreas.pokorny@canonical.com>
580+ */
581+
582+#ifndef MIR_INPUT_EVDEV_INPUT_DEVICE_FACTORY_H_
583+#define MIR_INPUT_EVDEV_INPUT_DEVICE_FACTORY_H_
584+
585+#include "mir/input/input_device_factory.h"
586+
587+#include <memory>
588+#include <vector>
589+#include <initializer_list>
590+
591+namespace mir
592+{
593+namespace input
594+{
595+class InputDeviceInfo;
596+class InputDeviceProvider;
597+
598+class EvdevInputDeviceFactory : public InputDeviceFactory
599+{
600+public:
601+ EvdevInputDeviceFactory(std::initializer_list<std::shared_ptr<InputDeviceProvider>> providers);
602+
603+ std::unique_ptr<InputDevice> create_device(InputDeviceInfo const& info);
604+
605+private:
606+ std::vector<std::shared_ptr<InputDeviceProvider>> providers;
607+};
608+
609+}
610+} // namespace mir
611+
612+#endif // MIR_INPUT_EVDEV_INPUT_DEVICE_FACTORY_H_
613+
614+
615
616=== added file 'src/server/input/input_device_info.h'
617--- src/server/input/input_device_info.h 1970-01-01 00:00:00 +0000
618+++ src/server/input/input_device_info.h 2014-11-24 16:32:54 +0000
619@@ -0,0 +1,66 @@
620+/*
621+ * Copyright © 2014 Canonical Ltd.
622+ *
623+ * This program is free software: you can redistribute it and/or modify it
624+ * under the terms of the GNU General Public License version 3,
625+ * as published by the Free Software Foundation.
626+ *
627+ * This program is distributed in the hope that it will be useful,
628+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
629+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
630+ * GNU General Public License for more details.
631+ *
632+ * You should have received a copy of the GNU General Public License
633+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
634+ *
635+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
636+ */
637+
638+#ifndef MIR_INPUT_INPUT_DEVICE_INFO_H_
639+#define MIR_INPUT_INPUT_DEVICE_INFO_H_
640+
641+#include <memory>
642+#include <string>
643+
644+namespace mir
645+{
646+namespace input
647+{
648+
649+struct InputDeviceIdentifier
650+{
651+ std::string name;
652+ std::string location;
653+ std::string unique_id;
654+ uint16_t bus;
655+ uint16_t vendor;
656+ uint16_t product;
657+ uint16_t version;
658+};
659+
660+class InputDeviceInfo
661+{
662+public:
663+ InputDeviceInfo() = default;
664+ enum DeviceClasses
665+ {
666+ cursor = 1<<1,
667+ keyboard = 1<<2,
668+ touchpad = 1<<3,
669+ touchscreen = 1<<4,
670+ gamepad = 1<<5,
671+ joystick = 1<<6,
672+ };
673+ virtual std::string path() const = 0;
674+ virtual uint32_t device_classes() const = 0;
675+ virtual InputDeviceIdentifier id() const = 0;
676+ virtual ~InputDeviceInfo() = default;
677+private:
678+ InputDeviceInfo(InputDeviceInfo const&) = delete;
679+ InputDeviceInfo& operator=(InputDeviceInfo const&) = delete;
680+};
681+
682+}
683+}
684+
685+#endif
686
687=== added file 'src/server/input/input_device_provider.h'
688--- src/server/input/input_device_provider.h 1970-01-01 00:00:00 +0000
689+++ src/server/input/input_device_provider.h 2014-11-24 16:32:54 +0000
690@@ -0,0 +1,59 @@
691+/*
692+ * Copyright © 2013-2014 Canonical Ltd.
693+ *
694+ * This program is free software: you can redistribute it and/or modify it
695+ * under the terms of the GNU General Public License version 3,
696+ * as published by the Free Software Foundation.
697+ *
698+ * This program is distributed in the hope that it will be useful,
699+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
700+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
701+ * GNU General Public License for more details.
702+ *
703+ * You should have received a copy of the GNU General Public License
704+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
705+ *
706+ * Authored by: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
707+ * Andreas Pokorny <andreas.pokorny@canonical.com>
708+ */
709+
710+#ifndef MIR_INPUT_INPUT_DEVICE_PROVIDER_H_
711+#define MIR_INPUT_INPUT_DEVICE_PROVIDER_H_
712+
713+#include <memory>
714+
715+namespace mir
716+{
717+namespace input
718+{
719+class InputDeviceInfo;
720+class InputDevice;
721+
722+class InputDeviceProvider
723+{
724+public:
725+ enum Priority
726+ {
727+ unsupported = 0,
728+ supported = 100,
729+ best = 255,
730+ };
731+
732+ InputDeviceProvider() = default;
733+ virtual ~InputDeviceProvider() = default;
734+
735+ virtual Priority get_support(InputDeviceInfo const& info) const = 0;
736+ virtual std::unique_ptr<InputDevice> create_device(InputDeviceInfo const& device) const = 0;
737+
738+protected:
739+ InputDeviceProvider(InputDeviceProvider const& cp) = delete;
740+ InputDeviceProvider& operator=(InputDeviceProvider const& cp) = delete;
741+
742+};
743+
744+}
745+} // namespace mir
746+
747+#endif // MIR_INPUT_INPUT_DEVICE_PROVIDER_H_
748+
749+
750
751=== added directory 'src/server/input/libinput'
752=== added file 'src/server/input/libinput/CMakeLists.txt'
753--- src/server/input/libinput/CMakeLists.txt 1970-01-01 00:00:00 +0000
754+++ src/server/input/libinput/CMakeLists.txt 2014-11-24 16:32:54 +0000
755@@ -0,0 +1,10 @@
756+list(
757+ APPEND INPUT_SOURCES
758+ ${CMAKE_CURRENT_SOURCE_DIR}/input_device_provider.cpp
759+ )
760+
761+set(
762+ INPUT_SOURCES
763+ ${INPUT_SOURCES}
764+ PARENT_SCOPE
765+)
766
767=== added file 'src/server/input/libinput/input_device_provider.cpp'
768--- src/server/input/libinput/input_device_provider.cpp 1970-01-01 00:00:00 +0000
769+++ src/server/input/libinput/input_device_provider.cpp 2014-11-24 16:32:54 +0000
770@@ -0,0 +1,61 @@
771+/*
772+ * Copyright © 2014 Canonical Ltd.
773+ *
774+ * This program is free software: you can redistribute it and/or modify it
775+ * under the terms of the GNU General Public License version 3,
776+ * as published by the Free Software Foundation.
777+ *
778+ * This program is distributed in the hope that it will be useful,
779+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
780+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
781+ * GNU General Public License for more details.
782+ *
783+ * You should have received a copy of the GNU General Public License
784+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
785+ *
786+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
787+ */
788+
789+#include "input_device_provider.h"
790+
791+#include "../input_device_info.h"
792+
793+#include "mir/input/input_device.h"
794+
795+#include <sys/types.h>
796+#include <sys/stat.h>
797+#include <fcntl.h>
798+#include <unistd.h>
799+#include <stdexcept>
800+
801+namespace mi = mir::input;
802+namespace mili = mi::libinput;
803+
804+mi::InputDeviceProvider::Priority mili::InputDeviceProvider::get_support(mi::InputDeviceInfo const& device) const
805+{
806+ auto device_classes = device.device_classes();
807+
808+ if (device_classes & mi::InputDeviceInfo::joystick)
809+ return unsupported;
810+
811+ if (device_classes & mi::InputDeviceInfo::gamepad)
812+ return unsupported;
813+
814+ if (device_classes & mi::InputDeviceInfo::touchscreen)
815+ return unsupported;
816+
817+ if (device_classes & mi::InputDeviceInfo::touchpad)
818+ return best;
819+
820+ if (device_classes == 0)
821+ return unsupported;
822+
823+ return supported;
824+}
825+
826+std::unique_ptr<mi::InputDevice> mili::InputDeviceProvider::create_device(mi::InputDeviceInfo const& device) const
827+{
828+ (void)device;
829+ return std::unique_ptr<mi::InputDevice>();
830+}
831+
832
833=== added file 'src/server/input/libinput/input_device_provider.h'
834--- src/server/input/libinput/input_device_provider.h 1970-01-01 00:00:00 +0000
835+++ src/server/input/libinput/input_device_provider.h 2014-11-24 16:32:54 +0000
836@@ -0,0 +1,42 @@
837+/*
838+ * Copyright © 2014 Canonical Ltd.
839+ *
840+ * This program is free software: you can redistribute it and/or modify it
841+ * under the terms of the GNU General Public License version 3,
842+ * as published by the Free Software Foundation.
843+ *
844+ * This program is distributed in the hope that it will be useful,
845+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
846+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
847+ * GNU General Public License for more details.
848+ *
849+ * You should have received a copy of the GNU General Public License
850+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
851+ *
852+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
853+ */
854+
855+#ifndef MIR_INPUT_LIBINPUT_INPUT_DEVICE_PROVIDER_H_
856+#define MIR_INPUT_LIBINPUT_INPUT_DEVICE_PROVIDER_H_
857+
858+#include "../input_device_provider.h"
859+
860+namespace mir
861+{
862+namespace input
863+{
864+namespace libinput
865+{
866+
867+class InputDeviceProvider : public input::InputDeviceProvider
868+{
869+public:
870+ Priority get_support(input::InputDeviceInfo const& device) const override;
871+ std::unique_ptr<InputDevice> create_device(input::InputDeviceInfo const& device) const override;
872+};
873+
874+}
875+}
876+}
877+
878+#endif // MIR_INPUT_LIBINPUT_INPUT_DEVICE_PROVIDER_H_
879
880=== added file 'tests/include/mir_test_doubles/stub_input_device_info.h'
881--- tests/include/mir_test_doubles/stub_input_device_info.h 1970-01-01 00:00:00 +0000
882+++ tests/include/mir_test_doubles/stub_input_device_info.h 2014-11-24 16:32:54 +0000
883@@ -0,0 +1,56 @@
884+/*
885+ * Copyright © 2014 Canonical Ltd.
886+ *
887+ * This program is free software: you can redistribute it and/or modify it
888+ * under the terms of the GNU General Public License version 3,
889+ * as published by the Free Software Foundation.
890+ *
891+ * This program is distributed in the hope that it will be useful,
892+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
893+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
894+ * GNU General Public License for more details.
895+ *
896+ * You should have received a copy of the GNU General Public License
897+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
898+ *
899+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
900+ */
901+
902+#ifndef MIR_TEST_DOUBLES_STUB_INPUT_INPUT_DEVICE_INFO_H_
903+#define MIR_TEST_DOUBLES_STUB_INPUT_INPUT_DEVICE_INFO_H_
904+
905+#include "src/server/input/input_device_info.h"
906+
907+namespace mir
908+{
909+namespace test
910+{
911+namespace doubles
912+{
913+
914+class StubInputDeviceInfo : public mir::input::InputDeviceInfo
915+{
916+public:
917+ explicit StubInputDeviceInfo(uint32_t classes = 0)
918+ : input_classes(classes)
919+ {}
920+ std::string path() const override
921+ {
922+ return "";
923+ }
924+ uint32_t device_classes() const override
925+ {
926+ return input_classes;
927+ }
928+ mir::input::InputDeviceIdentifier id() const override
929+ {
930+ return mir::input::InputDeviceIdentifier();
931+ }
932+ uint32_t input_classes;
933+};
934+
935+}
936+}
937+}
938+
939+#endif
940
941=== added file 'tests/mir_test_framework/udev_recordings/joystick-detection.ioctl'
942--- tests/mir_test_framework/udev_recordings/joystick-detection.ioctl 1970-01-01 00:00:00 +0000
943+++ tests/mir_test_framework/udev_recordings/joystick-detection.ioctl 2014-11-24 16:32:54 +0000
944@@ -0,0 +1,25 @@
945+@DEV /dev/input/event13
946+EVIOCGBIT(1) 96 000000000000000000000000000000000000000000000000000000000000000000000000FF0F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
947+EVIOCGBIT(2) 2 0000
948+EVIOCGBIT(3) 8 6300030000000000
949+EVIOCGBIT(5) 2 0000
950+EVIOCGBIT(17) 2 0000
951+EVIOCGBIT(21) 16 00000000000000000000000000000000
952+EVIOCGPROP(0) 4 00000000
953+EVIOCGBIT(0) 8 0B00000000000000
954+EVIOCGNAME(0) 29 4C6F676974656368204C6F6769746563682045787472656D65203344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
955+EVIOCGPHYS(0) 26 7573622D303030303A30303A31342E302D322F696E70757430000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
956+EVIOCGUNIQ(0) 1 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
957+EVIOCGID 0 03006D0415C21001
958+EVIOCGVERSION 0 01000100
959+EVIOCGBIT(4) 8 1000000000000000
960+EVIOCGBIT(18) 8 0000000000000000
961+EVIOCGKEY(0) 96 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
962+EVIOCGLED(0) 8 0000000000000000
963+EVIOCGSW(0) 8 0000000000000000
964+EVIOCGABS 0 FC01000000000000FF030000030000003F00000000000000
965+EVIOCGABS(1) 0 FC01000000000000FF030000030000003F00000000000000
966+EVIOCGABS(5) 0 8000000000000000FF000000000000000F00000000000000
967+EVIOCGABS(6) 0 0000000000000000FF000000000000000F00000000000000
968+EVIOCGABS(16) 0 00000000FFFFFFFF01000000000000000000000000000000
969+EVIOCGABS(17) 0 00000000FFFFFFFF01000000000000000000000000000000
970
971=== added file 'tests/mir_test_framework/udev_recordings/joystick-detection.umockdev'
972--- tests/mir_test_framework/udev_recordings/joystick-detection.umockdev 1970-01-01 00:00:00 +0000
973+++ tests/mir_test_framework/udev_recordings/joystick-detection.umockdev 2014-11-24 16:32:54 +0000
974@@ -0,0 +1,351 @@
975+P: /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/0003:046D:C215.0016/input/input258/event13
976+N: input/event13
977+S: input/by-id/usb-Logitech_Logitech_Extreme_3D-event-joystick
978+S: input/by-path/pci-0000:00:14.0-usb-0:2:1.0-event-joystick
979+E: DEVLINKS=/dev/input/by-id/usb-Logitech_Logitech_Extreme_3D-event-joystick /dev/input/by-path/pci-0000:00:14.0-usb-0:2:1.0-event-joystick
980+E: DEVNAME=/dev/input/event13
981+E: ID_BUS=usb
982+E: ID_FOR_SEAT=input-pci-0000_00_14_0-usb-0_2_1_0
983+E: ID_INPUT=1
984+E: ID_INPUT_JOYSTICK=1
985+E: ID_MODEL=Logitech_Extreme_3D
986+E: ID_MODEL_ENC=Logitech\x20Extreme\x203D
987+E: ID_MODEL_ID=c215
988+E: ID_PATH=pci-0000:00:14.0-usb-0:2:1.0
989+E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_2_1_0
990+E: ID_REVISION=0204
991+E: ID_SERIAL=Logitech_Logitech_Extreme_3D
992+E: ID_TYPE=hid
993+E: ID_USB_DRIVER=usbhid
994+E: ID_USB_INTERFACES=:030000:
995+E: ID_USB_INTERFACE_NUM=00
996+E: ID_VENDOR=Logitech
997+E: ID_VENDOR_ENC=Logitech
998+E: ID_VENDOR_ID=046d
999+E: MAJOR=13
1000+E: MINOR=77
1001+E: SUBSYSTEM=input
1002+E: TAGS=:seat:uaccess:
1003+A: dev=13:77
1004+L: device=../../input258
1005+A: power/async=disabled
1006+A: power/control=auto
1007+A: power/runtime_active_kids=0
1008+A: power/runtime_active_time=0
1009+A: power/runtime_enabled=disabled
1010+A: power/runtime_status=unsupported
1011+A: power/runtime_suspended_time=0
1012+A: power/runtime_usage=0
1013+
1014+P: /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/0003:046D:C215.0016/input/input258
1015+E: ABS=30063
1016+E: EV=1b
1017+E: ID_BUS=usb
1018+E: ID_FOR_SEAT=input-pci-0000_00_14_0-usb-0_2_1_0
1019+E: ID_INPUT=1
1020+E: ID_INPUT_JOYSTICK=1
1021+E: ID_MODEL=Logitech_Extreme_3D
1022+E: ID_MODEL_ENC=Logitech\x20Extreme\x203D
1023+E: ID_MODEL_ID=c215
1024+E: ID_PATH=pci-0000:00:14.0-usb-0:2:1.0
1025+E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_2_1_0
1026+E: ID_REVISION=0204
1027+E: ID_SERIAL=Logitech_Logitech_Extreme_3D
1028+E: ID_TYPE=hid
1029+E: ID_USB_DRIVER=usbhid
1030+E: ID_USB_INTERFACES=:030000:
1031+E: ID_USB_INTERFACE_NUM=00
1032+E: ID_VENDOR=Logitech
1033+E: ID_VENDOR_ENC=Logitech
1034+E: ID_VENDOR_ID=046d
1035+E: KEY=fff00000000 0 0 0 0
1036+E: MODALIAS=input:b0003v046DpC215e0110-e0,1,3,4,k120,121,122,123,124,125,126,127,128,129,12A,12B,ra0,1,5,6,10,11,m4,lsfw
1037+E: MSC=10
1038+E: NAME="Logitech Logitech Extreme 3D"
1039+E: PHYS="usb-0000:00:14.0-2/input0"
1040+E: PRODUCT=3/46d/c215/110
1041+E: PROP=0
1042+E: SUBSYSTEM=input
1043+E: TAGS=:seat:
1044+E: UNIQ=""
1045+A: capabilities/abs=30063
1046+A: capabilities/ev=1b
1047+A: capabilities/ff=0
1048+A: capabilities/key=fff00000000 0 0 0 0
1049+A: capabilities/led=0
1050+A: capabilities/msc=10
1051+A: capabilities/rel=0
1052+A: capabilities/snd=0
1053+A: capabilities/sw=0
1054+L: device=../../../0003:046D:C215.0016
1055+A: id/bustype=0003
1056+A: id/product=c215
1057+A: id/vendor=046d
1058+A: id/version=0110
1059+A: modalias=input:b0003v046DpC215e0110-e0,1,3,4,k120,121,122,123,124,125,126,127,128,129,12A,12B,ra0,1,5,6,10,11,m4,lsfw
1060+A: name=Logitech Logitech Extreme 3D
1061+A: phys=usb-0000:00:14.0-2/input0
1062+A: power/async=disabled
1063+A: power/control=auto
1064+A: power/runtime_active_kids=0
1065+A: power/runtime_active_time=0
1066+A: power/runtime_enabled=disabled
1067+A: power/runtime_status=unsupported
1068+A: power/runtime_suspended_time=0
1069+A: power/runtime_usage=0
1070+A: properties=0
1071+A: uniq=
1072+
1073+P: /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/0003:046D:C215.0016
1074+E: DRIVER=logitech
1075+E: HID_ID=0003:0000046D:0000C215
1076+E: HID_NAME=Logitech Logitech Extreme 3D
1077+E: HID_PHYS=usb-0000:00:14.0-2/input0
1078+E: MODALIAS=hid:b0003g0000v0000046Dp0000C215
1079+E: SUBSYSTEM=hid
1080+E: UPOWER_VENDOR=Logitech, Inc.
1081+L: driver=../../../../../../../bus/hid/drivers/logitech
1082+A: modalias=hid:b0003g0000v0000046Dp0000C215
1083+A: power/async=disabled
1084+A: power/control=auto
1085+A: power/runtime_active_kids=0
1086+A: power/runtime_active_time=0
1087+A: power/runtime_enabled=disabled
1088+A: power/runtime_status=unsupported
1089+A: power/runtime_suspended_time=0
1090+A: power/runtime_usage=0
1091+H: report_descriptor=05010904A101A1029502750A150026FF03350046FF03093009318102750495012507463B01661400093981426500750826FF0046FF0009358102A495087501250145010509190129088102B409368102950475012501450105091909290C810295048101C0A1029504750826FF0046FF000600FF0901B102C0C0
1092+
1093+P: /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0
1094+E: DEVTYPE=usb_interface
1095+E: DRIVER=usbhid
1096+E: ID_MODEL_FROM_DATABASE=Extreme 3D Pro
1097+E: ID_VENDOR_FROM_DATABASE=Logitech, Inc.
1098+E: INTERFACE=3/0/0
1099+E: MODALIAS=usb:v046DpC215d0204dc00dsc00dp00ic03isc00ip00in00
1100+E: PRODUCT=46d/c215/204
1101+E: SUBSYSTEM=usb
1102+E: TYPE=0/0/0
1103+A: bAlternateSetting= 0
1104+A: bInterfaceClass=03
1105+A: bInterfaceNumber=00
1106+A: bInterfaceProtocol=00
1107+A: bInterfaceSubClass=00
1108+A: bNumEndpoints=01
1109+L: driver=../../../../../../bus/usb/drivers/usbhid
1110+A: modalias=usb:v046DpC215d0204dc00dsc00dp00ic03isc00ip00in00
1111+A: power/async=enabled
1112+A: power/runtime_active_kids=0
1113+A: power/runtime_enabled=enabled
1114+A: power/runtime_status=suspended
1115+A: power/runtime_usage=0
1116+A: supports_autosuspend=1
1117+
1118+P: /devices/pci0000:00/0000:00:14.0/usb3/3-2
1119+N: bus/usb/003/043=12011001000000086D0415C204020102000109022200010100800F090400000103000000092110012101227A000705810307000A
1120+E: BUSNUM=003
1121+E: DEVNAME=/dev/bus/usb/003/043
1122+E: DEVNUM=043
1123+E: DEVTYPE=usb_device
1124+E: DRIVER=usb
1125+E: ID_BUS=usb
1126+E: ID_MODEL=Logitech_Extreme_3D
1127+E: ID_MODEL_ENC=Logitech\x20Extreme\x203D
1128+E: ID_MODEL_FROM_DATABASE=Extreme 3D Pro
1129+E: ID_MODEL_ID=c215
1130+E: ID_REVISION=0204
1131+E: ID_SERIAL=Logitech_Logitech_Extreme_3D
1132+E: ID_USB_INTERFACES=:030000:
1133+E: ID_VENDOR=Logitech
1134+E: ID_VENDOR_ENC=Logitech
1135+E: ID_VENDOR_FROM_DATABASE=Logitech, Inc.
1136+E: ID_VENDOR_ID=046d
1137+E: MAJOR=189
1138+E: MINOR=298
1139+E: PRODUCT=46d/c215/204
1140+E: SUBSYSTEM=usb
1141+E: TYPE=0/0/0
1142+E: UPOWER_VENDOR=Logitech, Inc.
1143+A: authorized=1
1144+A: avoid_reset_quirk=0
1145+A: bConfigurationValue=1
1146+A: bDeviceClass=00
1147+A: bDeviceProtocol=00
1148+A: bDeviceSubClass=00
1149+A: bMaxPacketSize0=8
1150+A: bMaxPower=30mA
1151+A: bNumConfigurations=1
1152+A: bNumInterfaces= 1
1153+A: bcdDevice=0204
1154+A: bmAttributes=80
1155+A: busnum=3
1156+A: configuration=
1157+H: descriptors=12011001000000086D0415C204020102000109022200010100800F090400000103000000092110012101227A000705810307000A
1158+A: dev=189:298
1159+A: devnum=43
1160+A: devpath=2
1161+L: driver=../../../../../bus/usb/drivers/usb
1162+A: idProduct=c215
1163+A: idVendor=046d
1164+A: ltm_capable=no
1165+A: manufacturer=Logitech
1166+A: maxchild=0
1167+L: port=../3-0:1.0/usb3-port2
1168+A: power/active_duration=1287064
1169+A: power/async=enabled
1170+A: power/autosuspend=2
1171+A: power/autosuspend_delay_ms=2000
1172+A: power/connected_duration=1287064
1173+A: power/control=on
1174+A: power/level=on
1175+A: power/persist=1
1176+A: power/runtime_active_kids=0
1177+A: power/runtime_active_time=1286764
1178+A: power/runtime_enabled=forbidden
1179+A: power/runtime_status=active
1180+A: power/runtime_suspended_time=0
1181+A: power/runtime_usage=1
1182+A: product=Logitech Extreme 3D
1183+A: quirks=0x0
1184+A: removable=unknown
1185+A: speed=1.5
1186+A: urbnum=24
1187+A: version= 1.10
1188+
1189+P: /devices/pci0000:00/0000:00:14.0/usb3
1190+N: bus/usb/003/001=12010002090001406B1D020016030302010109021900010100E0000904000001090000000705810304000C
1191+E: BUSNUM=003
1192+E: DEVNAME=/dev/bus/usb/003/001
1193+E: DEVNUM=001
1194+E: DEVTYPE=usb_device
1195+E: DRIVER=usb
1196+E: ID_BUS=usb
1197+E: ID_FOR_SEAT=usb-pci-0000_00_14_0
1198+E: ID_MODEL=xHCI_Host_Controller
1199+E: ID_MODEL_ENC=xHCI\x20Host\x20Controller
1200+E: ID_MODEL_FROM_DATABASE=2.0 root hub
1201+E: ID_MODEL_ID=0002
1202+E: ID_PATH=pci-0000:00:14.0
1203+E: ID_PATH_TAG=pci-0000_00_14_0
1204+E: ID_REVISION=0316
1205+E: ID_SERIAL=Linux_3.16.0-24-generic_xhci_hcd_xHCI_Host_Controller_0000:00:14.0
1206+E: ID_SERIAL_SHORT=0000:00:14.0
1207+E: ID_USB_INTERFACES=:090000:
1208+E: ID_VENDOR=Linux_3.16.0-24-generic_xhci_hcd
1209+E: ID_VENDOR_ENC=Linux\x203.16.0-24-generic\x20xhci_hcd
1210+E: ID_VENDOR_FROM_DATABASE=Linux Foundation
1211+E: ID_VENDOR_ID=1d6b
1212+E: MAJOR=189
1213+E: MINOR=256
1214+E: PRODUCT=1d6b/2/316
1215+E: SUBSYSTEM=usb
1216+E: TAGS=:seat:
1217+E: TYPE=9/0/1
1218+A: authorized=1
1219+A: authorized_default=1
1220+A: avoid_reset_quirk=0
1221+A: bConfigurationValue=1
1222+A: bDeviceClass=09
1223+A: bDeviceProtocol=01
1224+A: bDeviceSubClass=00
1225+A: bMaxPacketSize0=64
1226+A: bMaxPower=0mA
1227+A: bNumConfigurations=1
1228+A: bNumInterfaces= 1
1229+A: bcdDevice=0316
1230+A: bmAttributes=e0
1231+A: busnum=3
1232+A: configuration=
1233+H: descriptors=12010002090001406B1D020016030302010109021900010100E0000904000001090000000705810304000C
1234+A: dev=189:256
1235+A: devnum=1
1236+A: devpath=0
1237+L: driver=../../../../bus/usb/drivers/usb
1238+A: idProduct=0002
1239+A: idVendor=1d6b
1240+A: ltm_capable=no
1241+A: manufacturer=Linux 3.16.0-24-generic xhci_hcd
1242+A: maxchild=14
1243+A: power/active_duration=471394472
1244+A: power/async=enabled
1245+A: power/autosuspend=0
1246+A: power/autosuspend_delay_ms=0
1247+A: power/connected_duration=493735372
1248+A: power/control=auto
1249+A: power/level=auto
1250+A: power/runtime_active_kids=3
1251+A: power/runtime_active_time=466119148
1252+A: power/runtime_enabled=enabled
1253+A: power/runtime_status=active
1254+A: power/runtime_suspended_time=22335316
1255+A: power/runtime_usage=0
1256+A: power/wakeup=disabled
1257+A: power/wakeup_abort_count=
1258+A: power/wakeup_active=
1259+A: power/wakeup_active_count=
1260+A: power/wakeup_count=
1261+A: power/wakeup_expire_count=
1262+A: power/wakeup_last_time_ms=
1263+A: power/wakeup_max_time_ms=
1264+A: power/wakeup_total_time_ms=
1265+A: product=xHCI Host Controller
1266+A: quirks=0x0
1267+A: removable=unknown
1268+A: serial=0000:00:14.0
1269+A: speed=480
1270+A: urbnum=1514
1271+A: version= 2.00
1272+
1273+P: /devices/pci0000:00/0000:00:14.0
1274+E: DRIVER=xhci_hcd
1275+E: ID_MODEL_FROM_DATABASE=8 Series/C220 Series Chipset Family USB xHCI
1276+E: ID_PCI_CLASS_FROM_DATABASE=Serial bus controller
1277+E: ID_PCI_INTERFACE_FROM_DATABASE=XHCI
1278+E: ID_PCI_SUBCLASS_FROM_DATABASE=USB controller
1279+E: ID_VENDOR_FROM_DATABASE=Intel Corporation
1280+E: MODALIAS=pci:v00008086d00008C31sv00001558sd00007410bc0Csc03i30
1281+E: PCI_CLASS=C0330
1282+E: PCI_ID=8086:8C31
1283+E: PCI_SLOT_NAME=0000:00:14.0
1284+E: PCI_SUBSYS_ID=1558:7410
1285+E: SUBSYSTEM=pci
1286+A: broken_parity_status=0
1287+A: class=0x0c0330
1288+H: config=8680318C060490020530030C000000000400E2F7000000000000000000000000000000000000000000000000581510740000000070000000000000000B010000FD01368089C60F8000000000000000009F6E8807000000000000000000000000302000000000000000000000000000000180C2C108000000000000000000000005008700F802E0FE000000000000000000000000000000000000000000000000400100000000000000000000000000000F000100000000000000000000000000030420C0030C3000030C300000000000FF3F0000FF3F00003F0000003F000000A0000000D03C000000000000D8D8D8080000000000000000B10F060800000000
1289+A: consistent_dma_mask_bits=64
1290+A: d3cold_allowed=1
1291+A: device=0x8c31
1292+A: dma_mask_bits=64
1293+L: driver=../../../bus/pci/drivers/xhci_hcd
1294+A: driver_override=(null)
1295+A: enabled=1
1296+A: irq=42
1297+A: local_cpulist=0-7
1298+A: local_cpus=00000000,00000000,00000000,00000000,00000000,00000000,00000000,000000ff
1299+A: modalias=pci:v00008086d00008C31sv00001558sd00007410bc0Csc03i30
1300+A: msi_bus=
1301+A: msi_irqs/42=msi
1302+A: numa_node=-1
1303+A: pools=poolinfo - 0.1\nbuffer-2048 0 0 2048 0\nbuffer-512 0 0 512 0\nbuffer-128 0 0 128 0\nbuffer-32 0 0 32 0\nxHCI 1KB stream ctx arrays 0 0 1024 0\nxHCI 256 byte stream ctx arrays 0 0 256 0\nxHCI input/output contexts 7 11 2112 11\nxHCI ring segments 82 152 1024 38\nbuffer-2048 0 38 2048 19\nbuffer-512 0 16 512 2\nbuffer-128 3 32 128 1\nbuffer-32 0 0 32 0
1304+A: power/async=enabled
1305+A: power/control=on
1306+A: power/runtime_active_kids=1
1307+A: power/runtime_active_time=493735800
1308+A: power/runtime_enabled=forbidden
1309+A: power/runtime_status=active
1310+A: power/runtime_suspended_time=0
1311+A: power/runtime_usage=1
1312+A: power/wakeup=enabled
1313+A: power/wakeup_abort_count=0
1314+A: power/wakeup_active=0
1315+A: power/wakeup_active_count=0
1316+A: power/wakeup_count=0
1317+A: power/wakeup_expire_count=0
1318+A: power/wakeup_last_time_ms=1534
1319+A: power/wakeup_max_time_ms=0
1320+A: power/wakeup_total_time_ms=0
1321+A: resource=0x00000000f7e20000 0x00000000f7e2ffff 0x0000000000140204\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000\n0x0000000000000000 0x0000000000000000 0x0000000000000000
1322+A: subsystem_device=0x7410
1323+A: subsystem_vendor=0x1558
1324+A: vendor=0x8086
1325+
1326
1327=== added file 'tests/mir_test_framework/udev_recordings/mt-screen-detection.ioctl'
1328--- tests/mir_test_framework/udev_recordings/mt-screen-detection.ioctl 1970-01-01 00:00:00 +0000
1329+++ tests/mir_test_framework/udev_recordings/mt-screen-detection.ioctl 2014-11-24 16:32:54 +0000
1330@@ -0,0 +1,28 @@
1331+@DEV /dev/input/event4
1332+EVIOCGBIT(1) 96 000000000000000000000000000010000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1333+EVIOCGBIT(2) 2 0000
1334+EVIOCGBIT(3) 8 0300000100006306
1335+EVIOCGBIT(5) 2 0000
1336+EVIOCGBIT(17) 2 0000
1337+EVIOCGBIT(21) 16 00000000000000000000000000000000
1338+EVIOCGPROP(0) 8 02000000
1339+EVIOCGBIT(0) 8 0B00000000000000
1340+EVIOCGNAME(0) 8 6D746B2D747064000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1341+EVIOCGID 0 0000000000000000
1342+EVIOCGPHYS(0) 0 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1343+EVIOCGUNIQ(0) 0 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1344+EVIOCGVERSION 0 01000100
1345+EVIOCGBIT(4) 8 0000000000000000
1346+EVIOCGBIT(18) 8 0000000000000000
1347+EVIOCGKEY(0) 96 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1348+EVIOCGLED(0) 4 00000000
1349+EVIOCGSW(0) 4 00000000
1350+EVIOCGABS 0 00000000000000001C02000000000000000000001C020000
1351+EVIOCGABS(1) 0 0000000000000000C00300000000000000000000C0030000
1352+EVIOCGABS(24) 0 0000000000000000FF000000000000000000000000000000
1353+EVIOCGABS(48) 0 000000000000000064000000000000000000000000000000
1354+EVIOCGABS(49) 0 000000000000000064000000000000000000000000000000
1355+EVIOCGABS(53) 0 00000000000000001C020000000000000000000000000000
1356+EVIOCGABS(54) 0 0000000000000000C0030000000000000000000000000000
1357+EVIOCGABS(57) 0 000000000000000000000000000000000000000000000000
1358+EVIOCGABS(58) 0 0000000000000000FF000000000000000000000000000000
1359
1360=== added file 'tests/mir_test_framework/udev_recordings/mt-screen-detection.umockdev'
1361--- tests/mir_test_framework/udev_recordings/mt-screen-detection.umockdev 1970-01-01 00:00:00 +0000
1362+++ tests/mir_test_framework/udev_recordings/mt-screen-detection.umockdev 2014-11-24 16:32:54 +0000
1363@@ -0,0 +1,44 @@
1364+P: /devices/virtual/input/input4/event4
1365+N: input/event4
1366+E: DEVNAME=/dev/input/event4
1367+E: ID_INPUT=1
1368+E: ID_INPUT_KEY=1
1369+E: ID_INPUT_TOUCHSCREEN=1
1370+E: MAJOR=13
1371+E: MINOR=68
1372+E: SUBSYSTEM=input
1373+A: dev=13:68
1374+L: device=../../input4
1375+
1376+P: /devices/virtual/input/input4
1377+E: ABS=6630000 1000003
1378+E: EV=b
1379+E: ID_INPUT=1
1380+E: ID_INPUT_KEY=1
1381+E: ID_INPUT_TOUCHSCREEN=1
1382+E: KEY=400 0 0 0 0 0 0 100000 0 0 0
1383+E: MODALIAS=input:b0000v0000p0000e0000-e0,1,3,k74,14A,ra0,1,18,30,31,35,36,39,3A,mlsfw
1384+E: NAME="mtk-tpd"
1385+E: PRODUCT=0/0/0/0
1386+E: PROP=2
1387+E: SUBSYSTEM=input
1388+E: TAGS=:seat:
1389+A: capabilities/abs=6630000 1000003
1390+A: capabilities/ev=b
1391+A: capabilities/ff=0
1392+A: capabilities/key=400 0 0 0 0 0 0 100000 0 0 0
1393+A: capabilities/led=0
1394+A: capabilities/msc=0
1395+A: capabilities/rel=0
1396+A: capabilities/snd=0
1397+A: capabilities/sw=0
1398+A: id/bustype=0000
1399+A: id/product=0000
1400+A: id/vendor=0000
1401+A: id/version=0000
1402+A: modalias=input:b0000v0000p0000e0000-e0,1,3,k74,14A,ra0,1,18,30,31,35,36,39,3A,mlsfw
1403+A: name=mtk-tpd
1404+A: phys=
1405+A: properties=2
1406+A: uniq=
1407+
1408
1409=== modified file 'tests/mir_test_framework/udev_recordings/synaptics-touchpad.ioctl'
1410--- tests/mir_test_framework/udev_recordings/synaptics-touchpad.ioctl 2014-02-17 03:46:06 +0000
1411+++ tests/mir_test_framework/udev_recordings/synaptics-touchpad.ioctl 2014-11-24 16:32:54 +0000
1412@@ -19,11 +19,4 @@
1413 EVIOCGNAME(0) 27 53796E50532F322053796E61707469637320546F756368506164000000000000200B00A8A37F0000C8A59DC6A37F0000C00800A8A37F0000C00407B8A37F0000F0DF950100000000F53326C8A37F00
1414 EVIOCGPHYS(0) 22 697361303036302F736572696F322F696E707574300068506164000000000000200B00A8A37F0000C8A59DC6A37F0000C00800A8A37F0000C00407B8A37F0000F0DF950100000000F53326C8A37F00
1415 EVIOCGNAME(0) 18 48444120496E74656C20504348204D6963007574300068506164000000000000200B00CC1C7F0000C81563E91C7F0000C00800CC1C7F0000C074CCDA1C7F0000307F170200000000F5A3EBEA1C7F00
1416-EVIOCGID 0 0000000000000000
1417 EVIOCGPHYS(0) 5 414C5341006E74656C20504348204D6963007574300068506164000000000000200B00CC1C7F0000C81563E91C7F0000C00800CC1C7F0000C074CCDA1C7F0000307F170200000000F5A3EBEA1C7F00
1418-EVIOCGBIT(1) 96 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1419-EVIOCGBIT(3) 8 0000000000000000
1420-EVIOCGBIT(5) 2 1000
1421-EVIOCGPROP(0) 4 00000000
1422-EVIOCGNAME(0) 27 53796E50532F322053796E61707469637320546F756368506164000000000000200B00E8217F0000C885F704227F0000C00800E8217F0000C0E460F6217F0000303FF40100000000F5138006227F00
1423-EVIOCGPHYS(0) 22 697361303036302F736572696F322F696E707574300068506164000000000000200B00E8217F0000C885F704227F0000C00800E8217F0000C0E460F6217F0000303FF40100000000F5138006227F00
1424
1425=== modified file 'tests/unit-tests/input/CMakeLists.txt'
1426--- tests/unit-tests/input/CMakeLists.txt 2014-10-29 06:21:10 +0000
1427+++ tests/unit-tests/input/CMakeLists.txt 2014-11-24 16:32:54 +0000
1428@@ -1,11 +1,14 @@
1429 add_subdirectory(android)
1430
1431 list(APPEND UNIT_TEST_SOURCES
1432+ ${CMAKE_CURRENT_SOURCE_DIR}/test_evdev_device_info.cpp
1433 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_filter_chain.cpp
1434 ${CMAKE_CURRENT_SOURCE_DIR}/test_display_input_region.cpp
1435 ${CMAKE_CURRENT_SOURCE_DIR}/test_cursor_controller.cpp
1436 ${CMAKE_CURRENT_SOURCE_DIR}/test_xcursor_loader.cpp
1437 ${CMAKE_CURRENT_SOURCE_DIR}/test_touchspot_controller.cpp
1438+ ${CMAKE_CURRENT_SOURCE_DIR}/test_evdev_input_device_factory.cpp
1439+ ${CMAKE_CURRENT_SOURCE_DIR}/test_libinput_device_provider.cpp
1440 )
1441
1442 set(
1443
1444=== modified file 'tests/unit-tests/input/android/CMakeLists.txt'
1445--- tests/unit-tests/input/android/CMakeLists.txt 2014-10-29 06:21:10 +0000
1446+++ tests/unit-tests/input/android/CMakeLists.txt 2014-11-24 16:32:54 +0000
1447@@ -1,6 +1,7 @@
1448 list(APPEND UNIT_TEST_SOURCES
1449 ${CMAKE_CURRENT_SOURCE_DIR}/test_event_filter_input_dispatcher_policy.cpp
1450 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_pointer_controller.cpp
1451+ ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_device_provider.cpp
1452 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_lexicon.cpp
1453 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_reader_policy.cpp
1454 ${CMAKE_CURRENT_SOURCE_DIR}/test_android_input_manager.cpp
1455
1456=== added file 'tests/unit-tests/input/android/test_android_input_device_provider.cpp'
1457--- tests/unit-tests/input/android/test_android_input_device_provider.cpp 1970-01-01 00:00:00 +0000
1458+++ tests/unit-tests/input/android/test_android_input_device_provider.cpp 2014-11-24 16:32:54 +0000
1459@@ -0,0 +1,71 @@
1460+/*
1461+ * Copyright © 2014 Canonical Ltd.
1462+ *
1463+ * This program is free software: you can redistribute it and/or modify it
1464+ * under the terms of the GNU General Public License version 3,
1465+ * as published by the Free Software Foundation.
1466+ *
1467+ * This program is distributed in the hope that it will be useful,
1468+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1469+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1470+ * GNU General Public License for more details.
1471+ *
1472+ * You should have received a copy of the GNU General Public License
1473+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1474+ *
1475+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
1476+ */
1477+
1478+#include "src/server/input/android/input_device_provider.h"
1479+#include "mir_test_doubles/stub_input_device_info.h"
1480+
1481+#include <gmock/gmock.h>
1482+#include <gtest/gtest.h>
1483+
1484+namespace mi = mir::input;
1485+namespace mia = mi::android;
1486+namespace mtd = mir::test::doubles;
1487+
1488+using AndroidStack = ::testing::TestWithParam<std::pair<uint32_t, mi::InputDeviceProvider::Priority>>;
1489+
1490+TEST_P(AndroidStack, device_probing_yields_expected_priority)
1491+{
1492+ using namespace ::testing;
1493+ mia::InputDeviceProvider provider;
1494+
1495+ auto const& param = GetParam();
1496+
1497+ EXPECT_THAT(provider.get_support(
1498+ mtd::StubInputDeviceInfo(param.first)
1499+ ), Eq(param.second));
1500+}
1501+
1502+INSTANTIATE_TEST_CASE_P(InputDeviceProviderTest,
1503+ AndroidStack,
1504+ ::testing::Values(
1505+ std::make_pair(
1506+ mi::InputDeviceInfo::touchpad,
1507+ mi::InputDeviceProvider::unsupported
1508+ ),
1509+ std::make_pair(
1510+ mi::InputDeviceInfo::touchscreen,
1511+ mi::InputDeviceProvider::best
1512+ ),
1513+ std::make_pair(
1514+ mi::InputDeviceInfo::joystick,
1515+ mi::InputDeviceProvider::supported
1516+ ),
1517+ std::make_pair(
1518+ mi::InputDeviceInfo::cursor,
1519+ mi::InputDeviceProvider::supported
1520+ ),
1521+ std::make_pair(
1522+ mi::InputDeviceInfo::keyboard,
1523+ mi::InputDeviceProvider::supported
1524+ ),
1525+ std::make_pair(
1526+ 0,
1527+ mi::InputDeviceProvider::unsupported
1528+ )
1529+ ));
1530+
1531
1532=== added file 'tests/unit-tests/input/test_evdev_device_info.cpp'
1533--- tests/unit-tests/input/test_evdev_device_info.cpp 1970-01-01 00:00:00 +0000
1534+++ tests/unit-tests/input/test_evdev_device_info.cpp 2014-11-24 16:32:54 +0000
1535@@ -0,0 +1,83 @@
1536+/*
1537+ * Copyright © 2014 Canonical Ltd.
1538+ *
1539+ * This program is free software: you can redistribute it and/or modify it
1540+ * under the terms of the GNU General Public License version 3,
1541+ * as published by the Free Software Foundation.
1542+ *
1543+ * This program is distributed in the hope that it will be useful,
1544+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1545+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1546+ * GNU General Public License for more details.
1547+ *
1548+ * You should have received a copy of the GNU General Public License
1549+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1550+ *
1551+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
1552+ */
1553+
1554+#include "src/server/input/evdev_device_info.h"
1555+#include "mir_test_framework/udev_environment.h"
1556+
1557+#include <gtest/gtest.h>
1558+
1559+#include <tuple>
1560+
1561+namespace mtf = mir_test_framework;
1562+namespace mi = mir::input;
1563+
1564+struct EvdevDeviceInfoTest : public ::testing::TestWithParam<std::tuple<char const*, char const*, uint32_t>>
1565+{
1566+ mtf::UdevEnvironment env;
1567+};
1568+
1569+TEST_P(EvdevDeviceInfoTest, evaluates_expected_input_class)
1570+{
1571+ using namespace testing;
1572+ auto const& param = GetParam();
1573+ env.add_standard_device(std::get<0>(param));
1574+ mi::EvdevDeviceInfo info(std::get<1>(param));
1575+ EXPECT_THAT(info.device_classes(),Eq(std::get<2>(param)));
1576+}
1577+
1578+INSTANTIATE_TEST_CASE_P(InputDeviceClassDetection,
1579+ EvdevDeviceInfoTest,
1580+ ::testing::Values(
1581+ std::make_tuple(
1582+ "synaptics-touchpad",
1583+ "/dev/input/event12",
1584+ mi::InputDeviceInfo::touchpad
1585+ ),
1586+ std::make_tuple(
1587+ "laptop-keyboard",
1588+ "/dev/input/event4",
1589+ mi::InputDeviceInfo::keyboard
1590+ ),
1591+ std::make_tuple(
1592+ "usb-keyboard",
1593+ "/dev/input/event14",
1594+ mi::InputDeviceInfo::keyboard
1595+ ),
1596+ std::make_tuple(
1597+ "usb-mouse",
1598+ "/dev/input/event13",
1599+ mi::InputDeviceInfo::cursor
1600+ ),
1601+ std::make_tuple(
1602+ "bluetooth-magic-trackpad",
1603+ "/dev/input/event13",
1604+ mi::InputDeviceInfo::touchpad
1605+ ),
1606+ std::make_tuple(
1607+ "mt-screen-detection", // device also reports available keys..
1608+ "/dev/input/event4",
1609+ mi::InputDeviceInfo::touchscreen|mi::InputDeviceInfo::keyboard
1610+ ),
1611+ std::make_tuple(
1612+ "joystick-detection",
1613+ "/dev/input/event13",
1614+ mi::InputDeviceInfo::joystick|mi::InputDeviceInfo::gamepad|mi::InputDeviceInfo::keyboard
1615+ )
1616+ ));
1617+
1618+
1619
1620=== added file 'tests/unit-tests/input/test_evdev_input_device_factory.cpp'
1621--- tests/unit-tests/input/test_evdev_input_device_factory.cpp 1970-01-01 00:00:00 +0000
1622+++ tests/unit-tests/input/test_evdev_input_device_factory.cpp 2014-11-24 16:32:54 +0000
1623@@ -0,0 +1,103 @@
1624+/*
1625+ * Copyright © 2014 Canonical Ltd.
1626+ *
1627+ * This program is free software: you can redistribute it and/or modify
1628+ * it under the terms of the GNU General Public License version 3 as
1629+ * published by the Free Software Foundation.
1630+ *
1631+ * This program is distributed in the hope that it will be useful,
1632+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1633+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1634+ * GNU General Public License for more details.
1635+ *
1636+ * You should have received a copy of the GNU General Public License
1637+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1638+ *
1639+ * Authored by: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
1640+ * Andreas Pokorny <andreas.pokorny@canonical.com>
1641+ */
1642+
1643+#include "src/server/input/evdev_input_device_factory.h"
1644+#include "src/server/input/input_device_info.h"
1645+#include "src/server/input/input_device_provider.h"
1646+
1647+#include "mir/input/input_device.h"
1648+
1649+#include "mir_test_doubles/stub_input_device_info.h"
1650+
1651+#include <mir_test/gmock_fixes.h>
1652+#include <gtest/gtest.h>
1653+
1654+namespace mi = mir::input;
1655+namespace mtd = mir::test::doubles;
1656+
1657+namespace
1658+{
1659+
1660+class MockInputDeviceProvider : public mi::InputDeviceProvider
1661+{
1662+public:
1663+ MOCK_CONST_METHOD1(get_support, mi::InputDeviceProvider::Priority(mi::InputDeviceInfo const&));
1664+ MOCK_CONST_METHOD1(create_device, std::unique_ptr<mi::InputDevice>(mi::InputDeviceInfo const&));
1665+};
1666+
1667+}
1668+
1669+TEST(EvdevInputDeviceFactory, probes_all_providers)
1670+{
1671+ using namespace testing;
1672+ auto a = std::make_shared<MockInputDeviceProvider>();
1673+ auto b = std::make_shared<MockInputDeviceProvider>();
1674+
1675+ EXPECT_CALL(*a, get_support(_))
1676+ .WillOnce(Return(mi::InputDeviceProvider::unsupported));
1677+ EXPECT_CALL(*b, get_support(_))
1678+ .WillOnce(Return(mi::InputDeviceProvider::unsupported));
1679+
1680+ mi::EvdevInputDeviceFactory factory({a, b});
1681+ mtd::StubInputDeviceInfo stub_dev;
1682+
1683+ factory.create_device(stub_dev);
1684+}
1685+
1686+TEST(EvdevInputDeviceFactory, creates_device_on_supported_provider)
1687+{
1688+ using namespace testing;
1689+ auto a = std::make_shared<MockInputDeviceProvider>();
1690+ auto b = std::make_shared<MockInputDeviceProvider>();
1691+
1692+ EXPECT_CALL(*a, get_support(_))
1693+ .WillOnce(Return(mi::InputDeviceProvider::unsupported));
1694+ EXPECT_CALL(*b, get_support(_))
1695+ .WillOnce(Return(mi::InputDeviceProvider::supported));
1696+ EXPECT_CALL(*b, create_device(_));
1697+
1698+ mi::EvdevInputDeviceFactory factory({a, b});
1699+ mtd::StubInputDeviceInfo stub_dev;
1700+
1701+ factory.create_device(stub_dev);
1702+}
1703+
1704+TEST(EvdevInputDeviceFactory, preferes_creating_on_better_provider)
1705+{
1706+ using namespace testing;
1707+ auto a = std::make_shared<MockInputDeviceProvider>();
1708+ auto b = std::make_shared<MockInputDeviceProvider>();
1709+
1710+ EXPECT_CALL(*a, get_support(_))
1711+ .Times(2)
1712+ .WillRepeatedly(Return(mi::InputDeviceProvider::best));
1713+ EXPECT_CALL(*b, get_support(_))
1714+ .Times(2)
1715+ .WillRepeatedly(Return(mi::InputDeviceProvider::supported));
1716+ EXPECT_CALL(*a, create_device(_))
1717+ .Times(2);
1718+
1719+ mi::EvdevInputDeviceFactory factory_one({a, b});
1720+ mi::EvdevInputDeviceFactory factory_two({b, a});
1721+ mtd::StubInputDeviceInfo stub_dev;
1722+
1723+ factory_one.create_device(stub_dev);
1724+ factory_two.create_device(stub_dev);
1725+}
1726+
1727
1728=== added file 'tests/unit-tests/input/test_libinput_device_provider.cpp'
1729--- tests/unit-tests/input/test_libinput_device_provider.cpp 1970-01-01 00:00:00 +0000
1730+++ tests/unit-tests/input/test_libinput_device_provider.cpp 2014-11-24 16:32:54 +0000
1731@@ -0,0 +1,75 @@
1732+/*
1733+ * Copyright © 2014 Canonical Ltd.
1734+ *
1735+ * This program is free software: you can redistribute it and/or modify it
1736+ * under the terms of the GNU General Public License version 3,
1737+ * as published by the Free Software Foundation.
1738+ *
1739+ * This program is distributed in the hope that it will be useful,
1740+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1741+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1742+ * GNU General Public License for more details.
1743+ *
1744+ * You should have received a copy of the GNU General Public License
1745+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1746+ *
1747+ * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
1748+ */
1749+
1750+#include "src/server/input/libinput/input_device_provider.h"
1751+
1752+#include "mir_test_doubles/stub_input_device_info.h"
1753+
1754+#include <gmock/gmock.h>
1755+#include <gtest/gtest.h>
1756+
1757+namespace mi = mir::input;
1758+namespace mili = mi::libinput;
1759+namespace mtd = mir::test::doubles;
1760+
1761+using LibInput = ::testing::TestWithParam<std::pair<uint32_t, mi::InputDeviceProvider::Priority>>;
1762+
1763+TEST_P(LibInput, device_probing_yields_expected_priority)
1764+{
1765+ using namespace ::testing;
1766+ mili::InputDeviceProvider provider;
1767+
1768+ auto const& param = GetParam();
1769+
1770+ EXPECT_THAT(provider.get_support(
1771+ mtd::StubInputDeviceInfo(param.first)
1772+ ), Eq(param.second));
1773+}
1774+
1775+INSTANTIATE_TEST_CASE_P(InputDeviceProviderTest,
1776+ LibInput,
1777+ ::testing::Values(
1778+ std::make_pair(
1779+ mi::InputDeviceInfo::touchpad,
1780+ mi::InputDeviceProvider::best
1781+ ),
1782+ std::make_pair(
1783+ mi::InputDeviceInfo::touchscreen,
1784+ mi::InputDeviceProvider::unsupported
1785+ ),
1786+ std::make_pair(
1787+ mi::InputDeviceInfo::joystick,
1788+ mi::InputDeviceProvider::unsupported
1789+ ),
1790+ std::make_pair(
1791+ mi::InputDeviceInfo::gamepad,
1792+ mi::InputDeviceProvider::unsupported
1793+ ),
1794+ std::make_pair(
1795+ mi::InputDeviceInfo::cursor,
1796+ mi::InputDeviceProvider::supported
1797+ ),
1798+ std::make_pair(
1799+ mi::InputDeviceInfo::keyboard,
1800+ mi::InputDeviceProvider::supported
1801+ ),
1802+ std::make_pair(
1803+ 0,
1804+ mi::InputDeviceProvider::unsupported
1805+ )
1806+ ));

Subscribers

People subscribed via source and target branches