Официальный форум СВД Встраиваемые Системы
24 Апрель, 2024, 20:34:27 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
 
 
 Сайт СВД ВС  Начало   Помощь Поиск Войти Регистрация  
Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Срабатывание PhEventEmit  (Прочитано 3686 раз)
ad
Пользователь

Сообщений: 70


« : 20 Сентябрь, 2014, 11:56:27 »

Что необходимо сделать для срабатывания PhEventEmit?
Есть демо программка, которая при нажатии на клавиши F1-F8 выводит в list-box информацию о том, какая кнопка нажата. При обработке на обычном ПК нажатия клавиш видно. На панельной станции есть спец-кнопки, значения которых принимаются по COM-порту. После приема заполняю структуру PhRawKeyEvent_t и отправляю PhEventEmit, но срабатывания не вижу.
Вот код создания региона обработки Photon события:
Код:
/**
 * @brief This function creates two Photon regions. We need one of them, which
 *   covers entire Photon space to listen Ph_EV_RAW events. The second one
 *   is used to emit Ph_EV_RAW_PTR events.
**/
static int create_region()
{
PhRegion_t region;
PhRect_t rect;

memset(&region, 0, sizeof(region));

region.events_sense = Ph_EV_RAW;

region.flags = Ph_KBD_REGION | Ph_PTR_REGION | Ph_FORCE_FRONT;

    region.origin.x = region.origin.y = 0;
region.input_group = 1;

// Cover all Photon space
rect.ul.x = rect.ul.y = SHRT_MIN;
rect.lr.x = rect.lr.y = SHRT_MAX;

if((Rid = PhRegionOpen(Ph_REGION_FLAGS | Ph_REGION_EV_SENSE |
Ph_REGION_RECT, &region, &rect, NULL)) == -1)
{
printf("PhRegionOpen have errors: [%s]\n", strerror(errno));
fflush(stdout);
return -1;
}

PhRegionQuery(Rid, &region, NULL, NULL, 0);
region.events_opaque = Ph_EV_RAW;
PhRegionChange(Ph_REGION_EV_OPAQUE, 0, &region, NULL, NULL);

region.input_group = 1;
region.flags = Ph_PTR_REGION | Ph_FORCE_FRONT;
rect.ul.x = rect.ul.y = rect.lr.x = rect.lr.y = 0;

if((Ptr = PhRegionOpen(Ph_REGION_FLAGS | Ph_REGION_INPUT_GROUP |
Ph_REGION_RECT, &region, &rect, NULL)) == -1)
{
printf("PhRegionOpen have errors: [%s]\n", strerror(errno));
fflush(stdout);
return -1;
}

return 0;
}

Вот код заполнения структуры:
Цитировать
/// Parses the answer from COM and fills the structure Photon event
void BtnHandle::parseAnswer(IncCMD* answer)
{
   PhRawKeyEvent_t* ke = NULL;
   int value = atoi(answer -> p3);
   if((*answer) == KDxCmd || (*answer) == KUxCmd)
   {
      event -> subtype = Ph_EV_RAW_KEY;
      event -> emitter.rid = Rid;
      event -> collector.rid = 0;

      ke = (PhRawKeyEvent_t*)PhGetData(event);
      ke -> key_flags = ((*answer) == KDxCmd) ? 0xe1 : 0xa0;
      switch(value)
      {
      case 1:
         ke -> key_cap = Pk_F1;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x3b : 0xbb;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0be : 0xb1;
      break;
      case 2:
         ke -> key_cap = Pk_F2;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x3c : 0xbc;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0bf : 0xb6;
      break;
      case 3:
         ke -> key_cap = Pk_F3;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x3d : 0xbd;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0c0 : 0xb7;
      break;
      case 4:
         ke -> key_cap = Pk_F4;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x3e : 0xbe;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0c1 : 0xb4;
      break;
      case 5:
         ke -> key_cap = Pk_F5;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x3f : 0xbf;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0c2 : 0xb5;
      break;
      case 6:
         ke -> key_cap = Pk_F6;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x40 : 0xc0;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0c3 : 0xca;
      break;
      case 7:
         ke -> key_cap = Pk_F7;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x41 : 0xc1;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0c4 : 0xcb;
      break;
      case 8:
         ke -> key_cap = Pk_F8;
         ke -> key_scan = ((*answer) == KDxCmd) ? 0x42 : 0xc2;
         ke -> key_sym = ((*answer) == KDxCmd) ? 0xf0c5 : 0xc8;
      break;
      default:
      break;
      }
      PhEventEmit(event, PhGetRects(event), ke);
   }
   else
      PhEventEmit(event, PhGetRects(event), PhGetData(event));
}
Единственное, функция создания региона и функция заполнения структуры сделаны в разных потоках. Это принципиально? OS QNX 4.25.
Записан
Андрей Панченко
Сотрудник СВД ВС
Опытный пользователь

