Кастомные интерфейсы в Офоно или как помяукать модемом

Всем хорош Sailfish, но что делать, если Вам захочется помяукать модемом?
Кастомные интерфейсы в Офоно или как помяукать модемом

Ладно, далее, в этой статье, я расскажу как создать плагин для офоно, в нём создать кастомный dbus интерфейс и покажу как обрабатывать входные данные, добро пожаловать под кат.

Итак, сразу начнём всё по взрослому, как в настоящем плагине! Да чтобы с конфигурацией и пакетами! Весь код будет располагаться тут https://github.com/neochapay/ofono-example-plugin и разбит коммитами по частям этой статьи. Так что приступаем!

Часть первая: Всё по взрослому!

Мы работаем с коммитом с хешем f6a8a2424987aad9d864be099161e61a3684d7e5 он же первый коммит
Кастомные интерфейсы в Офоно или как помяукать модемом

Для создания Makefile и последующей сборки мы будем использовать automake. Почему? Потому что я стар и видел смерти и рождения галактик вот почему!
Для начала создаём папку ofono-example-plugin в котором создаём папки rpm и src. По названию можно понят, что в rpm будут файлы, относящиеся к пакетированию, а в src собственно исходники нашего плагина.
В rpm кладём файл следующего содержания:
Код SPEC:
  1. Name: ofono-example-plugin
  2. Version: 0.0.1
  3. Release: 1
  4. Summary: Ofono example plugin
  5. Group: Development/Libraries
  6. License: BSD
  7. URL: https://github.com/neochapay/ofono-example-plugin
  8. Source: %{name}-%{version}.tar.bz2
  9.  
  10. Requires: ofono
  11. BuildRequires: ofono-devel
  12.  
  13. %description
  14. Implements some examples for ofono plugin
  15.  
  16. %prep
  17. %setup -q -n %{name}-%{version}
  18.  
  19. %build
  20. ./autogen.sh
  21. %configure
  22. make %{_smp_mflags}
  23.  
  24. %install
  25. rm -rf %{buildroot}
  26. %make_install
  27. #libtool don't like lib without version
  28. rm %{buildroot}/usr/lib/ofono/plugins/exampleplugin.so.0
  29. rm %{buildroot}/usr/lib/ofono/plugins/exampleplugin.so
  30. mv %{buildroot}/usr/lib/ofono/plugins/exampleplugin.so.0.0.0 %{buildroot}/usr/lib/ofono/plugins/exampleplugin.so
  31.  
  32. %files
  33. %defattr(-,root,root,-)
  34. %{_libdir}/ofono/plugins/exampleplugin.so
Если Вы собирали когда либо RPM файлы - Вам всё понятно, за исключением одной мелочи, о которой позже. Если же нет, то стоит сперва почитать о создании rpm из исходников, но в этой статье, я решил, что всё уже всё знают. О странном коде в секции install: я так и не понял, как сказать libtool создать библиотеку без версионирования - поэтому, всё, что не нужно удаляем и переносим с нужным именем.

Далее нам понадобятся файлы AUTHORS ChangeLog README NEWS значение которых, я думаю понятно по их названию. Я их оставил пустыми, потому что вот почему.

Далее нам понадобится autogen.sh - файл, который вызывает различные утилиты и формирует нам ./configure и Makefile. У меня он до боли прост:
Код BASH:
  1. #!/bin/sh
  2. autoreconf --install --force
Да вот так всё просто smile

Далее нам нужен файл configure.ac из которого уже получится необходимый нам ./configure
Код AUTOCONF:
  1. AC_INIT([example-plugin], [0,1])
  2. AC_CONFIG_SRCDIR(src/example-plugin.c)
  3. AM_INIT_AUTOMAKE
  4. AC_PROG_CC
  5. AC_PROG_INSTALL
  6. AC_PROG_LIBTOOL
  7. AC_ENABLE_SHARED
  8. AC_DISABLE_STATIC
  9. libdir=/usr/lib/ofono/plugins
  10. AC_OUTPUT(Makefile src/Makefile)
Разберём его построчно:
1 - инициализация autoconf - объявляем название библиотеки и её версию
2 - говорим, где у нас исходники
3 - говорим, что будем собирать automake
4 - говорим, что мы используем C
5 - говорим, что нам нужна будет утилита install
6 - говорим, что мы собираем shared библиотеку
7 - говорим, что мы не собираем static библиотеку
8 - обявляем переменную, где у нас хранятся плагины ofono
9 - говорим, что нам нужно на выходе.

Далее, для формирования Makefile нам нужны Makefile.am файлы, аж 2 штуки - одна в корне исходников:
Код AUTOMAKE:
  1. SUBDIRS = src
Он нам просто говорит, что смотри в папку src не отвлекайся. А вот в папке src Makefile.am будет чуть сложнее:
Код AUTOMAKE:
  1. lib_LTLIBRARIES = exampleplugin.la
  2. exampleplugin_la_LDFLAGS=-module -lglibutil -lglib-2.0 -lgobject-2.0
  3. exampleplugin_la_SOURCES = example-plugin.c
