| # mist: Modem Interface Switching Tool | |
| ## Overview | |
| `mist` is a Chromium OS utility for switching USB cellular dongles into the | |
| modem mode. A cellular dongle may implement multiple functions and the function | |
| exposed by its initial USB configuration may not be a modem. We need to switch | |
| the device into a modem before it can be detected and managed by | |
| [ModemManager](https://www.freedesktop.org/wiki/Software/ModemManager) to | |
| provide cellular connectivity. | |
| `mist` is activated by udev events. When udev detects a supported dongle, it | |
| invokes `mist` to switch the dongle into the modem mode. The mode switching | |
| operation invokes the following: | |
| - Open the USB device associated with the dongle. If the device has a USB | |
| configuration that exposes a MBIM interface, select that configuration and | |
| complete the switch operation. Otherwise, find and claim the mass storage | |
| interface of the device. | |
| - Initiate a bulk output transfer of a (or multiple) special USB message(s) to | |
| the mass storage endpoint of the device. | |
| - On some devices, a bulk input transfer from the mass storage endpoint of the | |
| device is expected after completing each bulk output transfer. | |
| - Once the transfer of the last message completes, the device is expected to | |
| disconnect from the USB bus and then reconnect to the bus after it has been | |
| switched to the modem mode. The device may change its USB vendor ID and | |
| product ID (mostly the latter) after the switch operation. | |
| ## Device Detection | |
| `mist` relies on udev to detect when a dongle is plugged into the system. A | |
| udev rules file, [`/lib/udev/rules.d/51-mist.rules`](51-mist.rules), is used to | |
| identify a supported dongle based on its USB vendor ID and product ID before | |
| and after mode switching. Upon detecting a supported dongle in the non-modem | |
| mode, udev launches a mist process to switch the dongle into modem, and also | |
| tags the dongle as `MIST_SUPPORTED_DEVICE=1`, which allows cros-disks to | |
| filter out the mass storage exposed by the dongle. | |
| After udev launches the `mist` process, `mist` daemonizes itself so that it can | |
| use libudev to monitor the status of the mode switching via udev events. After | |
| the special USB messages are sent to the mass storage interface of the dongle, | |
| the dongle detaches itself from USB, which results in a udev remove event. | |
| After the dongle switches into the modem mode, it reattaches to USB, which | |
| results in a udev add event. | |
| ## Configuration File | |
| `mist` uses a protobuf-based configuration file, | |
| [`/usr/share/mist/default.conf`](default.conf), to specify information about | |
| the supported dongles. The configuration file specifies a list of supported | |
| dongles and the following information associated with each dongle: | |
| - Initial USB vendor and product ID of the modem when it is in the mass storage | |
| mode. | |
| - A list of possible final USB vendor and product IDs of the modem after it has | |
| switched to the modem mode. | |
| - A list of USB messages, in form of hexadecimal strings, to send to the mass | |
| storage interface of the modem in order to switch the modem to the modem | |
| mode. | |
| - An optional flag to indicate whether a response is expected from the mass | |
| storage interface after sending each USB message to the interface. | |
| - An optional initial delay, in milliseconds, that mist should wait before | |
| starting the modem switch operation. | |
| ## USB Communications | |
| `mist` uses libusb 1.x API to retrieve the USB descriptors of the dongle and | |
| initiate bulk transfers to the mass storage interface of the dongle. It thus | |
| needs to have read and write access to the USB device associated with the | |
| dongle. |