Сообщений: 106



WWW
« Ответ #1 : 20 Сентябрь, 2014, 12:32:05 »

Как я понимаю, спец-кнопки сами не генерируют события Photon через какой-либо драйвер? И в этом случая вы хотите с нуля создать и отправить событие?
Тогда непонятно, для чего в данном случае нужен регион перехватывающий события клавиатуры и откуда в  BtnHandle::parseAnswer(IncCMD* answer) указатель на event?
Записан

Сотрудник СВД Встраиваемые Системы
ad
Пользователь

Сообщений: 70


« Ответ #2 : 20 Сентябрь, 2014, 18:29:03 »

Как я понимаю, спец-кнопки сами не генерируют события Photon через какой-либо драйвер? И в этом случая вы хотите с нуля создать и отправить событие?
Тогда непонятно, для чего в данном случае нужен регион перехватывающий события клавиатуры и откуда в  BtnHandle::parseAnswer(IncCMD* answer) указатель на event?
event - глобальная переменная. А регион, насколько я понял из Ваших слов, вообще не нужен
Записан
Андрей Панченко
Сотрудник СВД ВС
Опытный пользователь

Сообщений: 106



WWW
« Ответ #3 : 20 Сентябрь, 2014, 18:54:00 »

То есть вам надо заполнить структуру с нуля? И до  BtnHandle::parseAnswer никто эту структуру не заполнял?
Тогда код должен быть примерно такой
Код:
	PhRawKeyEvent_t ke;
PhRect_t rect;
PhEvent_t event;

rect.ul.x = rect.ul.y = 0;
rect.lr.x = rect.lr.y = 0;
event.type = Ph_EV_KEY;
event.subtype = Ph_EV_RAW_KEY;
event.emitter.rid = Ph_DEV_RID;
event.collector.rid = 0;
event.num_rects = 1;
event.data_len = sizeof(ke);
event.input_group = 1;
ke.key_flags = ((*answer) == KDxCmd) ? 0xe1 : 0xa0;
switch(value)
{
case 1:
ke.key_cap = Pk_F1;
ke.key_scan = ((*answer) == KDxCmd) ? 0x3b : 0xbb;
ke.key_sym = ((*answer) == KDxCmd) ? 0xf0be : 0xb1;
break;
...
...
}
PhEventEmit(&event, &rect, &ke);
« Последнее редактирование: 20 Сентябрь, 2014, 19:05:48 от Андрей Панченко » Записан

Сотрудник СВД Встраиваемые Системы
ad
Пользователь

Сообщений: 70


« Ответ #4 : 20 Сентябрь, 2014, 21:43:13 »

Спасибо огромное. Попробую в понедельник.  Я правильно думал, что что-то я заполнил неполностью. И на будущее пригодиться. Еще раз спасибо.
Записан
ad
Пользователь

Сообщений: 70


« Ответ #5 : 21 Сентябрь, 2014, 18:58:03 »