Опять таки, разберём по строчкам:
1 - говорим, что собираем библиотеку с именем examplepulgin
2 - сообщаем файлы линковки
3 - сообщаем, где лежат исходники самой библиотеки

И тут ты спросишь: "А где собственно плагин то?"
Кастомные интерфейсы в Офоно или как помяукать модемом

Ну всё до этого, было подготовкой, теперь встречайте сам код плагина
Код C:
  1. define OFONO_API_SUBJECT_TO_CHANGE
  2. #include <ofono/plugin.h>
  3. #include <ofono/log.h>
  4.  
  5. #Функция при старте
  6. static int example_plugin_init()
  7. {
  8. ofono_info("Hello example ofono plugin.");
  9. return 0;
  10. }
  11.  
  12. #Функция при выходе
  13. static void example_plugin_exit()
  14. {
  15. ofono_info("Bye bye example ofono plugin");
  16. }
  17.  
  18. #обозночаем плагин
  19. OFONO_PLUGIN_DEFINE(example, "example plugin",
  20. OFONO_VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
  21. example_plugin_init, example_plugin_exit)
  22.  
Код, достаточно простой, для понимания за исключением макроса OFONO_PLUGIN_DEFINE
у него входные параметры:
Названия плагина
Описание плагина
Версия ofono, для которого он был создан
Приоритет запуска - у нас стандартный
Функция вызываемая при инициализации
Функция вызываемая при завершении

Теперь можно собрать пакет, установить его на свой телефон и при запуске ofono увидеть строчку "Hello example ofono plugin.", а при остановке "Bye bye example ofono plugin"
Кастомные интерфейсы в Офоно или как помяукать модемом

Часть 2: Пытаемся поговорить

Но просто включаться и выключаться нам не очень то и интересно, хочется и поговорить с плагином, чтобы он нам отвечал на наши просьбы и мольбы - для этого ofono использует DBUS. Что это за монстр, я не буду рассказывать в рамках этой статьи, но попробуем в данной части зарегистрировать наш кастомный интерфейс.
Используем тот же репозиторий, но коммит 43fec818746984d90265911ced75b131d0cf78ef Кому лень читать, а сразу посмотреть изменения, то смотрим тут: https://github.com/neochapay/ofono-example-plugin/commit/43fec818746984d90265911ced75b131d0cf78ef

Первое, что нам понадобится - добавить в configure.ac опрос системы, на наличие библиотек dbus glib dbus-glib - делается это так:

Код AUTOCONF:
  1. PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, dummy=yes,
  2. AC_MSG_ERROR(D-Bus >= 1.4 is required))
  3. AC_SUBST(DBUS_CFLAGS)
  4. AC_SUBST(DBUS_LIBS)
Для поиска библиотек нам поможет pkgconfig, который нам подскажет есть ли библиотеки нужной нам версии и добавит нам флаги компиляции (DBUS_CFLAGS) и флаги линковки(DBUS_LIBS) которые понадобятся нам при сборке нашего плагина.

Так же добавляем для glib и dbus-glib
Код AUTOCONF:
  1. PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.32, dummy=yes,
  2. AC_MSG_ERROR(GLib >= 2.32 is required))
  3. AC_SUBST(GLIB_CFLAGS)
  4. AC_SUBST(GLIB_LIBS)
  5.  
  6. PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1, dummy=yes,
  7. AC_MSG_ERROR(dbus-glib is required))
  8. AC_SUBST(DBUS_GLIB_CFLAGS)
  9. AC_SUBST(DBUS_GLIB_LIBS)
Чтобы эти флаги применялись при компиляции, добавим в src/Makefile.am некоторые изменения:
Строчку
Код AUTOMAKE:
  1. exampleplugin_la_LDFLAGS=-module -lglibutil -lglib-2.0 -lgobject-2.0
Меняем на
Код AUTOMAKE:
  1. exampleplugin_la_LDFLAGS=-module @GLIB_LIBS@ @DBUS_GLIB_LIBS@
И добавляем строку
Код AUTOMAKE:
  1. exampleplugin_la_CFLAGS=@DBUS_CFLAGS@ @GLIB_CFLAGS@ @DBUS_GLIB_CFLAGS@
Думаю понятно, откуда взялись переменные и зачем. Если нет - спрашивай в комментариях.
Теперь нам нужно создать 2 файлика: src/dbus-iface.c и src/dbus-iface.h , где собственно и будет реализация создания интерфейса dbus для нашего плагина.

В src/dbus-iface.h объявляем 2 функции - создание и удаление интерфейса
Код C:
  1. #ifndef DBUS_EXAMPLE_H
  2. #define DBUS_EXAMPLE_H
  3. static int register_example_dbus();
  4. static void free_example_dbus();
  5. #endif
register_example_dbus будет нам возвращать 1 если зарегистрировал интерфейс и нолик если нет. Напишем его реализацию в src/dbus-iface.c

