TAPI для Windows Mobile

Телефония в смартфоне и карманном ПК

Существует два класса мобильных устройств, которые обладают функциями телефона и, соответственно, поддерживают интерфейс телефонии: смартфоны и гибридные карманные ПК (Pocket PC) с поддержкой телефонии, реализуемой в Windows Mobile (WM) через интерфейс TAPI.

Под телефонией в данном случае понимается не только обычные голосовые звонки, но и VoIP связь, управление журналом звонков, организация конференций, передача данных по ISDN/ADSL сетям, получение сервисной информации о линии или звонке и многое другое.

Telephony API

Обзор

Мобильные устройства на платформе WM CE поддерживают интерфейс телефонии Microsoft API (TAPI 2.0) и частично TAPI 2.1. TAPI – это API, который значительно упрощает процесс соединения двух и более устройств. Абстракции TAPI для управления вызовами облегчают работу с, казалось бы, разными протоколами взаимодействия  посредством абстракций под названием Telephony Service Provider (TSP).

Windows CE устройство по умолчанию поставляется с одним TSP – Unimodem Service Provider – провайдер универсального модема, которым можно управлять, используя AT команды. Тем не менее интерфейс TAPI позволяет инсталлировать дополнительные TSP сторонних разработчиков, чтобы обеспечить поддержку VoIP, H.323 (голосовые и видеоконференции), SIP, ISDN, сотовой связи и пр.

TAPI – совместная разработка компании Microsoft и Intel. TAPI находит широкое применение как в приложениях под PC на базе MS Windows, так и в в приложениях, работающих под управлением Windows CE. TAPI 2.1 CE – это значительно сокращенная версия полнофункциональной библиотеки телефонии TAPI 3.0. Схема TAPI 3.0 для Win 32 платформы приведена ниже:

Рис. 1 Детализированная схема TAPI 3

Схема TAPI CE несколько скромнее, по умолчанию здесь присутствует только один TSP:

Рис. 2 Интерфейс и компоненты Win CE TAPI. Укрупненная схема.

TAPI для мобильных телефонов делится на 5 подмножеств: Assisted API, Extended API, Phone API, Telephony API и TSP API. Рассмострим каждый из них в отдельности.

CE TAPI

Assisted TAPI

Assisted TAPI – данное подмножество состоит из единственного метода для выполнения обычного голосового звонка.

  1. LONG tapiRequestMakeCall (
  2. LPCTSTR lpszDestAddress,
  3. LPCTSTR lpszAppName = NULL,
  4. LPCTSTR lpszCalledParty,
  5. LPCTSTR lpszComment = NULL
  6. );

Header: astdtapi.h
Library: cellcore.lib

Примечание: ввиду различной реализации Assisted TAPI звонка и звонка через полнофункциональную Telephony API, не рекомендуется смешивать в одном приложении оба способа вызова адресата.

В карманных ПК Assisted TAPI работает только в CDMA сети.

2.2.2.    Extended TAPI

Extended TAPI – интерфейс для работы с беспроводным интерфейсом: запрос мощности сигнала, состояние передатчика и приемника, выбор оператора сотовой связи и пр. С помощью Extended API можно работать с CDMA, GSM, GPRS интерфейсами.
Все операции выполняются через сервис работы с линией.

Примеры методов:

  1. LONG WINAPI lineGetGeneralInfo(
  2. HLINE hLine,
  3. LPLINEGENERALINFO lpLineGeneralInfo
  4. );
  5.  
  6. typedef struct linegeneralinfo_tag {
  7. DWORD dwTotalSize;
  8. DWORD dwNeededSize;
  9. DWORD dwUsedSize;
  10. DWORD dwManufacturerSize;
  11. DWORD dwManufacturerOffset;
  12. DWORD dwModelSize;
  13. DWORD dwModelOffset;
  14. DWORD dwRevisionSize;
  15. DWORD dwRevisionOffset;
  16. DWORD dwSerialNumberSize;
  17. DWORD dwSerialNumberOffset;
  18. DWORD dwSubscriberNumberSize;
  19. DWORD dwSubscriberNumberOffset;
  20. } LINEGENERALINFO, * LPLINEGENERALINFO;
  21.  
  22. LONG WINAPI lineGetCurrentOperator(
  23. HLINE hLine,
  24. LPLINEOPERATOR lpCurrentOperator
  25. );
  26.  
  27. typedef struct lineoperator_tag {
  28. DWORD dwIndex;
  29. DWORD dwValidFields;
  30. DWORD dwStatus;
  31. TCHAR lpszLongName[MAX_LENGTH_OPERATOR_LONG];
  32. TCHAR lpszShortName[MAX_LENGTH_OPERATOR_SHORT];
  33. TCHAR lpszNumName[MAX_LENGTH_OPERATOR_NUMERIC];
  34. } LINEOPERATOR, * LPLINEOPERATOR;