Так-с. Сегодня испробовал код. К сожалению не помогло. Немножко дописал и... все-равно не помогло. Итак. create_region() удалена нафиг. А вот BtnHandle::parseAnswer(IncCmd* answer) изменена следующим образом:
Код:
// Parses the answer from COM and fills the structure Photon event 
void BtnHandle::parseAnswer(IncCMD* answer)
{
PhEvent_t event;
PhRect_t rect;
PhRawKeyEvent_t ke;
memset(&event, 0, sizeof(PhEvent_t));
memset(&rect, 0, sizeof(PhRect_t));
memset(&ke, 0, sizeof(PhRawKeyEvent_t));

rect.ul.x = rect.ul.y = 0;
rect.lr.x = rect.lr.y = 0;
event.type = Ph_EV_KEY;
event.subtype = Ph_EV_RAW_KEY;
event.emitter.rid = Ph_DEV_RID;
event.collector.rid = 0;
event.num_rects = 1;
event.data_len = sizeof(PhRawKeyEvent_t);
event.input_group = 1;

int value = atoi(answer -> p3);
if((*answer) == KDxCmd || (*answer) == KUxCmd)
{
ke.key_flags = ((*answer) == KDxCmd) ? 0xe1 : 0xa0;
ke.key_mods = 0x0;
switch(value)
{
case 1:
ke.key_cap = Pk_F1;
ke.key_scan = ((*answer) == KDxCmd) ? 0x3b : 0xbb;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F1 : 0xb1;
break;
case 2:
ke.key_cap = Pk_F2;
ke.key_scan = ((*answer) == KDxCmd) ? 0x3c : 0xbc;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F2 : 0xb6;
break;
case 3:
ke.key_cap = Pk_F3;
ke.key_scan = ((*answer) == KDxCmd) ? 0x3d : 0xbd;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F3 : 0xb7;
break;
case 4:
ke.key_cap = Pk_F4;
ke.key_scan = ((*answer) == KDxCmd) ? 0x3e : 0xbe;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F4 : 0xb4;
break;
case 5:
ke.key_cap = Pk_F5;
ke.key_scan = ((*answer) == KDxCmd) ? 0x3f : 0xbf;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F5 : 0xb5;
break;
case 6:
ke.key_cap = Pk_F6;
ke.key_scan = ((*answer) == KDxCmd) ? 0x40 : 0xc0;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F6 : 0xca;
break;
case 7:
ke.key_cap = Pk_F7;
ke.key_scan = ((*answer) == KDxCmd) ? 0x41 : 0xc1;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F7 : 0xcb;
break;
case 8:
ke.key_cap = Pk_F8;
ke.key_scan = ((*answer) == KDxCmd) ? 0x42 : 0xc2;
ke.key_sym = ((*answer) == KDxCmd) ? Pk_F8 : 0xc8;
break;
default:
break;
}
}
PhEventEmit(&event, &rect, &ke);

printf("   key_cap 0x%x, key_flags 0x%x, key_scan 0x%x, key_sym 0x%x, key_mods 0x%x\n", ke.key_cap,
ke.key_flags, ke.key_scan, ke.key_sym, ke.key_mods);
if((*answer) == KDxCmd)
{
printf("Pressed key F%s\n", answer -> p3);
}
else if((*answer) == KUxCmd)
{
printf("Released key F%s\n", answer -> p3);
}
}
И все равно в демо программе (демонстрашке) я не вижу ответа. А ответ с обычной клавиатуры на этой же станции показывается. При печати значений структуры event обратил внимание, что при печати значений на станции не совпадают значения event.emitter.rid и, как ни странно, event.data_len. rid = 0x1 на станции при нажатии на кнопки с COM-порта, а при нажатии на кнопки клавиатуры значение другое, 0x30. data_len при нажатии на обычную клаву - 0x26, и при кнопках COM-порта - 0x20.
Записан
Андрей Панченко
Сотрудник СВД ВС
Опытный пользователь

Сообщений: 106



WWW
« Ответ #6 : 21 Сентябрь, 2014, 20:20:07 »

