Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
6.0 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. modem.c
  5. Abstract:
  6. This module provides access to modems.
  7. Author:
  8. Wesley Witt (wesw) 22-Jan-1996
  9. Revision History:
  10. --*/
  11. BOOL
  12. SendModemCommand(
  13. HANDLE hFile,
  14. LPOVERLAPPED OverlappedWrite,
  15. LPSTR Command
  16. )
  17. /*++
  18. Routine Description:
  19. Sends an AT command to the modem.
  20. Arguments:
  21. hFile - File handle for the comm port.
  22. Command - AT Command
  23. Return Value:
  24. TRUE if the command is sent, FALSE otherwise
  25. --*/
  26. {
  27. DWORD Bytes;
  28. DWORD ec;
  29. if (!WriteFile(
  30. hFile,
  31. Command,
  32. strlen(Command),
  33. &Bytes,
  34. OverlappedWrite
  35. )) {
  36. //
  37. // the write failed
  38. //
  39. ec = GetLastError();
  40. if (ec == ERROR_IO_PENDING) {
  41. if (WaitForSingleObject( OverlappedWrite->hEvent, 10000 ) == WAIT_TIMEOUT) {
  42. //
  43. // write never completed
  44. //
  45. return FALSE;
  46. }
  47. if (!GetOverlappedResult( hFile, OverlappedWrite, &Bytes, FALSE )) {
  48. //
  49. // the write failed
  50. //
  51. return FALSE;
  52. }
  53. } else {
  54. return FALSE;
  55. }
  56. }
  57. return TRUE;
  58. }
  59. BOOL
  60. ReceiveModemResponse(
  61. HANDLE hFile,
  62. LPOVERLAPPED OverlappedRead,
  63. LPSTR Response,
  64. DWORD ResponseSize
  65. )
  66. /*++
  67. Routine Description:
  68. Receives a response from a modem.
  69. Arguments:
  70. hFile - File handle for the comm port.
  71. Response - Buffer to put the response into
  72. ResponseSize - Size of the response buffer
  73. Return Value:
  74. TRUE if the response is received, FALSE otherwise
  75. --*/
  76. {
  77. DWORD Bytes;
  78. DWORD ec;
  79. if (!ReadFile(
  80. hFile,
  81. Response,
  82. ResponseSize,
  83. &Bytes,
  84. OverlappedRead
  85. )) {
  86. //
  87. // the read failed
  88. //
  89. ec = GetLastError();
  90. if (ec == ERROR_IO_PENDING) {
  91. if (WaitForSingleObject( OverlappedRead->hEvent, 10000 ) == WAIT_TIMEOUT) {
  92. //
  93. // write never completed
  94. //
  95. return FALSE;
  96. }
  97. if (!GetOverlappedResult( hFile, OverlappedRead, &Bytes, FALSE )) {
  98. //
  99. // the write failed
  100. //
  101. return FALSE;
  102. }
  103. } else {
  104. return FALSE;
  105. }
  106. }
  107. Response[Bytes] = 0;
  108. // {
  109. // LPTSTR ResponseW = AnsiStringToUnicodeString( Response );
  110. // DebugPrint(( TEXT("bytes=%d, [%s]"), Bytes, ResponseW ));
  111. // MemFree( ResponseW );
  112. // }
  113. return TRUE;
  114. }
  115. BOOL
  116. IsResponseOk(
  117. LPSTR Response
  118. )
  119. /*++
  120. Routine Description:
  121. Verifies that a modem response is positive,
  122. that it contains the string "OK"
  123. Arguments:
  124. Response - Modem response
  125. Return Value:
  126. TRUE if the response is positive, FALSE otherwise
  127. --*/
  128. {
  129. Response = strchr( Response, 'O' );
  130. if (Response && Response[1] == 'K') {
  131. return TRUE;
  132. }
  133. return FALSE;
  134. }
  135. DWORD
  136. GetModemClass(
  137. HANDLE hFile
  138. )
  139. /*++
  140. Routine Description:
  141. Determines the lowest FAX class that the modem
  142. connected to the requested port supports.
  143. Arguments:
  144. PortName - Communications port name.
  145. Return Value:
  146. Class number.
  147. --*/
  148. {
  149. DWORD ModemClass = 0;
  150. DCB Dcb;
  151. CHAR Response[64];
  152. COMMTIMEOUTS cto;
  153. OVERLAPPED OverlappedRead;
  154. OVERLAPPED OverlappedWrite;
  155. ZeroMemory( &OverlappedRead, sizeof(OVERLAPPED) );
  156. ZeroMemory( &OverlappedWrite, sizeof(OVERLAPPED) );
  157. OverlappedRead.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  158. OverlappedWrite.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  159. if (!GetCommState( hFile, &Dcb )) {
  160. goto exit;
  161. }
  162. Dcb.BaudRate = CBR_2400;
  163. Dcb.fDtrControl = DTR_CONTROL_ENABLE;
  164. Dcb.fRtsControl = RTS_CONTROL_ENABLE;
  165. if (!SetCommState( hFile, &Dcb )) {
  166. goto exit;
  167. }
  168. cto.ReadIntervalTimeout = 1000;
  169. cto.ReadTotalTimeoutMultiplier = 0;
  170. cto.ReadTotalTimeoutConstant = 4 * 1000;
  171. cto.WriteTotalTimeoutMultiplier = 0;
  172. cto.WriteTotalTimeoutConstant = 4 * 1000;
  173. SetCommTimeouts( hFile, &cto );
  174. //
  175. // reset the modem
  176. //
  177. if (!SendModemCommand( hFile, &OverlappedWrite, "ATZ0\r" )) {
  178. goto exit;
  179. }
  180. if (!ReceiveModemResponse( hFile, &OverlappedRead, Response, sizeof(Response) )) {
  181. goto exit;
  182. }
  183. //
  184. // turn off echo
  185. //
  186. if (!SendModemCommand( hFile, &OverlappedWrite, "ATE0\r" )) {
  187. goto exit;
  188. }
  189. if (!ReceiveModemResponse( hFile, &OverlappedRead, Response, sizeof(Response) )) {
  190. goto exit;
  191. }
  192. //
  193. // H0 - go on hook
  194. // Q0 - enable modem responses
  195. // V1 - verbal modem responses (ok, error, etc)
  196. //
  197. if (!SendModemCommand( hFile, &OverlappedWrite, "ATH0Q0V1\r" )) {
  198. goto exit;
  199. }
  200. if (!ReceiveModemResponse( hFile, &OverlappedRead, Response, sizeof(Response) )) {
  201. goto exit;
  202. }
  203. if (!IsResponseOk( Response )) {
  204. goto exit;
  205. }
  206. if (!SendModemCommand( hFile, &OverlappedWrite, "AT+FCLASS=?\r" )) {
  207. goto exit;
  208. }
  209. if (!ReceiveModemResponse( hFile, &OverlappedRead, Response, sizeof(Response) )) {
  210. goto exit;
  211. }
  212. if (!IsResponseOk( Response )) {
  213. DebugPrint(( TEXT("bad modem response #2 [%s]"), Response ));
  214. goto exit;
  215. }
  216. if (strchr( Response, '1' )) {
  217. ModemClass = 1;
  218. } else if (strchr( Response, '2' )) {
  219. ModemClass = 2;
  220. }
  221. if (!SendModemCommand( hFile, &OverlappedWrite, "AT+FAE=1\r" )) {
  222. goto exit;
  223. }
  224. if (!ReceiveModemResponse( hFile, &OverlappedRead, Response, sizeof(Response) )) {
  225. goto exit;
  226. }
  227. exit:
  228. CloseHandle( OverlappedRead.hEvent );
  229. CloseHandle( OverlappedWrite.hEvent );
  230. if (ModemClass == 0) {
  231. DebugPrint(( TEXT("Could not detect modem class") ));
  232. }
  233. return ModemClass;
  234. }