USB_MODED use and API description/overview.
==========================================

Usb_moded is a relatively simple daemon which tracks the
usb cable connection status and activates a certain USB
profile based on that.
To do this it has a number of built in common profiles, 
an optional application launcher (app_sync) and configurable
dynamic modes.

All the system wide communication goes over the DBus system bus,
while application launching is handled on the session bus.
Thus if you need this functionality, usb_moded needs to be started 
with the session. 
(functionality not verified yet on multi-user setups. See TODO)

Usb cable detection is handled with udev, it even tries to guess
which is the correct power_supply entry to use. 

A Qt lib to interact with usb-moded is available here: 
https://git.merproject.org/mer-core/libusb-moded-qt

Starting usb_moded
-------------------

Simply start with usb_moded.
usb_moded --help will give you more details

Status and configuration query/setting
---------------------------------------

The current status can be queried any time over DBus. From a program
using a method call or using dbus-send.

dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.mode_request

Similary a mode can be set.

dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.set_mode string:'<mode_name>'

Even the configuration can be set over DBus

dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.set_config string:'<mode_name>'

To get the currently stored default mode from the config:

dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.get_config

The supported modes can be queried over dbus as follows:

dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.get_modes

Usb_moded will also broadcast changes and errors over the system bus.
This will happen on the com.meego.usb_moded interface

For regular signals: sig_usb_state_ind
And errors: sig_usb_state_error_ind

More info and details in usb_moded-dbus.h

Main configuration file
------------------------

There is also a configuration file and some configuration directories under /etc/usb-moded
The main config file is /etc/usb-moded/usb-moded.ini . This file will be auto-generated if 
it is not there (default profile will be developer_mode). Also it will be regenerated if some
extra config file gets dropped into the /etc/usb-moded/ directory. This way you can easily 
add extra hw/configuration dependent information in there.

Most common use case would be passing the udev information for the power supply tracking entry,
as in some cases it is not /sys/class/power_supply/usb

This is also known as config file merging (see further)

The most imporant entry is the power_supply, or iow the place in sysfs where usb_moded can
read the cable connection status and type. For example on the N900 

[udev]
path = /sys/class/power_supply/isp1704

Without this information usb_moded will not run and exit.

In case nothing is specified and it is not the typical path it will try to guess.
This might not always work. There is the source of a utility in the tree udev-search.c
under utils, that will give you an idea of what paths usb-moded might be choosing. It always
takes the one with the highest score.

There are the mountpoints, this defines which device/filesystem entry should be 
exported over mass-storage (this ideally also has an entry in /etc/fstab). You can add more 
filesystems to the mount option, by making it a comma-seperated list in case there are 
several exports (like internal mmc and sd card for example)

[mountpoints]
mount = /dev/mmcblk0p1

The following option plays with certain sync options that exist and have to be set per
fs and thus cannot be handled by setting them in /etc/modprobe.d/....conf

[sync]
nofua = 1

This mount is the alternative mountpoint for in case something goes wrong. Usb_moded
will mount a 512 RO tmpfs on that location to mitigate potential disasters on the system,
and make clear to programs on the device that something is wrong with the fs they want to use.

[altmount]
mount = /home/user/MyDocs

Also the default usb mode can be configured there. For example:

[usbmode]
mode = ask
mode_100001 = charging

This says that default mode for user with uid 100001 is charging and other users default to mode ask.
Modes with uid are only used when built with --enable-sailfish-access-control and
only users with uid higher than 100000 and lower or equal to 999999 can have user specific usb modes.

The other settings and config dirs will be handled later in the appsync and dynamic modes part.
(This is optional and can be compiled out)

There is also an optional network configuration. 

Certain parts of this config will override the settingsset in the dynamic mode configuration, like for example interface! 
The default ip set for usb networking is 192.168.2.15 (for Meego/Nemo/SailfishOS). However this can be configured by 
hand in the ini file also (optionally in a separate ini file which is possible due to config file merging).

For example:

[network]
ip = 10.0.0.2
interface = usb1
gateway = 10.0.0.1

By default usb0 will be used, so no need to fill it in if not needed. The gateway setting is also optional
and will not be set if there is no value filled in.
If the ip is set to dhcp, usb_moded will try to use dhcp to configure the network (requires dhclient or udhcpc atm)

The network configuration can also be set with dbus method calls via the net_config method.
This requires two strings as arguments. Supported are: ip, interface and gateway

for exmaple:

dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.net_config string:'ip' string:'192.168.2.15'

Usb_moded will generate a random mac address for the g_ether driver. Thus when plugging in the device repeatedly the mac address will not
change and udev rules / network manager etc will not think it is a new device each time.
This mac is stored using the default modprobe configuration and thus will be in /etc/modprobe.d/g_ether.conf
If this file exits usb_moded will assume there is a default mac set and will not do anything.

