Открыть главное меню

Изменения

Application

11 609 байт добавлено, 19:48, 16 февраля 2010
ну и уродец получился =)
Application - приложение для системы [[AFW]]. Приложение это именно то, что взаимодействует с пользователем (драйвера, в отличие от приложений, обычно не взаимодействуют с пользователем, они работают с железом и приложениями или [[OS|операционной системой]]).

Приложение для AFW разрабатывалось таким, чтобы работать из [[ROM]]'а, поэтому приложение может вообще не иметь глобальных переменных, все данные приложения должны храниться в структуре приложения, в которой первой должна быть структура [[APPLICATION_T]], указатель на экземпляр текущего приложения передаётся в каждом обработчике событий, из которых по сути и состоит приложение. В приложениях из эльфов немного иначе, как минимум таблица ивентов регистрации должна быть в [[RAM]]'е, т.к. база ивентов выделяется динамически. В прошивке коды ивентов назначаются автоматически в процессе компиляции.


== Таблица [[Event|ивентов]] регистрации ==
Массив кодов ивентов на которые стартует приложение. На эти ивенты регистрируется функция старта приложения. Для эльфов это обычно один единственный ивент код которого записывается в глобальной структуре [[ldrElf]].

== Регистрация ==
Приложение должно быть зарегестрировано в системе [[AFW]], делается это функцией [[APP_Register]]. Её параметры:
* таблица ивентов регистрации.
* количество элементов в таблице ивентов.
* таблица, описывающая стэйты приложения.
* количество элементов в таблице, описывающей стэйты.
* адресс функции старта приложения.
Регистрируется приложение один раз и удалить регистрацию потом будет невозможно, а эльф обычно должен выгружаться из памяти, поэтому нужно исключить совпадение ивентов для выгружаемого эльфа, для этого используется функция [[ldrRequestEventBase]], которая каждый раз возвращает уникальный свободный код ивента который можно использовать как "свои" ивенты. Даже более, следующие 63 кода тоже свободны и никогда не встретятся. При регистрации система запоминает не ивенты, а адресс таблицы, а т.к. память эльфа может быть освобождена данные могут быть изменениы и это может быть источником глюков, от этого никуда не деться.

== Старт ==
Функция старта приложения имеет вид:
<pre>UINT32 AppStart( EVENT_STACK_T * ev_st, REG_ID_T reg_id, void * reg_hdl );</pre>
Параметры:
* ev_st - указатель на [[Event_Stack|стэк событий]].
* reg_id - идентификатор регистрации приложения. Когда приложение регистрируется оно получает уникальный идентификатор регистрации, по которому его можно найти. По reg_id можно определить что приложение с таким идентификатором уже запущено (см. [[AFW_InquireRoutingStackByRegId]]).
* reg_hdr - структура с данными, которые получены при регистрации приложениями.
В начале можно проверить, вдруг это приложение уже папущено:
<pre> if( AFW_InquireRoutingStackByRegId( reg_id ) == RESULT_OK ) {
return RESULT_FAIL;
}</pre>
Дальше нужно выделить память под структуру и провести инициализацию AFW приложения функцией [[APP_InitAppData]]. Параметры:
* адресс функции обработчика ивентов приложения. Можно воспользоваться уже готовыми в прошивке - [[APP_HandleEvent]] для приложений использующих [[UIS|графический интерфейс]] или [[APP_HandleEventPrepost]] для фоновых.
* размер структуры приложения.
* идентификатор регистрации приложения.
* размер элемента [[стэк истории приложения|стэка истории приложения]].
* глубина [[стэк истории приложения|стэка истории приложения]].
* приоритет. =1.
:Дальше идут несколько уровней приоритета приложения. Очевидно, фоновое приложение имеет высший приоритет и раньше поймает событие в обработчике.
* =AFW_APP_CENTRICITY_PRIMARY для фоновых, =AFW_APP_CENTRICITY_SECONDARY для приложений с [[UIS]].
* =AFW_PREPROCESSING для фоновых, =AFW_FOCUS для приложений с UIS.
* приоритет в стэке приложений. =AFW_POSITION_TOP.
Функция должна указатель на структуру приложения, NULL в случае ошибки.
Если функция вернула не NULL, то приложение можно запустить, после чего приложение будет обрабатывать ивенты. Делается это функцией [[APP_Start]]. Параметры:
* указатель на стэк событий.
* указатель на структуру приложения.
* индеск первого стэйта, в котором стартует приложение.
* адресс функции, закрывающей приложение, освобождающей данные.
* указатель на глобальную константу, содержащую имя приложения.
* указатель на таблицу, описывающую имена стэйтов. Можно указать NULL.
Функция должна вернуть RESULT_OK если все сделано без ошибок.
Приложение запущено, возвращаем RESULT_OK, как подтверждение, что приложение успешно запущено.