Всего определено около 30 функций.

Header: extapi.h.
Library: сellcore.lib

Phone API

Phone API – интерфейс для работы с журналом вызовов (Call Log), а также со временем и оплатой вызовов (Billing). Данное подмножество TAPI имеет наибольшее практическое применение.
Все входящие, исходящие, пропущенные звонки сохраняются во внутренней таблице журнала вызовов. С помощью функций Phone API можно получать информацию о звонках из этой таблицы, фильтровать, сортировать, удалять и пр.

Данный интерфейс поддерживается только в смартфонах и гибридных карманных ПК.

Функции Phone API:

  • PhoneAddSpeedDial – добавить запись в таблицу быстрого набора
  • PhoneMakeCall – позвонить
  • PhoneOpenCallLog – открыть журнал вызовов
  • PhoneGetCallLogEntry – получить журнал вызовов
  • PhoneCloseCallLog  – закрыть журнал вызовов
  • PhoneSeekCallLog – позиционировать в журнале вызовов на определенную запись
  • PhoneShowCallLog – показывает Call Log с указанным фильтром

Работа с журналом вызовов схожа с работой с типизированными файлами, где каждая запись – это структура. Вначале необходимо открыть Call Log, получив дескриптор. Затем с помощью функции PhoneGetCallLogEntry читать последовательно по записи. В конце работы с журналом – закрыть его.
Есть возможность позиционировать маркер в файле на определенную запись.
С помощью позиционирования можно также получить общее кол-во записей в журнале.

Прототип функции извлечения записи журнала вызовов:

  1. HRESULT PhoneGetCallLogEntry(
  2. HANDLE h,
  3. PCALLLOGENTRY pentry
  4. );
  5.  
  6. typedef struct {
  7. DWORD cbSize;
  8. FILETIME ftStartTime;
  9. FILETIME ftEndTime;
  10. IOM iom;
  11. BOOL fOutgoing:1;
  12. BOOL fConnected:1;
  13. BOOL fEnded:1;
  14. BOOL fRoam:1;
  15. CALLERIDTYPE cidt;
  16. PTSTR pszNumber;
  17. PTSTR pszName;
  18. PTSTR pszNameType;
  19. PTSTR pszNote;
  20. } CALLLOGENTRY, * PCALLLOGENTRY;

Из журнала вызовов можно извлечь следующую информацию:

  • Время начала звонка
  • Время окончания звонка
  • Тип: входящий принятый, входящий пропущенный, исходящий
  • Как закончился звонок: штатно или был сброшен
  • Звонок в Home Area или в роуминге
  • Информация о CallerID: доступна, заблокирована, не доступна
  • Номер абонента
  • Имя абонента
  • Тип телефона абонента: домашний, рабочий (из адресной книги)

Header: phone.h
Library: phone.lib

Telephony API

Telephony API состоит из двух интерфейсов: работа с линией и работа с телефоном.

Телефон

Телефон – это абстракция, описывающая микрофон, динамик, модуль беспроводной связи и т.д.

С помощью функций для работы с телефоном можно как получить статус телефона, настройки вызова, состояние спикерфона, так и изменить настройки.

Например,

  1. LONG WINAPI phoneGetStatus(
  2. HPHONE hPhone,
  3. LPPHONESTATUS lpPhoneStatus
  4. );
  5.  
  6. typedef struct phonestatus_tag {
  7. DWORD dwTotalSize;
  8. DWORD dwNeededSize;
  9. DWORD dwUsedSize;
  10. DWORD dwStatusFlags;
  11. DWORD dwNumOwners;
  12. DWORD dwNumMonitors;
  13. DWORD dwRingMode;
  14. DWORD dwRingVolume;
  15. DWORD dwHandsetHookSwitchMode;
  16. DWORD dwHandsetVolume;
  17. DWORD dwHandsetGain;
  18. DWORD dwSpeakerHookSwitchMode;
  19. DWORD dwSpeakerVolume;
  20. DWORD dwSpeakerGain;
  21. DWORD dwHeadsetHookSwitchMode;
  22. DWORD dwHeadsetVolume;
  23. DWORD dwHeadsetGain;
  24. DWORD dwDisplaySize;
  25. DWORD dwDisplayOffset;
  26. DWORD dwLampModesSize;
  27. DWORD dwLampModesOffset;
  28. DWORD dwOwnerNameSize;
  29. DWORD dwOwnerNameOffset;
  30. DWORD dwDevSpecificSize;
  31. DWORD dwDevSpecificOffset;
  32. DWORD dwPhoneFeatures;
  33. } PHONESTATUS, FAR* LPPHONESTATUS;