По поводу data_len можно попробовать заменить структуру PhRawKeyEvent_t на PhKeyEvent_t. И event.subtype установить в 0.
И ещё проверить что при генерации нажатия key_flags устанавливаются в Pk_KF_Cap_Valid, Pk_KF_Sym_Valid и Pk_KF_Key_Down и соответсвенно key_cap и key_sym устанавливаются в одно значение, например Pk_F1. А при генерации отжатия key_flags устанавливаются только в Pk_KF_Cap_Valid, key_cap устанавливается в нужное значение, например Pk_F1.
Также вместо F1 можно проверить символьные клавиши A-Z.
Ещё неплохо было бы проверить, что возвращает PhEventEmit().
« Последнее редактирование: 21 Сентябрь, 2014, 21:50:03 от Андрей Панченко » Записан

Сотрудник СВД Встраиваемые Системы
ad
Пользователь

Сообщений: 70


« Ответ #7 : 21 Сентябрь, 2014, 21:51:23 »

key_sym и key_cap я выставляю в одно значение при нажатии. А при срабатывании обычной клавы я вижу одно значение при нажатии и разные при отпускании.
Записан
Андрей Панченко
Сотрудник СВД ВС
Опытный пользователь

Сообщений: 106



WWW
« Ответ #8 : 21 Сентябрь, 2014, 22:11:50 »

Потому что при отпускании, как правило, в key_flags установлен только Pk_KF_Cap_Valid (ещё может быть установлен Pk_KF_Scan_Valid, но scan в нашем случае не нужен) то есть валидны только key_cap.
« Последнее редактирование: 21 Сентябрь, 2014, 22:21:34 от Андрей Панченко » Записан

Сотрудник СВД Встраиваемые Системы
ad
Пользователь

Сообщений: 70


« Ответ #9 : 22 Сентябрь, 2014, 21:26:39 »

Так-с. Уже результаты поинтереснее.

Во-первых, PhEventEmit возвращает -1. Со следующим сообщением об ошибке:
Цитировать
Operation not permitted
У меня вызов функции PhEventEmit делается в функции, которая вызывается в параллельном потоке. Так можно?

Во-вторых, сделал следующий код из примера в документации прямо в функции main:
Код:
int main(int argc, char** argv)
{
// Something
// .....

/// Initialize Photon functions
phChannel = PhAttach(NULL, NULL);
if(!phChannel)
{
printf("Photon is not running.\n");
fflush(stdout);
return EXIT_FAILURE;
}

/// Temporary checks
PhEvent_t event;
PhRect_t rect;
PhRawKeyEvent_t ke;
memset(&event, 0, sizeof(PhEvent_t));
memset(&rect, 0, sizeof(PhRect_t));
memset(&ke, 0, sizeof(PhRawKeyEvent_t));

event.type = Ph_EV_KEY;
event.subtype = Ph_EV_RAW_KEY;
event.emitter.rid = Ph_DEV_RID;
//event.collector.rid = 0;
event.num_rects = 1;
event.data_len = sizeof(PhRawKeyEvent_t);
event.input_group = 1;
rect.ul.x = rect.ul.y = 0;
rect.lr.x = rect.lr.y = 0;
ke.key_flags = Pk_KF_Sym_Valid | Pk_KF_Cap_Valid | Pk_KF_Key_Down;
ke.key_mods = 0x0;
ke.key_cap = Pk_F1;
//ke.key_scan = 0x3b;
ke.key_sym = Pk_F1;

int em_ret = PhEventEmit(&event, &rect, &ke);
printf("em ret %i, key_cap 0x%x, [%s]\n", em_ret, ke.key_cap, strerror(errno));
fflush(stdout);

// Something
// ........
}


И этот код тоже em_ret вернул -1 со следующим сообщением:
Цитировать
em ret -1, key_cap 0xf0be, [No message of desired type]
Как же сделать правильно? Смотрел на следующий http://www.qnx.com/developers/docs/6.4.0/photon/prog_guide/events.html?lang=jp пример. Функция
Цитировать
static void send_key( long key )
Записан
Андрей Панченко
Сотрудник СВД ВС
Опытный пользователь