Код C:
  1. /*Подключаем необходимые заголовки*/
  2. #include <ofono/dbus.h>
  3. #include <ofono/gdbus.h>
  4. //Определяем где у нас будет интерфейс
  5. #define EXAMPLE_DBUS_INTERFACE "org.nemomobile.ofono.Example"
  6.  
  7. //Болванки, которые нам понадобятся позже
  8. static const GDBusMethodTable example_dbus_methods[] = {};
  9. static const GDBusSignalTable example_dbus_signals[] = {};
  10.  
  11. //Регистрируем интерфейс
  12. int register_example_dbus() {
  13. //Вызываем главный интерфейс dbus ofono - мы же всё же плагин, а не отдельное приложение
  14. DBusConnection *connection = dbus_connection_ref(ofono_dbus_get_connection());
  15.  
  16. /*
  17. connection - наш основной интерфейс ofono
  18. /Example - путь отосительно которого мы коннектимся. Должен быть уникальным
  19. EXAMPLE_DBUS_INTERFACE - наш личный плагиновый интерфейс
  20. example_dbus_methods - методы, которые мы представляем
  21. example_dbus_signals - сигналы, которые мы можем слать
  22. */
  23. if (g_dbus_register_interface(connection, "/Example",
  24. EXAMPLE_DBUS_INTERFACE,
  25. example_dbus_methods,
  26. example_dbus_signals,
  27. NULL, NULL, NULL)) {
  28. // Если соединение проходит возвращаем 1
  29. return 1;
  30. }
  31. //Если нет - то возвращаем ноль
  32. return 0;
  33. }
  34. //А это домашнее задание - написать код освобождения интерфейса
  35. void free_example_dbus() {
  36. }
Прописываем вызовы при создании и удалении интерфейса в src/example-plugin.c
Теперь он будет выглядеть так:
Код C:
  1.  
  2. #define OFONO_API_SUBJECT_TO_CHANGE
  3. #include <ofono/plugin.h>
  4. #include <ofono/log.h>
  5.  
  6. #include "dbus-iface.h"
  7.  
  8. static int example_plugin_init()
  9. {
  10. ofono_info("Hello example ofono plugin.");
  11. if(register_example_dbus() != 0) {
  12. ofono_info("Register example dbus interface.");
  13. } else {
  14. ofono_warn("Fail register dbus interface.");
  15. }
  16. return 0;
  17. }
  18.  
  19. static void example_plugin_exit()
  20. {
  21. free_example_dbus();
  22. ofono_info("Bye bye example ofono plugin");
  23. }
  24.  
  25. OFONO_PLUGIN_DEFINE(example, "example plugin",
  26. OFONO_VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT,
  27. example_plugin_init, example_plugin_exit)
Собираем, устанавливаем и в консоли от рута запускаем
Код BASH:
  1. dbus-send --system --print-reply --dest=org.ofono / org.freedesktop.DBus.Introspectable.Introspect
Ура у нас появился интерфейс! Мы можем к нему обратится! Но как? Увы у нас нет методов.
Кастомные интерфейсы в Офоно или как помяукать модемом

Ну котикам грустить не стоит! Давайте в следующей части создадим интерфейсы и поговорим с ними через dbus!

Часть 3: Продолжаем пытаться говорить

Далее мы будем работать с коммитом da495d6b068a4522cdfcf6ecd21f55e817a5e92b . Изменения смотреть тут : https://github.com/neochapay/ofono-example-plugin/commit/da495d6b068a4522cdfcf6ecd21f55e817a5e92b
Кастомные интерфейсы в Офоно или как помяукать модемом

Для начала, в файле src/dbus-iface.c создадим функцию example_meow
Код C:
  1. static DBusMessage *example_meow(DBusConnection *conn, DBusMessage *msg, void *data) {
  2. ofono_info("Some cat say meow!");
  3. return dbus_message_new_method_return(msg);
  4. }
При вызове которой в логе ofono будет отображаться сообщение "Some cat say meow!" далее, добавим эту функцию в нашу таблицу методов, теперь он будет выглядеть так:
Код C:
  1. static const GDBusMethodTable example_dbus_methods[] = {
  2. { GDBUS_METHOD("SayMeow", GDBUS_ARGS({"path", "s"}), NULL, example_meow) },
  3. { }
  4. };
Метод зовётся SayMeow и принимает параметр "s" - string и при его вызове запускается функция example_meow.
Собираем, и прочее и при вызове в консоли от рута
Код BASH:
  1. dbus-send --system --print-reply --dest=org.ofono /Example org.nemomobile.ofono.Example.SayMeow string:""
Мы получим в логе офоно сообщение "Some cat say meow!"
Кастомные интерфейсы в Офоно или как помяукать модемом

А что, если нам нужно, чтобы котик не только мяукал например, а мурчал? Добро пожаловать в следующую часть.
Комментарии (0)

Нет комментариев. Ваш будет первым!

Copyright 2016-2024 NeoChapay