Enabling input (sensor) access for ARM devices

Registered by Bryce Harrington on 2012-10-24

Enable various input drivers to provide sensor access on ARM devices (tablets and phones). This includes the following:

    - camera [PRIORITY]
    - wifi [PRIORITY] works
    - bluetooth [PRIORITY] works
    - touch [PRIORITY] works (single touch)
    - accelerometer
    - GPS
    - compass
    - NFC
    - Telephony

Blueprint information

Not started
Jason Warner
Bryce Harrington
Series goal:
Accepted for raring
Milestone target:
milestone icon ubuntu-13.04-beta-1

Related branches



2012-11-26 bryce: With the bug fixes from last Friday, rotation appears to be working well now. Remaining tasks related to hooking up gnome to the rotation sensor.

= IIO Overview =
IIO is a generic bus tailored towards (buffered) ADC devices, i. e. mostly sensors. They turn up in /sys/bus/iio/devices/ with info, and have an associated /dev/iio:deviceN char device for reading the data. Technically it is totally unrelated to input/evdev; you basically get a stream of sensor data at a configured sampling rate, and can configure certain triggers through sysfs.


= IIO on the Nexus 7 =
The nexus7 has two (recognized) IIO devices:
 - MPU 6050 gyroscope and accellerometer (http://www.invensense.com/mems/gyro/mpu6050.html)
 - AMI 306 magnetic compass (http://www.aichi-steel.co.jp/ENGLISH/pro_info/pro_intro/elect_3.html)

There is some code for interfacing with the MPU 6050 at http://www.i2cdevlib.com/devices/mpu6050, but it is not self-contained but builds on top of an "Arduino" development environment. For basic operation, you can enable the buffer for a (set of) sensor(s), and read the raw data:

$ echo 1 | sudo tee scan_elements/in_accel_x_en
$ echo 100 | sudo tee buffer/length
$ echo 1 | sudo tee buffer/enable # start capturing
[ wait a second]
$ echo 0 | sudo tee buffer/enable # stop capturing
$ sudo hd /dev/iio:device0

= Emulating evdev events =
If an userspace driver wants to "translate" IIO measurements, or synthesize any kind of input event into evdev events, it can use the "uinput" driver (/dev/uinput) to create an arbitrary synthetic evdev device and then send events to it. See http://thiemonge.org/getting-started-with-uinput for details. For some first experiments, or for writing test suites you can use python-evdev which has rather convenient uinput bindings (but that shouldn't be used in production of course, as the overhead of Python is prohibitive for this kind of application): http://gvalkov.github.com/python-evdev/

= Sensor Bugs =

= Ambient light sensor and screen brightness =

== Light sensor ==

The AL3010 light sensor is controlled by the hwmon driver of the same name. It can be used to automatically adjust screen brightness to accommodate ambient lighting conditions.

The driver exposes a set of sysfs attributes, show_lux being the most relevant

$cd /sys/bus/i2c/drivers/al3010/2-001c

(this ranges from 0 to ~40000 in my tests using the latest Raring kernel based on the Android 4.2.1 one)
$cat show_lux

The driver also provides a char device named /dev/lightsensor but this seems to have only been used for stress testing and debugging - an ioctl call schedules a periodic read of the ADC that would print it to the kernel log).

== Screen backlight ==

The kernel provides a standard pwm_backlight interface in sysfs under

$cat actual_brightness

10 and 255 seem to be the dimmest and brightest values that can be set.
#echo 10 >brightness
#echo 255 >brightness
Completely turning off the screen via this knob only does not seem to work on Ubuntu.
On Android 4.2.1 however writing 0 to brightness turns the screen off - there may be an additional system components that monitors these sysfs attributes that shuts down the screen.

Either a dedicated daemon or better yet one of the existing settings/desktop helper daemons would need to get the ambient light sensor and screen backlight correlated.
Currently xrandr can be used to turn the screen off and on.
$xrandr --output LVDS-1 --off
$xrandr --output LVDS-1 --auto

== GPS ==

Probably need some kind of kick from brcm_patchram, much like bluetooth
Should try to run gpsd to see what gets detected, and seeing if glgps from Android has reusable code to get the hardware supported.

== NFC ==
/dev/pn544. Isn't supported by libnfc, nor other nfc libraries I could find. (cyphermox) libnfc has support for similar devices and there is some code in Android source to handle the device, so the proper support in libnfc can probably be derived from all that.

= Test app =
I made a test app in Go to play around with the formulas for backlight and accelerometer readings .
It could probably be made into a shell script of about the same size - maybe expand the existing xrotate helper - but I wanted to see what a Go long running app's memory footprint would be. It is ~1.5M so not too lean TBH.

Install the golang package and go build nexus.go then sudo ./nexus (it needs admin rights to change backlight for now)
Alternately just save this prebuilt binary and run it http://people.canonical.com/~jani/a


Work Items

Work items:
[achiang] tag nexus 7 bugs with 'sensors': DONE
[achiang] Jot down (in Nexus7 wiki) a list of what existing userspace libraries exist for each of the sensors: POSTPONED
[pitti] understand difference between IIO and evdev: DONE
[pitti] investigate how to emulate evdev events: DONE
[sil2100] write unity tests that check that XRandR rotation events configure the desktop accordingly: TODO
[jani] fix camera driver (in talks with Nvidia who are working on this): TODO
[achiang] create wifi bug and assign: DONE
[bryce] driver level work in rotation bugs: DONE
[jani] understand where accelerometer is exposing data: DONE
[cyphermox] GPS investigation: INPROGRESS
[cyphermox] NFC investigation: POSTPONED
[jani] investigate ambient light sensor: DONE

Dependency tree

* Blueprints in grey have been implemented.