It is possible to set the configuration on the kernel command line also. For this the format of regular ip setting from the kernel is
being re-used. 

The format followed is:
usb_moded_ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>

For more info see the kernel source: Documentation/filesystems/nfs/nfsroot.txt

for example : usb_moded_ip=192.168.3.100::192.168.3.1:255.255.255.0::usb0:off

NOTE: The device must be usb0! The autoconf value is ignored.

Ip forwarding or nat can also be set up by usb_moded. This is in case you want to use an interface
on the device to route traffic coming from your pc/laptop. The best use case example would be connecting
to the internet over USB using the data connection of your smartphone. This does not work the other way round!

To enable this you need to add the following lines to your network config (the example expects rmnet0 to be
your internet facing interface on the device). 

nat_interface = rmnet0

When nat=1 is given in the mode configuration this will be used to enable nat on that interface.
This is a bit complicated but related to the fact that the nat interface is usually the same on a device, 
but not all usb network related profiles might want it enabled.

If you want the device to load a dhcp server you need to configure this in the mode config, just like nat. (see lower)

USB moded supports access control of dynamic modes when built with --enable-sailfish-access-control.
Modes are allowed and denied based on the user of the process accessing the D-Bus API.
By default dynamic modes are allowed for users in sailfish-system but the group can be overridden in configuration.

For example:

[mode_group]
mtp_mode = users
developer_mode = developers

This allows mode called mtp_mode to users in "users" group and mode called developer_mode for users in "developers" group.
Users group includes all regular users which is less restrictive than the default.
Note that if the group doesn't exist access is denied.

Functional overview
--------------------

When a usb cable is insertion is detected usb_moded will start to act.
First it will warn on the system bus that a cable is connected. 
Then it will check what the configuration setting is. Thus it knows how to act.
If it is a known configured mode it will load the correct modules (after checking 
what is loaded and clean up if needed), perform other needed operations and
make sure the chosen mode works. At this point it will broadcast which mode 
is set to warn other programs.
If things fail it will go to undefined state (and also broadcast this).

There is the special case where the config option is called "ask". In this
case usb_moded will enable a fake mass_storage profile to enable enumeration 
so charging can be done, and wait until it is instructed which mode needs
to be selected. Thus this state can be used for an UI that will set the right
mode on user interaction. For this purpose usb_moded broadcasts it goes in ask
mode, and also stays in ask mode until a chosen mode is requested or the cable
is disconnected. This also avoids race conditions in case the  UI starts
after a cable is inserted and usb_moded has also been started. The UI can then 
query the state to know if it needs to show a selection dialog or not.

On cable disconnect usb_moded will broadcast a disconnect signal, so that all programs
that use the usb interface/mode know that a cable is disconnected and then can act
(if needed) on the changed situation. It will then do all the necessary to reset
the system to a clean state.

Another special feature is the dedicated charger tracking. When a charger is connected
usb_moded will broadcast a charger_connected signal and go to "dedicated charger" mode.
This is just a place-holder mode. On charger disconnect then there will be a 
charger_disconnected signal.

Appsync feature
---------------

In case you need some program to be started along some mode the appsync option 
provides this option.
Only condition is that it can be activated by dbus and that (preferably) it will
notify usb_moded that it is ready by ready_method call on the session bus.
This ready method call is just calling the regular usb_moded interface, but now
on the session bus, with as argument the program name as defined in the config file.
Systemd is also supported.

To achieve this you need to have a config file in /etc/usb-moded/run.
Best practice would be giving it a descriptive name followed by .ini

For example:
/etc/usb-moded/run/foo.ini

Where foo.ini would be for dbus:
[info]
name = foo
mode = foo_mode
launch = com.meego.foo

For systemd it would be as follows:
[info]
name = foo.service
mode = foo_mode
systemd = 1

The name here is the service name used when launching it for example with systemctl

Those files will be read on start and usb_moded will keep a list of apps to launch 
for a certain mode. This also means that if you change the files or add/remove some
you need to restart usb_moded. Later when the mode is activated, usb_moded will start 
each of them after the module has been loaded and keep track if they have been started.
It will warn you if that failed.

These services will start before the whole setup for the usb is done. In case the application
only works after everything has been set up, you can start the application at the end by adding
post = 1 to configuration.

Dynamic modes
-------------

Apart from ask and charging_only modes, all modes for usb_moded are defined
within configuration files. These are to be defined with an ini file alsoi, but this time in 
/etc/usb-moded/dyn-modes.

The format would be for example for : /etc/usb-moded/dyn-modes/dyn-mode-1.ini

[mode]
name = dyn-mode-1
module = dyn-mode-module
appsync = 1
network = 1
network_interface = usb0

[options]
sysfs_path = /* in case you need to echo parameters somewhere in a sysfs path */
sysfs_value = /* the values */
sysfs_reset_value = /* in case a reset value needs to be written */