Наиболее полезные с практической точки зрения функции:

  • phoneConfigDialog – открыть диалог настроек телефона
  • phoneGetDevCaps – получить данные о TAPI и телефоне (версия, DeviceID…)
  • phoneGetGain/phoneSetGain – получить /установить уровень чувствительности микрофона
  • phoneGetMessage – получить следующее сервисное сообщение TAPI
  • phoneGetStatus – получить статус телефона
  • phoneGetRing/phoneSetRing – получить/установить тип звонка и громкость

Всего чуть больше 20 функций.

Header: tapi.h.
Library: coredll.lib.

Линия

Под линией понимается абстракция, обозначающая телефонную линию. Она может содержать один или несколько коммуникационных каналов. В большинстве случаев обстракции ‘линия’ и ‘телефон’ имеют отношение “один к одному”. Но возможны случаи, когда одна линия связана с несколькими телефонами (в случае ISDN).

С помощью функций для работы с линией можно ‘звонить’, отвечать на вызовы, выполнять переадресацию, удерживать абонента на линии, организовывать конференции, получать статус линии и конфигурировать ее.

Например,

  1. LONG WINAPI lineAnswer(
  2. HCALL hCall,
  3. LPCSTR lpsUserUserInfo,
  4. DWORD dwSize
  5. );
  6.  
  7. LONG WINAPI lineDial(
  8. HCALL hCall,
  9. LPCWSTR lpszDestAddress,
  10. DWORD dwCountryCode
  11. );
  12.  
  13. LONG WINAPI lineGetCallInfo(
  14. HCALL hCall,
  15. LPLINECALLINFO lpCallInfo
  16. );
  17.  
  18. typedef struct linecallinfo_tag {
  19. DWORD dwTotalSize;
  20. DWORD dwNeededSize;
  21. DWORD dwUsedSize;
  22. HLINE hLine;
  23. DWORD dwLineDeviceID;
  24. DWORD dwAddressID;
  25. DWORD dwBearerMode;
  26. DWORD dwRate;
  27. DWORD dwMediaMode;
  28. DWORD dwAppSpecific;
  29. DWORD dwCallID;
  30. DWORD dwRelatedCallID;
  31. DWORD dwCallParamFlags;
  32. DWORD dwCallStates;
  33. DWORD dwMonitorDigitModes;
  34. DWORD dwMonitorMediaModes;
  35. LINEDIALPARAMS DialParams;
  36. DWORD dwOrigin;
  37. DWORD dwReason;
  38. DWORD dwCompletionID;
  39. DWORD dwNumOwners;
  40. DWORD dwNumMonitors;
  41. DWORD dwCountryCode;
  42. DWORD dwTrunk;
  43. DWORD dwCallerIDFlags;
  44. DWORD dwCallerIDSize;
  45. DWORD dwCallerIDOffset;
  46. DWORD dwCallerIDNameSize;
  47. DWORD dwCallerIDNameOffset;
  48. DWORD dwCalledIDFlags;
  49. DWORD dwCalledIDSize;
  50. DWORD dwCalledIDOffset;
  51. DWORD dwCalledIDNameSize;
  52. DWORD dwCalledIDNameOffset;
  53. DWORD dwConnectedIDFlags;
  54. DWORD dwConnectedIDSize;
  55. DWORD dwConnectedIDOffset;
  56. DWORD dwConnectedIDNameSize;
  57. DWORD dwConnectedIDNameOffset;
  58. DWORD dwRedirectionIDFlags;
  59. DWORD dwRedirectionIDSize;
  60. DWORD dwRedirectionIDOffset;
  61. DWORD dwRedirectionIDNameSize;
  62. DWORD dwRedirectionIDNameOffset;
  63. DWORD dwRedirectingIDFlags;
  64. DWORD dwRedirectingIDSize;
  65. DWORD dwRedirectingIDOffset;
  66. DWORD dwRedirectingIDNameSize;
  67. DWORD dwRedirectingIDNameOffset;
  68. DWORD dwAppNameSize;
  69. DWORD dwAppNameOffset;
  70. DWORD dwDisplayableAddressSize;
  71. DWORD dwDisplayableAddressOffset;
  72. DWORD dwCalledPartySize;
  73. DWORD dwCalledPartyOffset;
  74. DWORD dwCommentSize;
  75. DWORD dwCommentOffset;
  76. DWORD dwDisplaySize;
  77. DWORD dwDisplayOffset;
  78. DWORD dwUserUserInfoSize;
  79. DWORD dwUserUserInfoOffset;
  80. DWORD dwHighLevelCompSize;
  81. DWORD dwHighLevelCompOffset;
  82. DWORD dwLowLevelCompSize;
  83. DWORD dwLowLevelCompOffset;
  84. DWORD dwChargingInfoSize;
  85. DWORD dwChargingInfoOffset;
  86. DWORD dwTerminalModesSize;
  87. DWORD dwTerminalModesOffset;
  88. DWORD dwDevSpecificSize;
  89. DWORD dwDevSpecificOffset;
  90. } LINECALLINFO, FAR* LPLINECALLINFO;