Сообщений: 106



WWW
« Ответ #10 : 22 Сентябрь, 2014, 22:08:07 »

QNX 4.25 отличается от QNX 6.25
Вот документация на PhEventEmit http://www.qnx.com/developers/docs/qnx_4.25_docs/photon114/lib_ref/ph/pheventemit.html
Цитировать
Returns:

0
    Success
-1
    An error occurred, or no further events are pending. Check the value of errno:

        If errno is ENOMSG, Photon had no messages enqueued to your application at the time you emitted the event.
        If errno isn't ENOMSG, an error occurred.

То есть 'No message of desired type' не является ошибкой в QNX 4.25.

Вопрос использования PhEventEmit  в потоке QNX 4.25 необходимо проработать.
Записан

Сотрудник СВД Встраиваемые Системы
ad
Пользователь

Сообщений: 70


« Ответ #11 : 23 Сентябрь, 2014, 05:47:34 »

QNX 4.25 отличается от QNX 6.25
То есть 'No message of desired type' не является ошибкой в QNX 4.25.
Ну хорошо, пусть не ошибка, но возвращается ведь -1, а хотелось бы увидеть, где код исполнялся бы полностью и без ошибок. Неужели даже пример с таким результатом???

Цитировать
Вопрос использования PhEventEmit  в потоке QNX 4.25 необходимо проработать.
?
Записан
Андрей Панченко
Сотрудник СВД ВС
Опытный пользователь

Сообщений: 106



WWW
« Ответ #12 : 23 Сентябрь, 2014, 11:51:22 »

Возврат -1 само по себе не означает возникновение ошибки. Если errno при этом равно ENOMSG, то это значит, что нет отложенных событий от Photon для вашего приложения. Ошибка если при возврате -1 errno установлено в отличное от ENOMSG значение.

Использование функции Photon в потоке не является безопасным. Если есть необходимость в разделении на потоки, то я бы советовал использовать функции Photon в отдельном приложении (в одном потоке), а полученные от клавиатуры данные передавать с помощью межпроцессного взаимодействия (IPC).

А ошибка 'Operation not permitted' говорит, скорeе всего о том, что отправляющий процесс (поток) не был подключён к Photon.
« Последнее редактирование: 23 Сентябрь, 2014, 14:58:13 от Андрей Панченко » Записан

Сотрудник СВД Встраиваемые Системы
ad
Пользователь

Сообщений: 70


« Ответ #13 : 23 Сентябрь, 2014, 20:28:06 »

Спасибо за объяснение. После того, как код, указанный выше, был перенесен в основной поток, эмуляция стала работать. Хотя, уже после работы, стал думать, что если бы я делал PhAttach в том потоке, в котором делал PhEventEmit, то, думаю, что тоже бы заработало.

Кстати, хочу добавить, что код компилирую и под QNX 4.25, и под QNX 6.5.0. Так вот для компиляции под четверку достаточно было в Makefile добавить следующее:
Код:
LDFLAGS		+=  -l photon

А для QNX 6.5.0
Код:
LDFLAGS+=l ph
LIBS+=-Bstatic ph -Bdynamic
Записан
ad
Пользователь

Сообщений: 70


« Ответ #14 : 23 Сентябрь, 2014, 20:33:05 »

Возврат -1 само по себе не означает возникновение ошибки. Если errno при этом равно ENOMSG, то это значит, что нет отложенных событий от Photon для вашего приложения.
А как сэмулировать так, чтобы PhEventEmit возвращал 0? Или такое поведение эмулировать нельзя. Спасибо огромное за помощь и подсказки.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP © 2002-2024 СВД Встраиваемые Системы.
При использовании материалов сайта ссылка на forum.kpda.ru обязательна.

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines | © Aiwan. Kolobok smiles | Sitemap
Valid XHTML 1.0! Valid CSS!
Сайт СВД ВС

В последний раз google посещал эту страницу 22 Апрель, 2024, 02:16:28