Модемы и факс-модемы. Программирование для MS-DOS и Windows

       

Сообщение WM_COMMNOTIFY


Сообщение WM_COMMNOTIFY отправляется драйвером COM-порта в функцию окна и служит извещением об изменении состояния COM-порта. Такое сообщение может поступать в функцию окна при наполнении входной очереди до определенного порогового значения, изменении состояния сигналов DTR, RI, RTS и т. д.

Параметр wParam сообщения WM_COMMNOTIFY определяет идентификатор COM-порта, вызвавшего отправку сообщения.

Через младшее слово параметра lParam функция окна получает число, по которому можно судить о причине посылки сообщения WM_COMMNOTIFY. Это число может быть комбинацией следующих кодов извещения:

Код извещения

Описание

CN_EVENT

Произошло событие, разрешенное в слове событий COM-порта. Эти события разрешаются вызовом функции SetCommEventMask. После прихода сообщения WM_COMMNOTIFY с кодом извещения CN_EVENT приложение должно вызвать функцию GetCommEventMask, чтобы определить, какое именно событие произошло и сбросить событие



CN_RECEIVE

Очередь приемника содержит больше, чем cbWriteNotify байт. Пороговое значение cbWriteNotify задается одним из параметров функции EnableCommNotification

CN_TRANSMIT

Очередь передатчика содержит меньше, чем cbOutQueue байт. Пороговое значение cbOutQueue задается одним из параметров функции EnableCommNotification

Если приложение обработало поступившее ему сообщение WM_COMMNOTIFY, оно должно возвратить нулевое значение.

Сообщение WM_COMMNOTIFY с кодом извещения CN_EVENT передается только тогда, когда слово состояния событий изменяет свое значение. Приложение, которое принимает сообщение WM_COMMNOTIFY, должно каждый раз очищать слово состояния событий, для того чтобы гарантировать получение сообщений в дальнейшем.

      Использование функции EnableCommNotification для разрешения передачи сообщений WM_COMMNOTIFY с кодами извещения CN_RECEIVE и CN_TRANSMIT может вызвать генерацию ошибочных сообщений WM_COMMNOTIFY, для которых параметр NotifyStatus равен нулю. При обмене данными на высоких скоростях это может привести к аварийной ситуации и даже перезагрузке компьютера.


Для решения этой проблемы можно использовать следующие методы:

         Игнорировать все сообщения WM_COMMNOTIFY, для которых параметр NotifyStatus равен нулю

         Не использовать сообщения WM_COMMNOTIFY для событий CN_RECEIVE и CN_TRANSMIT

         Разрешить сообщение CN_EVENT для события EV_RXCHAR с помощью функций SetCommEventMask и EnableCommNotification. Сообщение формируется при поступлении во входную очередь очередного символа. Функцию EnableCommNotification следует вызывать с параметрами cbWriteNotify и cbOutQueue -1, чтобы сообщения CN_RECEIVE и CN_TRANSMIT не посылались. Этот метод продемонстрирован в приложении TTY из Windows Software Development Kit (SDK)

         Вместо использования функции EnableCommNotification приложение должно само периодически опрашивать входной буфер на наличие в нем принятых данных. Опрос можно производить по таймеру или в цикле обработки сообщений

         Заменить драйвер последовательного асинхронного адаптера COMM.DRV.

Событие CN_RECEIVE формируется в тех случаях, когда количество байт во входной очереди превышает пороговое значение cbWriteNotify, установленное функцией EnableCommNotification, или когда истекло время (тайм-аут). После формирования события CN_RECEIVE в случае превышения пороговой величины cbWriteNotify другие сообщения CN_RECEIVE не будут генерироваться до тех пор, пока количество байт во входной очереди не станет меньше значения cbWriteNotify и не превысит ее снова.

Сообщение CN_TRANSMIT создается аналогично CN_RECEIVE. Порог устанавливается параметром cbOutQueue функции EnableCommNotify. Когда количество символов в выходной очереди становится меньше, чем cbOutQueue, формируется сообщение CN_TRANSMIT. Другие сообщения CN_TRANSMIT не будут посылаться до тех пор, пока в буфере не станет больше, чем cbOutQueue символов.

Однако, если прерывания поступают достаточно быстро, дополнительные сообщения CN_RECEIVE (или CN_TRANSMIT) могут посылаться до того, как количество символов в выходной очереди станет больше, чем cbWriteNotify. Эти сообщения можно пропускать (игнорировать), однако они могут послужить причиной перезагрузки системы.



Ниже приведен фрагмент обработчика сообщения WM_COMMNOTIFY:

//==========================================================

// Функция окна WndProc

//==========================================================

LRESULT CALLBACK _export

WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

      switch( message )

      {

             case WM_COMMNOTIFY:

             {

                   if(CN_EVENT & LOWORD( lParam ) == CN_EVENT)

                   {

                         GetCommEventMask(COMDEV( npTTYInfo ), EV_RXCHAR);   

                         return(TRUE);

                   }

                   else if(CN_RECEIVE & LOWORD( lParam ) == CN_RECEIVE)

                   {

                         return(TRUE);

                   }

                   else if(CN_TRANSMIT & LOWORD( lParam ) == CN_TRANSMIT)

                   {

                         return(TRUE);

                   }

                                      else if(LOWORD( lParam ) == 0)

                         return(TRUE);

             }

             default:

                   return(DefWindowProc(hwnd, message, wParam, lParam));

      }

}

При загрузке драйвера последовательного асинхронного адаптера он вызывает функцию CreateSystemTimer и создает таймер, посылающий сообщения драйверу каждые 100 миллисекунд. Обрабатывая сообщения таймера, драйвер просматривает состояние всех открытых COM-портов и проводит проверку тайм-аута. Период таймера изменить нельзя.


Содержание раздела