== Выход ==
Функция выхода(закрытия) из приложения имеет вид:
<pre>UINT32 AppExit( EVENT_STACK_T * ev_st, APPLICATION_T * app );</pre>
В этой функции должны быть удалены диалоги, освобождена память и прочие ресурсы, выделенные динамически в процессе работы приложения. Вызвана стандартная функция выхода из приложения.


== Состояния ({{lang-en|states}}) ==
В один момент времени приложение в целом может находиться в одном из состояний, за исключением зарезервированного ANY под индексом 0. От стэйта зависит поведение приложения. Когда на стандартный обработчик событий приложением (задается первым параметром в [[APP_InitAppData]] при старте приложения) поступает ивент он ищет код этого ивента в таблице обработчиков ивентов, которая записана под ANY стэйтом, если там не находит, то ищет в таблице под текущим стэйтом и вызывает обработчик события. Если обработчик ивента вернул чтото отличное от RESULT_OK вызывается функция выхода из приложения.
Одно состояние должно иметь:
* идентификатор. Задается через enum в заголовочном файле, при этом ANY_STATE под индексом 0.
* функция входа в стэйт, можно NULL, если такая не нужна.
* функция выхода из стэйта, можно NULL, если такая не нужна.
* указатель на таблицу обработчиков ивентов.
Пример:
<pre>static const STATE_HANDLERS_ENTRY_T state_handling_table[] =
{ APP_STATE_ANY,
NULL,
NULL,
any_state_handlers
},

{ APP_STATE_INIT,
NULL,
NULL,
init_state_handlers
},

{ APP_STATE_MAIN,
MainStateEnter,
MainStateExit,
main_state_handlers
}//,
};</pre>

=== Функция входа в стэйт ===
Должна иметь вид:
<pre>UINT32 StateEnter( EVENT_STACK_T * ev_st, APPLICATION_T * app, ENTER_STATE_TYPE_T type );</pre>
type при этом может принимать значения:
* ENTER_STATE_ENTER - обычный вход в стэйт, либо при старте приложения, либо при смене стэйта.
* ENTER_STATE_RESUME - приложение уже находится в этом стэйте, если приложение потеряло фокус, из-за того, что было запущено другое, которое использует UIS, и закрылось. Тоесть потеряло фокус и снова получило.

=== Функция выхода из стэйта ===
Должна иметь вид:
<pre>UINT32 StateExit( EVENT_STACK_T * ev_st, APPLICATION_T * app, EXIT_STATE_TYPE_T type );</pre>
type при этом может принимать значения:
* EXIT_STATE_EXIT - обычный выход из стэйта.
* EXIT_STATE_SUSPEND - когда приложение должно "приостановить" свою активность т.к. оно не имеет фокус.

=== Таблица обработчиков ивентов ===
Представляет из себя массив элементов типа:
<pre>typedef struct
{
EVENT_CODE_T code; // код ивента
EVENT_HANDLER_T *hfunc; // функция, которая обрабатывает ивент с этим кодом
} EVENT_HANDLER_ENTRY_T;</pre>
84
правки