Only the mode name and module are mandatory. In case you do not use modules, use none as the value 
for module (as for the android gadget for example. See the android section for more info)

If appsync or network is not defined, or explicitly set to 0, it will not be used.
To use the mass_storage functions you need to define mass_storage = 1. The needed info for
mass_storage data need to be defined in the config file. (other approaches are possible so this is not
mandatory for all kinds of mass_storage support)

To enable nat, you need to set nat = 1 and configure the nat_interface in the network settings.

To have dhcp server functionality on the device, set dhcp_server = 1. This will use udhcpd.
It also uses the default network address or whatever has been configured and sets up a corresponding dhcp
configuration. This way the device is always available on the same address.

Both NAT and dhcp server need a corresponding service that can be started by usb_moded. (see Appsyn feature)

Trigger support
---------------

This will only work if udev is configured as it is a udev trigger.
Atm only one trigger is supported.
This is to support special equipment that will send a trigger event.
Usually this will be in combination with a dynamic mode.

You need to add the following to usb-moded.ini to get a trigger activated

For example

[trigger]
path = /sys/devices/platform/musb_hdrc
udev_subsystem = platform
mode = mass_storage
property = TRIGGER_CMD

Android gadget driver support
-----------------------------

A number of configurations are already supported out of the box for android. They
just need to be installed in the right spot to work.

In the main configuration file a few extras can be configured for all modes.

An android extra section in the main configuration file would look like this:

[android]
iManufacturer = foo-factory
idVendor = 0666 /* this is the vendor id code in hex */
iProduct = awesome-device
idProduct = 0001 /* If you decide to use one Product id for all the supported modes. Not recommended if you will connect it to Windows machines */

A mode configuration would look like this: 

[mode]
name = developer_mode
module = none
network = 1
network_interface = rndis0

[options]
# sysfs_value = comma separated list of functions to enable in this mode
sysfs_value = rndis
idProduct = 0002


Android portability
---------------------

On some android kernels cable detection/charging etc is broken unless the gadget is active.
Often this is weirdly done on purpose by checking if the gadget is active before doing anything.
This is not recommend and is actually wrong. Not to mention all the potential issues this could cause.
(extra power drain, suspend issues, accidental exposure of data over USB, ...)

For this purpose there is the -a switch that activates by default the charging mode, and will set it
on disconnect. So technically unless you connect and set some mode, the gadget will always be active
in the fake mass-storage charging mode.

WARNING: This could potentially expose data over mass-storage (TODO, make sure this does not happen)

rescue mode
-----------

When started with -r usb_moded will always enable developer mode (networking)
if it can. This is a debug feature and should not be used in production software.

Turning it off when the device is booted completely can easily be done over dbus.

dbus-send --system --type=method_call --print-reply --dest=com.meego.usb_moded /com/meego/usb_moded com.meego.usb_moded.rescue_off

config files and config file merging
------------------------------------

The main config file for usb_moded is /etc/usb-moded/usb-moded.ini

If this does not exist usb_moded will create one for you, which will default
to setting up a default network with ip 192.168.2.15 and uses the g_ether module.

The different sections of the config file can be split out in different ini files 
(they thus need to end in .ini or they will not be considered as valid). However take into 
account usb_moded will need to be restarted to merge these in a new usb-moded.ini file. 
As usb_moded will only then check if new files were added to the /etc/usb-moded
directory and refresh the main ini file as needed on start-up.

diagnostic mode
---------------

Usb-moded supports a diagnostic mode. This requires a special command line parameter (-d).
One mode should be configured in /etc/usb-moded/diag and this will be automatically used.
This is a feature to allow for "hidden" or non-standard modes that are only of use for 
testing/QA.

USB tethering
-------------

Usb_moded can set up USB tethering. In the sense that it can share the connection of your device to a second one.
Most common use case would be using USB tethering from a phone to a laptop.

When compiled with ofono and connman support you can make the most of this. ofono can be used to detect roaming status.
Connman for getting dns settings and interface from the modem connection.
However it works also without it. It can be configured so that it knows what the interfaces are and get the dns info 
from /etc/resolv.conf.

For this are the 

#define NETWORK_NAT_INTERFACE_KEY       "nat_interface"
#define NO_ROAMING_KEY                  "noroaming"

Network options. nat_interface documents which interfaces the internet facing modem. noroaming when set to 1
will prohibit enabling the modem interface in case you are roaming (this requires ofono). 


hidden modes
------------

Sometimes it is useful to hide modes from the ui (the mode can be queried through dbus).
To hide modes this can be done by adding a hide= key to the
[usbmode] section. If you want to hide more modes this needs
to be a comma separated list.

For example
[usbmode]
hide=developer_mode,bastard_mode

Modes can also be set and removed through dbus (one mode at a time)
See usb_moded_util (-v, -i and -u)