Всего около 50 функций.

Header: tapi.h.
Library: coredll.lib.

Telephony Service Provider (TSP) API

TSP API – это прослойка между Win CE TAPI интерфейсом, с которым работает разработчик и устройством, через которое происходит взаимодействие с внешним миром, оформленная в виде DLL. Верхний уровень TSP предоставляет разработчику унифицированный интерфейс, а низкоуровневый интерфейс TSP работает непосредственно с устройством.

Алгоритм работы

Рассмотрим пример работы с TAPI:

Инициализация линии

  1. LONG WINAPI lineInitialize(
  2. LPHLINEAPP          lphLineApp,
  3. HINSTANCE           hInstance,
  4. LINECALLBACK        lpfnCallback,
  5. LPCWSTR             lpszAppName,
  6. LPDWORD             lpdwNumDevs
  7. );

Данная функция принимает callback функцию, через которую приложение нотифицируется о входящих звонках, изменениях состояния линии и пр.

Фрагмент инициализации TAPI:

  1. VOID CALLBACK lineCallbackFunc(
  2. DWORD hDevice,
  3. DWORD dwMsg,
  4. DWORD dwCallbackInstance,
  5. DWORD dwParam1,
  6. DWORD dwParam2,
  7. DWORD dwParam3)
  8. {
  9. switch (dwMsg)
  10. {
  11. case LINE_CALLSTATE:    // Sent after change of call state
  12.  
  13. // dwParam1 is the specific CALLSTATE change that is occurring.
  14. switch (dwParam1)
  15. {
  16. case LINECALLSTATE_DIALTONE:
  17. lpszStatus = TEXT("Dial tone");
  18. break;
  19.  
  20. case LINECALLSTATE_DIALING:
  21. lpszStatus = TEXT("Dialing…");
  22. break;
  23.  
  24. case LINECALLSTATE_PROCEEDING:
  25. lpszStatus = TEXT("Dialing completed, call proceeding.");
  26. break;
  27.  
  28. case LINECALLSTATE_RINGBACK:
  29. lpszStatus = TEXT("Ring back");
  30. break;
  31.  
  32. case LINECALLSTATE_CONNECTED:
  33. lpszStatus = TEXT("Connected");
  34. break;
  35.  
  36. case LINECALLSTATE_BUSY:
  37. lpszStatus = TEXT("Line busy, shutting down.");
  38. bCloseLine = TRUE;
  39. break;
  40.  
  41. case LINECALLSTATE_IDLE:
  42. lpszStatus = TEXT("Line is idle");
  43. break;
  44.  
  45. case LINECALLSTATE_SPECIALINFO:
  46. lpszStatus =TEXT("Special Information, couldn’t dial number");
  47. bCloseLine = TRUE;
  48. break;
  49.  
  50. case LINECALLSTATE_DISCONNECTED:
  51. {
  52. LPTSTR lpszDisconnected;
  53. lpszDisconnected = TEXT(" ");
  54.  
  55. switch (dwParam2)
  56. {
  57. case LINEDISCONNECTMODE_NORMAL:
  58. lpszDisconnected = TEXT("Remote party disconnected");
  59. break;
  60.  
  61. case LINEDISCONNECTMODE_UNKNOWN:
  62. lpszDisconnected = TEXT("Disconnected: Unknown reason");
  63. break;
  64.  
  65. case LINEDISCONNECTMODE_REJECT:
  66. lpszDisconnected = TEXT("Remote Party rejected call");
  67. break;
  68.  
  69. case LINEDISCONNECTMODE_PICKUP:
  70. lpszDisconnected =
  71. TEXT("Disconnected: Local phone picked up");
  72. break;
  73.  
  74. case LINEDISCONNECTMODE_FORWARDED:
  75. lpszDisconnected = TEXT("Disconnected: Forwarded");
  76. break;
  77.  
  78. case LINEDISCONNECTMODE_BUSY:
  79. lpszDisconnected = TEXT("Disconnected: Busy");
  80. break;
  81.  
  82. case LINEDISCONNECTMODE_NOANSWER:
  83. lpszDisconnected = TEXT("Disconnected: No Answer");
  84. break;
  85.  
  86. case LINEDISCONNECTMODE_BADADDRESS:
  87. lpszDisconnected = TEXT("Disconnected: Bad address");
  88. break;
  89.  
  90. case LINEDISCONNECTMODE_UNREACHABLE:
  91. lpszDisconnected = TEXT("Disconnected: Unreachable");
  92. break;
  93.  
  94. case LINEDISCONNECTMODE_CONGESTION:
  95. lpszDisconnected = TEXT("Disconnected: Congestion");
  96. break;
  97.  
  98. case LINEDISCONNECTMODE_INCOMPATIBLE:
  99. lpszDisconnected = TEXT("Disconnected: Incompatible");
  100. break;
  101.  
  102. case LINEDISCONNECTMODE_UNAVAIL:
  103. lpszDisconnected = TEXT("Disconnected: Unavailable");
  104. break;
  105.  
  106. case LINEDISCONNECTMODE_NODIALTONE:
  107. lpszDisconnected = TEXT("Disconnected: No dial tone");
  108. break;
  109.  
  110. default:
  111. lpszDisconnected = TEXT("Disconnected: Unknown reason");
  112. break;
  113. }    // end switch (dwParam2)
  114.  
  115. bCloseLine = TRUE;
  116. wcscpy(lpszStatus,lpszDisconnected);
  117. break;
  118. }       // end case LINECALLSTATE_DISCONNECTED:
  119. }          // end switch (dwParam1)
  120.  
  121. if (g_hwndDial)
  122. SendDlgItemMessage(g_hwndDial, IDC_STATUSMESSAGE, WM_SETTEXT,
  123. 0,(LPARAM)lpszStatus);
  124.  
  125. if (bCloseLine)
  126. {
  127. CurrentLineClose ();
  128. if (g_hwndDial)
  129.  
  130. SendMessage (g_hwndDial, WM_COMMAND, MAKEWPARAM(IDOK,0), 0);
  131. }
  132. break;
  133. ….
  134. }
  135.  
  136. HLINEAPP g_hLineApp;
  137. DWORD dwNumDevices = 0;
  138. DWORD dwRet = ::lineInitialize(&g_hLineApp,g_hInst,
  139. (LINECALLBACK)LineCallbackFunc,
  140. _T("Developer.com Test"),
  141. &dwNumDevices);
  142.  
  143. if ( dwRet != 0 )
  144. {
  145. // Report error
  146. }

Для завершения работы с линией, ее нужно деинициализировать.

  1. lReturn = ::lineShutdown(m_hLineApp);

Ссылки

  • http://msdn.microsoft.com/en-us/library/aa454282.aspx
  • “Chapter 8. Pocket PC Phone Edition”
    Pocket PC Network Programming, By Steve Makofsky
    Publisher : Addison Wesley
    Pub Date : July 11, 2003
    ISBN : 0-321-13352-8
    Pages : 656

(c) 2008 Г. Земсков

Ваши комментарии:

также вы можете зарегистрироваться
Подпишитесь на новые записи моего блога:
Добавить в закладки: (в том числе и в Twitter)

Читайте также:

  • Недокументированные трюки для Windows Mobile 6
  • Windows Mobile Power Manager
  • Windows Mobile 6.5
  • Закрываются GPRS соединения при закрытии приложения
  • Тестирование мобильных приложений