Psion Link Protocol
Это первая часть перевода описания протокола обмена ПДА Psion. Документ достаточно объемный, поэтому прошу меня не пинать ногами если процесс будет идти несколько медленно.
Psion Link Protocol
Версия 1.04, от 02 июня 2000by Alexander Thoukydides (alex@thouky.co.uk)
Copyright (C) Alexander Thoukydides.
Перевод Андрей А. Породько Copyright (C).
Вы можете свободно копировать, передавать и/или модифицировать данный документ на условиях лицензии GNU (GNU Free Documentation License), версии 1.1 или другой, более поздней, опубликованной Free Software Foundation; без частей помеченных как "Неизменная", без титульных листов. Копия лицензии "GNU Free Documentation License".
Введение
Операционные системы SIBO и EPOC (ОС для ПДА Psion и родственных ему, EPOC относится к Psion Series 5 и выше, SIBO для предыдущих версий, прим. пер.) используют свой собственный протокол для обмена по последователным линиям. Данный протокол называется Psion Link Protocol (PLP), и позволяет осуществлять удаленный доступ к файловой системе данных ОС и решения вопросов синхронизации. Данный документ представляет собой попытку предоставить достаточную информацию для создания клиентских приложений использующих связь устройствами на базе SIBO или EPOC через протокол PLP.Свежую версию оригинального можно найти на http://www.thouky.co.uk/software/psifs/plp.html.
История
Версия | Дата | Автор | Описание |
---|---|---|---|
1.04 | 2 июня 2000 г. | Alexander Thoukydides | Документ опубликован на условиях лицензии GNU версии 1.1 для документации. |
1.03 | 21 апреля 2000 г. | Alexander Thoukydides | Иправлен HTML код. Обновлена адреса email. Добавлена ссылка на последнюю версию. |
1.02 | 23 анваря 2000 г. | Alexander Thoukydides | Добавлено детальное описание функций NCP_SET_TIME и NCP_GET_MACHINE_INFO. |
1.01 | 22 декабря 1999 г. | Alexander Thoukydides | Добавлено описание для большинства команд сервера RFSV. |
1.00 | 09 декабря 1999 г. | Alexander Thoukydides | Предварительная версия.Отсутствует описание RFSV-сервера. |
Отказ от гарантий
Данный документ приводится "как есть"; без каких бы то либо гарантий. (Далее следуют обычные в таком случае изъявления на этот счет, я их опускаю, так как это касается юридической стороны, а мне бы не хотелось ее исказить. прим. пер.) Все торговые марки признаются за их владельцами.Благодарности.
Информация содержащаяся в данном документе собрана из различных, включая (но не только их):- Частичное описание протокола PLP сделанное доктором Olaf Flebbe.
- Реализацию протокола PLP сделанную для UNIX-а Phil Proudman.
- Документы Psion описывающие различия в реализации протокола ОС SIBO и EPOC.
- EPOC C++ SDK, пробовательная редакция.
- Выдержки из исходных текстов ОС EPOC.
- Анализ обмена данными между Psion Series 5 и PC с запущенной программой PsiWin.
- Опыт и ошибки полученные в процессе реализации PsiFS для RISC OS.
Уровни
Протокол PLP состоит из набора уровней которые некоторым образом соотносятся с моделью OSI :
Уровень OSI | Название в ОС EPOC | Описание | |
---|---|---|---|
7 | Прикладной | неприменимо | |
6 | Представительный | LINK, RPCS, RFSV и т.д. | Множество сервером, каждый из которых предоставляет свой уровень сервиса |
5 | Сеансовый | NCP | Мультиплексор для организации множественных каналов клиент-сервер с communications channels включая кправление потоком (flow control) |
4 | Транспортный | неприменимо | |
3 | Сетевой | неприменимо | |
2 | Канальный | Link | Синхронизация, обнаружение и коррекция ошибок |
1 | Физический | RS-232 |
Соглашения
Если не указано обратное, действуют следующие соглашения:- Числа больше, чем один байт, хранятся в LITTLE_ENDIAN (менее значащий байт -- первый):
- Строки заканчиваются нулевым байтом.
Физический уровень
На самом нижнем уровне PLP использует стандартный протокол RS-232. В зависимости от конкретного устройства, использующего EPOC, может понадобится специальный кабель.Линии DTR и RTS переводятся в 1 если соединения PLP установлено и сбрасываются в случае рассоединения. Таким образом, достаточно контролировать сигнал DTR для определения активности устройства с EPOC.
Любая скорость передачи поддерживаемая устройствами может быть использована. Формат данных 8,1,N (8-бит данных, 1 стоп-бит, без четности).
Канальный уровень
Канальный уровень представляет собой простой байт-ориентированный протокол для реализации надежного соединения между двумя устройствами. Это протоколо ориентированный на соединение с явно выраженными фазами установления соединения, обмена данными, и разрыва соединения. Используемые посылка подтверждений и повторы гарантируют безошибочный обмен данными.На этот уровень иногда ссылаются как на уровень LINK, однако это может ввести в заблуждение, так как один из протоколов более высокого уровня имеет такое же название.
Формат кадра (пакета)
Все данные передаются кадрами (пакетами) следующего формат:
Размер (байт) | 1 | 1 | 1 | 1 | n | 1 | 1 | 2 | |
Поле | SYN | DLE | STX | Cont | Seq | Data | DLE | ETX | CRC |
Поля Cont и Seq объединены в один байт, где Cont -- это старший полубайт, а Seq младший. Если величина поля Seq больше 7, то выставляется наиболее значащий в поле Seq и в кадр добавляется дополнительный байт (только вариант EPOC):
Размер (байт) | 1 | 1 | 1 | 1 | 1 | n | 1 | 1 | 2 | |
Поле | SYN | DLE | STX | Cont | Data | DLE | ETX | CRC |
Длина поля Data field (n) может варьироваться в пределах от 0 до 300 байт. Сеансовый (NCP) обязан разбивать более длинные данные (и собирать их) на части умещающиеся в данные пределы. 16-ти битная циклическая контрольная сумма (CRC) передается в порядке, обратном принятому для других данных -- более значащий байт идет первым.
Специальные символы
В протоколе используются следующие специальные символы:
Название | Значение | Описание |
---|---|---|
STX | 0x02 | Начало пакета |
ETX | 0x03 | Конец пакета |
EOT | 0x04 | Символ-затычка для ETX (A stuffed ETX character) |
DLE | 0x10 | Разделитель полей в пакете |
SYN | 0x16 | Байт синхронизации начала пакета |
При предотвращения неправильного распознавания управляющих символов внудтри пакета, используется система подстановок. Для этого любые символы DLE которые могут встретится в полях Cont/Seq и Data при передаче заменяются двойным символом DLE (DLE DLE), соответственно на приемной стороне такие пары должны бать ообратно преобразованы в одиночные символы данных. Вариает протокола для EPOC также заменяет байты ETX последовательностью DLE EOT.
Циклическая контрольная сумма
Для получения CRC используется стандартный полином x16 + x12 + x5 + 1. Сумма вычисляется для полей Cont/Seq и Data до описанных выше подстановок. Следующий пример C-кода выполняет расчет CRC:static const int table[] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; new_crc = (old_crc << 8) ^ table[((old_crc >> 8) ^ value) & 0xff];где value -- это байт, который нужно добавить к текущей сумме (old_crc) для получения новой суммы CRC (new_crc). Значение CRC должно быть инициализировано 0 до обработки любых данных. Возможно необходимо воспользоваться беззнаковыми величинами для предотвращения системных проблем с 16-ти битными целыми.
Таймеры
Используются два события по таймеру для определения таймаутов:
Событие | Величина |
---|---|
Перепосылка | Зависит от скорости обмена |
Неактивность | Зависит от конкретного приложения |
Таймаут для перепосылки используется для определения момента перепосылки пакетов на которые не было подтверждения. Для оптимизации таймаутов в реальных условиях учитываются (складываются) следующие компоненты:
Компонента | Описание |
---|---|
Фактор скорости обмена | Для определения времени, необходимого для передачи битов пакета при заданной скорости, подходящий таймаут можно вычислить как (13200/скорость в bps) секунд. |
Время на обработку | Дополнительное время, необходимое для обработки и посылки подтверждения. Как правило, для большинства применений достаточно использовать постоянную задержку в 0.2 секунды. |
Фактор возврата | Дополнительное время, зависящее от количества уже сделанных перепосылок. В простых приложениях может быть опущен. |
Фактор скорости является более значимым на низких скоростях, в то же время Время на обработку приобретает большее значение на высоких скоростях обмена.
Таймер Неактивности может быть подогнан под конкретное приложение. Если не используется проверка на простой соединения, то он может быть полностью запрещен. В других случаях рекомендуется таймаут в 60 секунд.
Несмотря на то, что применяются два различных события по времени, в реализации может использоваться только один таймер, так как эти события существуют в разное время.
Элементы протокола данных (Protocol Data Units, PDU)
Всего возможно четыре основных типа пакетов или элементов данных протокола (Protocol Data Unit ,PDU):
Номер | Последовательность (номер пакета) | Наименование | Описание |
---|---|---|---|
0 | Номер пакета последнего правильно принятого пакета (Data_Pdu) | Ack_Pdu | Используется для завершения процедуры подтверждения в процеесе установления, и для подтверждения приема пактов данных (Data_Pdu frames). |
1 | 0 | Disc_Pdu | Используется для завершения соединения. |
1 | Disc_Req_Pdu | Первое рассоединение в подтверждение разрыва связи. В настоящей реализации не используется. | |
2 | 0 | Req_Pdu | Используется на шаге установления соединения как запрос на подключение. |
1...3 (use 1) | Req_Req_Pdu | Первый запрос в процессе установки соединения. Только для варианта протокола EPOC. | |
4...6 (use 4) | Req_Con_Pdu | Ответ за запрос соединения. Только для варианта протокола EPOC. | |
3 | Next sequence number | Data_Pdu | Пакет данных. |
Только пакеты типа Data_Pdu и Req_Con_Pdu содержат поле "Данные" (Data field).
Пакеты Data_Pdu и Ack_Pdu содержат "последовательный номер пакета" (sequence number, далее просто "номер пакета"). Номер пакета используется для идентификации пакетов при отправке подтверждения приема. Каждое устройство поддерживает свою последовательность номеров пакетов, который (номер) увеличивается при отправке очередного пакета Data_Pdu, номер вычисляется по модулю 8 для варианта протокола SIBO или по модулю 2048 для варианта EPOC. Подробности можно найти в следующих разделах описания.
Порядок соединения
Порядок соденияния для SIBO и EPOC незначительно отличаются. Оригинальная реализация варианта протокола SIBO имеет ошибку связанную с эхом модема (modem echo problem), в этом случае уровень data link может установить связь сам с собой если на последовательном порту имеется заглушка; проблема решена в реализации варианта протокола EPOC.Поддерживаются режимы соединения точка-точка и клиент-сервер. Точка-точка представляет собой симметричный вариант последовательности соединения клиент-сервер, при котором оба устройства отрабатывают все типы пакетов (PDUs).
Вариант SIBO
Соединение клиент-сервер инициируется клиентом:
От клиента | От сервера | Описание |
---|---|---|
Req_Pdu | Запрос соединения клиентом | |
Req_Pdu | Запрос соединения подтвержден | |
Ack_Pdu | Соединение установлено |
Соединение точка-точка очень похоже:
От устройства 1 | От устройства 2 | Description |
---|---|---|
Req_Pdu | Req_Pdu | Оба устройства запрашивают соединение |
Ack_Pdu | Ack_Pdu | Оба устройства подтверждают соединение |
В обоих случаях "номер пакета" (sequence numbers) должны быть сброшены в 0, и пакет типа Ack_Pdu посылается с полем Seq, установленным в 0. Однако, если принятый пакет Ack_Pdu содержит не ноль, в поле Seq "номер пакета" (sequence number) должен быть проинициализирован указанным числом.
Вариант EPOC
Соединение клиент-сервер инициируется клиентом:
От клиента | От сервера | Описание |
---|---|---|
Req_Req_Pdu | Запрос соединения клиентом | |
Req_Con_Pdu | Запрос соединения подтвержден сервером | |
Ack_Pdu | Соединения установлено |
Соедиение точка-точка происходит сходным образом:
От устройства 1 | От устройства 2 | Описание |
---|---|---|
Req_Req_Pdu | Req_Req_Pdu | Оба устройства запрашивают соединение |
Req_Con_Pdu | Req_Con_Pdu | Оба устройства подтверждают запрос на соединение |
Ack_Pdu | Ack_Pdu | Оба устройства принимают соединение |
Поле Data field пакета Req_Con_Pdu содержит четырех-байтовое "магическое" число (4 byte magic number). Это псевдо-случайное число генерируется независимо каждым устройством. Если "магические" числа совпадают, значит, соединение точка-точка отвергается, так как это указывает, что устройство пытается соединится само с собой. Для уменьшения риска получения двух одинаковых псево-случайных чисел обоими устройствами, полезным будет включить дополнительно в это число какой-нибудь уникальный элемент, например значение времени.
В обоих случаях номер пакета должен быть сброшен в ноль, и пакет Ack_Pdu должен быть послан с полем Seq равным 0. Тем не менее, если полученный пакет Ack_Pdu содержит не нулевое поле Seq, номер пакета должен быть проинициализирован полученным числом.
Если пакет Ack_Pdu не был получен в течение таймаута перепосылки (re-transmission timeout), пакет Req_Req_Pdu может быть повторно послан еще 4 раза, прежде чем следует прервать попытки соединения.
Универсальная процедура соединения
При недольших дополнительных расходах возможно реализовать оба варианта протокола в пределах одного конечного автомата (within a single state machine). Максимальное значение для номеров пакетов, в этом случае, выбирается после определения типа.
Пакет Req_Req_Pdu всегда может быть использован для инициирования соединения; устройство поддерживающее вариант протокола EPOC просто ответит пакетом Req_Con_Pdu, а устройства, поддерживающие вариант SIBO, будут интерпретировать его как Req_Pdu и ответят пактом Ack_Pdu. Следовательно, вариант протокола может быть определен по пакету Req_Con_Pdu, полученному до пакета Ack_Pdu.
Соответственно, если другое устройство инициировало соединение, то вариант протокола может быть выбран в зависимости от того, какой пакет был принят: Req_Pdu или Req_Req_Pdu.
Последовательность передачи данных
Уровень передачи данных использует только одно окно (is single windowed), т.е. только одно подтверждение приема может быть обработано за один раз. Это гарантирует, что необходим только один буфер на прием, и один на передачу. Однако, из-за асинхронной природы обмена данными, передача пакета и получение подтверждения на него в каждом направлении могут быть разнесены во времени.Последовательность обмена данными одинакова для обоих (SIBO и EPOC) вариантов протокола. Оба устройства могут инициировать передачу данных, при этом посылая подтверждение на ранее полученные данные.
От устройства 1 | От устройства 2 | Описание |
---|---|---|
Data_Pdu | Посылка данных | |
Ack_Pdu | Подтверждение приема |
Здесь существует только одно различие между вариантами SIBO и EPOC, как было описано ранее: диапазон используемых номеров пакетов (sequence numbers). Это число по модулю 8 (от 0 до 7, прим. пер.) для варианта SIBO. И по модулю 2048 (от 0 до 2047, прим. пер.) для варианта EPOC. Номер пакета увеличивается на 1 до посылки пакета с данными (Data_Pdu).
Подтверждение Ack_Pdu должно посылаться всегда в ответ на полученный пакет Data_Pdu, даже если номер пакета (sequence number ) не совпал с ожидаемым. Однако, поле Seq в пакете Ack_Pdu должно быть равно номеру последнего правильно принятого пакета, и совсем не обязательно является подтверждением на полученный Data_Pdu (However, the Seq field of the Ack_Pdu should be set to the value from the last valid Data_Pdu received, not necessarily that of the Data_Pdu being responded to).
Если подтверждение Ack_Pdu не было получено в течении таймаута перепосылки (re-transmission timeout), или если подтверждение содержит неверный номер пакета (отличающийся от посланного с данными), пакет данных может быть повторно послан еще до 8 раз, прежде чем соединение будет разорвано. Номер павета при перепосылке меняться не должен.
Последовательность рассоединения
В протоколе PLP не предусматривается никаких подтверждений при рассоединение, поэтому существует риск, что одно устройство отсоединится без уведомления другого. Предполагалось, что варианте EPOC исправить это положение, однако не видно, чтобы это было сделано.Рассоединение также может произойти, если последовательный кабель был физически отключен от устройства, как было описано ранеее, для этого надо следить за линией DSR. Дополнительно, если по истечение таймаута неактивности (inactivity timeout) не было принято ни одного пакета, это может служить сигналом к рассоединению.
Рассоединение в варианте SIBO
Любое из двух устройств может инициировать рассоединение
От устройства 1 | От устройства 2 | Описание |
---|---|---|
Disc_Pdu | Инициализация рассоединения |
Отметим, что здесь нет подтверждения рассоединения, тем не менее оно считается успешным.
Рассоединение в варианте EPOC
Предполагалось, что следующая последовательность рассоединения решит проблему, описанную выше. Но не похоже, чтобы она была реализована. Любое из устройств может инициировать рассоединение:
От устройства 1 | От устройства 2 | Описание |
---|---|---|
Disc_Req_Pdu | Инициализация рассоединения | |
Disc_Pdu | Рассоединение подтверждено |
Даже если реализована поддержка этой усовершенствованной процедуры рассоединения, оригинальная процедура рассоединения (вариант SIBO) также должна поддерживаться. В частности, если пакет Disc_Pdu не получен в течение таймаута перепосылки (re-transmission timeout) нужно послать пакет Disc_Pdu и считать рассоединение состоявшимся.
Конечный автомат
Этат раздел описывает пример конечного автомата, который реализует оба варианта протокола уровня передачи данных (data link layer). В автомате делается попытка установить соединение точка-точка, но и соединение клиент-сервер также поддерживаются.Не предполагается, что данное описание является окончательной реализацией, однако может оно помочь понять работу протокола.
Состояния
Используются пять состояний (здесь и далее термины "событие" и "состояние" используются как синонимы, прим. пер.):
Состояние | Описание |
---|---|
Idle_State | Рассоединен |
Idle_Req_State | послан Req_Req_Pdu, ждем подтверждения соединения Req_Con_Pdu |
Idle_Ack_State | послан Req_Con_Pdu, ждем отзыва Ack_Pdu |
Data_State | Состояние приема/передачи данных. Не требуется вспециальных указаний на это состояние |
Data_Ack_State | послан пакет данных Data_Pdu, ждем подстверждения приема |
События
Следующие события обрабатываются конечным автоматом:
Событие | Источник (информации о событии - прим. пер.) | Описание |
---|---|---|
Ack_Rx | Полученный пакет | получен Ack_Pdu (подтверждение приема) |
Disc_Rx | получен Disc_Pdu или Disc_Req_Pdu (рассоединение) | |
Req_Rx | получен Req_Pdu (запрос соединения) | |
Req_Req_Rx | получен Req_Req_Pdu (ответ за запрос соединения) | |
Req_Con_Rx | получен Req_Con_Pdu (подтверждение соединения) | |
Data_Rx | получен пакет данных Data_Pdu | |
Connect | Программа-клиент | Запрос соединения |
Disconnect | Запрос рассоединения | |
Write | Передача данных | |
Timeout | Таймер | Истекло время ожидания подстверждения приема (таймаут перепосылки, re-transmission timer) или истекло время неактивности (inactivity timer) |
Отметим, что используется только один таймер; оба таймаута отслеживаются одним таймером.
Кроме того, процедура рассоединения описана только п оварианту SIBO, соответственно пакеты Disc_Pdu и Disc_Req_Pdu интерпретируются одинаково.
Переменные
Для хранения дополнительных состояний необходимы следующие переменные:
Переменная | Описание | Значение по умолчанию |
---|---|---|
Enabled | Соединение установлено? | FALSE |
Variant | Тип протокола: SIBO или EPOC | SIBO |
Retries | Количество перепосылок | 0 |
Seq_Tx | Номер последнего отправленного пакета (sequence number) для переданных пактов данных | 0 |
Seq_Rx | Номер последнего принятого пакета данных | 0 |
Magic | "Магическое" число для данного устройства | Псевдослучайная величина |
Таблицы переходов (state tables)
Описанные ниже таблицы детально описывают действия, выполняемые для каждого события, отдельная таблица для каждого состояния.Функция Inc(x) возвращает следующее за x число по заранее определенному модулю.
Функция Reset() сбрасывает все переменные, за исключением переменной Enabled, в значения по умолчанию, а также получает новое псевдо-случайное число для Magic и запускает таймер перепосылки (re-transmission timer).
Idle_State
Событие | Условие | Действие | Следующее состояние |
---|---|---|---|
Ack_Rx | Всегда | Нет действия | Idle_State |
Disc_Rx | Всегда | Нет действия | Idle_State |
Req_Rx | Enabled | Вариант SIBO - послать Req_Con с числом Magic в качестве данных. Запустить таймер перепосылки. Retries = 4 | Idle_Ack_State |
иначе | нет действия | Idle_State | |
Req_Req_Rx | Enabled | Вариаен EPOC - послать Req_Con с числом Magic в качестве данных. Запустить таймер перепосылки. Retries = 4 | Idle_Ack_State |
иначе | нет действия | Idle_State | |
Req_Con_Rx | Всегда | нет действия | Idle_State |
Data_Rx | Всегда | нет действия | Idle_State |
Connect | Всегда | Enabled = TRUE | Idle_State |
Disconnect | Всегда | Enabled = FALSE | Idle_State |
Write | Всегда | Ошибка - нет соединения | Idle_State |
Timeout | Enabled | Send Req_Req_PduStart re-transmission timer | Idle_Req_State |
иначе | нет действия | Idle_State |
Idle_Req_State
Событие | Условие | Действие | Следующее состояние |
---|---|---|---|
Ack_Rx | Enabled | Seq_Tx = sequence numberSeq_Rx = 0 запустить таймер неактивности (inactivity timer) Соединение установлено | Data_State |
иначе | нет действия | Idle_Req_State | |
Disc_Rx | Всегда | Reset() | Idle_State |
Req_Rx | Enabled | Вариант SIBO: SeqTx = 0 Seq_Rx = 0 Послать Ack_Pdu с Seq_Rx Запустить таймер неактивности Соединение установлено | Data_State |
иначе | нет действия | Idle_Req_State | |
Req_Req_Rx | Enabled | Вариант EPOC: Послать Req_Con с числом Magic в качестве данных Запустить таймер перепосылки Retries = 4 | Idle_Ack_State |
иначе | нет действия | Idle_Req_State | |
Req_Con_Rx | Всегда | нет действия | Idle_Req_State |
Data_Rx | Всегда | нет действия | Idle_Req_State |
Connect | Всегда | Ошибка - соединение уже установлено | Idle_Req_State |
Disconnect | Всегда | Enabled = FALSE Послать Disc_PduReset() | Idle_State |
Write | Всегда | Ошибка - нет соединения | Idle_Req_State |
Timeout | Enabled | Попытаться на другой скорости, если реализовано авто-определение скорости. Послать Req_Req_Pdu Запустить таймер перепосылки | Idle_Req_State |
иначе | Reset() | Idle_State |
Idle_Ack_State
Событие | Условие | Действие | Следующее состояние |
---|---|---|---|
Ack_Rx | Enabled | Seq_Tx = номер пакета Seq_Rx = 0 Запустить таймер неактивности Соединение установлено | Data_State |
иначе | нет действия | Idle_Ack_State | |
Disc_Rx | Всегда | Reset() | Idle_State |
Req_Rx | Enabled | Вариант SIBO: SeqTx = 0 Seq_Rx = 0 Послать Ack_Pdu с номером пакета Seq_Rx Запустить таймер неактивности Соединение установлено | Data_State |
иначе | нет действия | Idle_Ack_State | |
Req_Req_Rx | Enabled | Вариант EPOC: Послать Req_Con с числом Magic в качестве данных Запустить таймер перепосылки Retries = 4 | Idle_Ack_State |
иначе | нет действия | Idle_Ack_State | |
Req_Con_Rx | Enabled and (полученное "магическое" число не равно сгенерированному нами, magic number != Magic) | Вариант EPOC: Seq_Tx = 0 Seq_Rx = 0 Послать Ack_Pdu с номером пакета Seq_Rx Запустить таймер неактивности Соединение установлено | Data_State |
иначе | нет действия | Idle_Ack_State | |
Data_Rx | Всегда | нет действия | Idle_Ack_State |
Connect | Всегда | Ошибка - соединение уже установлено | Idle_Ack_State |
Disconnect | Всегда | Enabled = FALSE Послать Disc_PduReset() | Idle_State |
Write | Всегда | Ошибка - нет соединения | Idle_Ack_State |
Timeout | Enabled и (исчерпан счетчик повторов, 0 < Retries) | Retries = Retries - 1Послать Req_Con с числом Magic в качестве данных | Idle_Ack_State |
иначе | Reset() | Idle_State |
Data_State
Событие | Условие | Действие | Следующее состояние |
---|---|---|---|
Ack_Rx | Всегда | Нет действия | Data_State |
Disc_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Req_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Req_Req_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Req_Con_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Data_Rx | увеличиваем номер пакета sequence number == Inc(Seq_Rx) | Seq_Rx = Inc(Seq_Rx)Посылаем Ack_Pdu с номером пакета Seq_RxЗапустить таймер неактивности | Data_State |
иначе | Послать Ack_Pdu с номером пакета Seq_Rx | Data_State | |
Connect | Всегда | Ошибка - соединение уже установлено | Data_State |
Disconnect | Всегда | Enabled = FALSE Послать Disc_PduReset() Соединение разорвано | Idle_State |
Write | Всегда | Seq_Tx = Inc(Seq_Tx) Послать Data_Pdu с номером пакета Seq_Tx Запустить таймер перепосылки Retries = 8 | Data_Ack_State |
Timeout | Всегда | Послать Disc_PduReset() Соединение разорвано | Idle_State |
Data_Ack_State
Событие | Условие | Действие | Следующее состояние |
---|---|---|---|
Ack_Rx | запоминаем номер пакета sequence number == Seq_Tx | Запустить таймер неактивности | Data_State |
иначе | нет действия | Data_Ack_State | |
Disc_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Req_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Req_Req_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Req_Con_Rx | Всегда | Reset() Соединение разорвано | Idle_State |
Data_Rx | увеличиваем номер пакета Inc(Seq_Rx) | Seq_Rx = Inc(Seq_Rx) Послать Ack_Pdu с номером пакета Seq_Rx Запустить таймер перепосылки | Data_Ack_State |
иначе | Послать Ack_Pdu с номером пакета Seq_Rx | Data_Ack_State | |
Connect | Всегда | Ошибка - соединение уже установлено | Data_Ack_State |
Disconnect | Всегда | Enabled = FALSE Послать Disc_PduReset() Соединение разорвано | Idle_State |
Write | Всегда | Ошибка - соединение занято | Data_Ack_State |
Timeout | исчерпан счетчик перепосылок 0 < Retries | Retries = Retries - 1 Послать Data_Pdu с номером пакета Seq_Tx Запустить таймер перепосылки | Data_Ack_State |
иначе | Послать Disc_PduReset() Соединение разорвано | Idle_State |
Андрей А. Породько
Интересные ссылки:
Комментариев к странице: 0 | Добавить комментарий
Домой | Проект ядро Core/2 | Проект OS/4 Download | Новости | Гостевая книга | Подробно обо всем | Нужные программы | Проекты | OS/2 FAQ | Всячина | За и Против | Металлолом | #OS2Russian | RDM/2 | Весёлые картинки | Наша галерея | Доска объявлений | Карта сайта | ПОИСК | ФОРУМ