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.

2053 lines
60 KiB

  1. /*******************************************************************************
  2. * Copyright (c) 1997 Gemplus developpement
  3. *
  4. * Name : GNTSER.C (Gemplus Win NT SERial port management)
  5. *
  6. * Description : This module holds the functions needed for a communication on a
  7. * serial line.
  8. *
  9. * Compiler : Microsoft DDK for Windows NT
  10. *
  11. * Host : IBM PC and compatible machines under Windows NT4
  12. *
  13. * Release : 1.00.002
  14. *
  15. * Last Modif : 01/12/97: V1.00.002 (TFB)
  16. * - Change IOCTL_SMARTCARD_WRITE and IOCTL_SMARTCARD_READ in
  17. * respectively GTSER_IOCTL_WRITE and GTSER_IOCTL_READ.
  18. * 07/07/97: V1.00.001 (GPZ)
  19. * - Start of development.
  20. *
  21. ********************************************************************************
  22. *
  23. * Warning :
  24. *
  25. * Remark :
  26. *
  27. *******************************************************************************/
  28. /*------------------------------------------------------------------------------
  29. Include section:
  30. - stdio.h: standards definitons.
  31. - ntddk.h: DDK Windows NT general definitons.
  32. - ntddser.h: DDK Windows NT serial management definitons.
  33. ------------------------------------------------------------------------------*/
  34. #include <stdio.h>
  35. #include <ntddk.h>
  36. #include <ntddser.h>
  37. /*------------------------------------------------------------------------------
  38. - smclib.h: smart card library definitions.
  39. ------------------------------------------------------------------------------*/
  40. #define SMARTCARD_POOL_TAG 'cGCS'
  41. #include <smclib.h>
  42. /*------------------------------------------------------------------------------
  43. - gemcore.h: Gemplus general definitions for the GemCore smart card reader.
  44. - gntser.h is used to define general macros and values for serial management.
  45. - gntscr09.h: public interface definition for the reader.
  46. - gioctl09.h: public interface definition for IOCTL functions.
  47. ------------------------------------------------------------------------------*/
  48. #include "gemcore.h"
  49. #include "gntscr09.h"
  50. #include "gioctl09.h"
  51. #include "gntser.h"
  52. /*------------------------------------------------------------------------------
  53. Type section:
  54. TPORT_CONFIG:
  55. - WaitRelease holds the timeout for the release of the semaphore.
  56. - Counter holds the number of opened session. If its value is 0, the port is
  57. closed.
  58. - Error holds Rx over state.
  59. - TimeOut holds the character level time out.
  60. - TxSize memorises the transmit buffer size.
  61. - RxSize memorises the reception buffer size.
  62. - InitRts memorises the initial Rts signal state.
  63. - InitDtr memorises the initial Dtr signal state.
  64. - Access is TRUE if the access is free, else FALSE if the channel access
  65. is locked.
  66. - pSerialPortDevice is a pointer on the serial Device Object.
  67. - pSerialFileObject is a pointer on the serial FileObject. Is needed to
  68. close the connection to the serial port.
  69. - GTSER_IOCTL_WRITE io control to write a buffer on a serial port.
  70. - GTSER_IOCTL_READ io control to read a buffer on a serial port.
  71. ------------------------------------------------------------------------------*/
  72. typedef struct
  73. {
  74. PIRP Irp;
  75. KEVENT Event;
  76. IO_STATUS_BLOCK IoStatus;
  77. KDPC Dpc;
  78. } CARD_STATUS;
  79. typedef struct
  80. {
  81. DWORD WaitRelease;
  82. WORD16 Counter;
  83. INT16 Error;
  84. WORD16 TimeOut;
  85. WORD16 TxSize;
  86. WORD16 RxSize;
  87. WORD16 InitRts;
  88. WORD16 InitDtr;
  89. INT32 Access;
  90. PDEVICE_OBJECT pSerialPortDevice;
  91. PFILE_OBJECT pSerialFileObject;
  92. PKMUTEX pExchangeMutex;
  93. } TPORT_CONFIG;
  94. #define GTSER_DEF_WAIT_RELEASE 2000
  95. #define GTSER_IOCTL_WRITE SCARD_CTL_CODE(1001)
  96. #define GTSER_IOCTL_READ SCARD_CTL_CODE(1000)
  97. /*------------------------------------------------------------------------------
  98. Macro section:
  99. - CTRL_BAUD_RATE control the baud rate parameter.
  100. - WORD_LEN, PARITY and STOP retreive the configuration values to pass to
  101. Windows to configure the port.
  102. ------------------------------------------------------------------------------*/
  103. #define WORD_LEN(x) (BYTE)(((x) & 0x03) + 5)
  104. #define PARITY(x) (BYTE)(parity[((BYTE)(x) >> 3) & 3])
  105. #define STOP(x) (BYTE)(stop[((x) >> 2) & 1])
  106. /*------------------------------------------------------------------------------
  107. Global variable section:
  108. - port_config is an array of TPORT_CONFIG which memorises the port
  109. configuration at each time.
  110. ------------------------------------------------------------------------------*/
  111. TPORT_CONFIG
  112. port_config[HGTSER_MAX_PORT] =
  113. {
  114. {0,0,0,0,0,0,0,0,TRUE,NULL,NULL},
  115. {0,0,0,0,0,0,0,0,TRUE,NULL,NULL},
  116. {0,0,0,0,0,0,0,0,TRUE,NULL,NULL},
  117. {0,0,0,0,0,0,0,0,TRUE,NULL,NULL}
  118. };
  119. static WORD16
  120. parity[] = {NO_PARITY,
  121. ODD_PARITY,
  122. NO_PARITY,
  123. EVEN_PARITY};
  124. static WORD16
  125. stop[] = {STOP_BIT_1,
  126. STOP_BITS_2};
  127. /*------------------------------------------------------------------------------
  128. Local function definition section:
  129. ------------------------------------------------------------------------------*/
  130. static NTSTATUS GDDKNT_SetupComm
  131. (
  132. const INT16 Handle,
  133. const ULONG InSize,
  134. const ULONG OutSize
  135. );
  136. static NTSTATUS GDDKNT_GetCommStatus
  137. (
  138. const INT16 Handle,
  139. SERIAL_STATUS *SerialStatus
  140. );
  141. static NTSTATUS GDDKNT_ResetComm
  142. (
  143. const INT16 Handle
  144. );
  145. static NTSTATUS GDDKNT_PurgeComm
  146. (
  147. const INT16 Handle,
  148. const ULONG Select
  149. );
  150. /*******************************************************************************
  151. * INT16 G_SerPortOpen
  152. * (
  153. * const TGTSER_PORT *Param
  154. * )
  155. *
  156. * Description :
  157. * -------------
  158. * This routine opens a serial port and initializes it according to the
  159. * parameters found in Param.
  160. *
  161. * Remarks :
  162. * -------------
  163. * Nothing.
  164. *
  165. * In :
  166. * -------------
  167. * Param holds the following parameters:
  168. * - Port indicates the selected port: G_COM1 (1), G_COM2 (2), G_COM3 (3) or
  169. * G_COM4 (4).
  170. * - BaudRate is used to set port baud rate: 110, 150, 300, 600, 1200, 2400,
  171. * 4800, 9600, 19200, 38400 or 57600.
  172. * A value greater than 57600 is reduced to 57600 !
  173. * - Mode gathers
  174. * * word size WORD_5 (0), WORD_6 (1), WORD_7 (2) or WORD_8 (3),
  175. * * stop bit number STOP_BIT_1 (0) or STOP_BIT_2 (4) and
  176. * * parity NO_PARITY (0), ODD_PARITY (8) or EVEN_PARITY (24).
  177. * - TimeOut indicates the time out value, in milli-seconds, at character level.
  178. * - TxSize is the transmit buffer size, in bytes.
  179. * - RxSize is the reception buffer size, in mbytes.
  180. *
  181. * Out :
  182. * -------------
  183. * Nothing.
  184. *
  185. * Responses :
  186. * -------------
  187. * If everything is OK:
  188. * - a handle on the port channel (>= 0).
  189. * If an error condition is raised:
  190. * - GE_HOST_PORT_ABS (- 401) if port is not found on host or is locked by
  191. * another device.
  192. * - GE_HOST_PORT_OPEN (- 411) if the port is already opened.
  193. * - GE_HOST_MEMORY (- 420) if a memory allocation fails.
  194. * - GE_HOST_PARAMETERS(- 450) if one of the given parameters is out of the
  195. * allowed range or is not supported by hardware.
  196. * - GE_UNKNOWN_PB (-1000) if an unexpected problem is encountered.
  197. *
  198. Extern var :
  199. -------------
  200. Nothing.
  201. Global var :
  202. -------------
  203. com_name gives the DOS level port name
  204. device_ctrl is used to hold the string requred by BuildCommDCB.
  205. parity gives the DOS level parity name
  206. port_config is set with the selected configuration.
  207. *******************************************************************************/
  208. INT16 G_SerPortOpen(const TGTSER_PORT *Param)
  209. {
  210. /*------------------------------------------------------------------------------
  211. Local variables:
  212. - Handle holds the handle associated to the given port. It is calculated
  213. by the following formula Port - 1.
  214. - response holds the called function responses.
  215. - current_dcb is used to set parameters in the device control block.
  216. ------------------------------------------------------------------------------*/
  217. INT16
  218. Handle = (INT16)(Param->Port - 1);
  219. NTSTATUS
  220. status;
  221. PSMARTCARD_EXTENSION
  222. SmartcardExtension;
  223. SERIAL_READER_CONFIG
  224. SerialConfig;
  225. PREADER_EXTENSION
  226. pReaderExtension;
  227. /*------------------------------------------------------------------------------
  228. Controls the given parameters:
  229. <= Test the port number (G_COM1 .. G_COM4): GE_HOST_PARAMETERS
  230. ------------------------------------------------------------------------------*/
  231. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  232. {
  233. return (GE_HOST_PARAMETERS);
  234. }
  235. /*------------------------------------------------------------------------------
  236. <= Test the port access state : GE_HOST_PORT_LOCKED
  237. ------------------------------------------------------------------------------*/
  238. if (port_config[Handle].Access == FALSE)
  239. {
  240. return (GE_HOST_PORT_LOCKED);
  241. }
  242. /*------------------------------------------------------------------------------
  243. <= Test the port state (Counter field null): GE_HOST_PORT_OPEN
  244. ------------------------------------------------------------------------------*/
  245. if (port_config[Handle].Counter != 0)
  246. {
  247. return (GE_HOST_PORT_OPEN);
  248. }
  249. /*------------------------------------------------------------------------------
  250. Retrieve the SmartcardExtension structure of the current device.
  251. ------------------------------------------------------------------------------*/
  252. SmartcardExtension = (PSMARTCARD_EXTENSION)(Param->pSmartcardExtension);
  253. pReaderExtension = SmartcardExtension->ReaderExtension;
  254. port_config[Handle].pSerialPortDevice = pReaderExtension->ConnectedSerialPort;
  255. port_config[Handle].pSerialFileObject = pReaderExtension->SerialFileObject;
  256. port_config[Handle].pExchangeMutex = &pReaderExtension->ExchangeMutex;
  257. /*------------------------------------------------------------------------------
  258. The current port state is read and stored in current_dcb structure by
  259. calling GetCommState function.
  260. If the reading is possible (GetCommState return 0)
  261. Then
  262. The current_dcb structure is updated with the given parameter (baud
  263. rate, ByteSize, Parity, StopBits).
  264. The modified state is written by calling SetCommState.
  265. ------------------------------------------------------------------------------*/
  266. status = GDDKNT_GetCommState(Handle,&SerialConfig);
  267. if (NT_SUCCESS(status))
  268. {
  269. status = GDDKNT_SetupComm(Handle,4096L,4096L);
  270. /*------------------------------------------------------------------------------
  271. Set the serial port communication parameters
  272. ------------------------------------------------------------------------------*/
  273. SerialConfig.BaudRate.BaudRate = Param->BaudRate;
  274. SerialConfig.LineControl.WordLength = WORD_LEN(Param->Mode);
  275. SerialConfig.LineControl.Parity = PARITY(Param->Mode);
  276. SerialConfig.LineControl.StopBits = STOP(Param->Mode);
  277. SerialConfig.WaitMask = SERIAL_EV_RXCHAR;
  278. /*------------------------------------------------------------------------------
  279. Set timeouts
  280. ------------------------------------------------------------------------------*/
  281. SerialConfig.Timeouts.ReadIntervalTimeout = 1000;
  282. SerialConfig.Timeouts.ReadTotalTimeoutConstant = 5000;
  283. SerialConfig.Timeouts.ReadTotalTimeoutMultiplier = 50;
  284. /*------------------------------------------------------------------------------
  285. Set special characters
  286. ------------------------------------------------------------------------------*/
  287. SerialConfig.SerialChars.ErrorChar = 0;
  288. SerialConfig.SerialChars.EofChar = 0;
  289. SerialConfig.SerialChars.EventChar = 0;
  290. SerialConfig.SerialChars.XonChar = 0;
  291. SerialConfig.SerialChars.XoffChar = 0;
  292. SerialConfig.SerialChars.BreakChar = 0xFF;
  293. /*------------------------------------------------------------------------------
  294. Set handflow
  295. ------------------------------------------------------------------------------*/
  296. SerialConfig.HandFlow.XonLimit = 0;
  297. SerialConfig.HandFlow.XoffLimit = 0;
  298. SerialConfig.HandFlow.FlowReplace = SERIAL_XOFF_CONTINUE ;
  299. SerialConfig.HandFlow.ControlHandShake = 0;
  300. status = GDDKNT_SetCommState(Handle,&SerialConfig);
  301. }
  302. /*------------------------------------------------------------------------------
  303. Else
  304. response is set with IE_DEFAULT error value.
  305. ------------------------------------------------------------------------------*/
  306. else
  307. {
  308. return (GE_HOST_PARAMETERS);
  309. }
  310. /*------------------------------------------------------------------------------
  311. Treats system error codes:
  312. If an error has occured (response < 0)
  313. Then
  314. switch response value:
  315. IE_OPEN, IE_BAD_ID and IE_HARDWARE
  316. <= GE_HOST_PORT_ABS
  317. IE_MEMORY
  318. <= GE_HOST_MEMORY
  319. IE_BAUDRATE, IE_BYTESIZE, IE_DEFAULT
  320. <= GE_HOST_PARAMETERS
  321. default
  322. <= GE_UNKNOWN_PB
  323. ------------------------------------------------------------------------------*/
  324. if (!NT_SUCCESS(status))
  325. {
  326. switch (status)
  327. {
  328. case STATUS_INSUFFICIENT_RESOURCES:
  329. {
  330. return (GE_HOST_MEMORY);
  331. }
  332. case STATUS_BUFFER_TOO_SMALL:
  333. {
  334. return (GE_HOST_PARAMETERS);
  335. }
  336. default :
  337. {
  338. return (GE_UNKNOWN_PB);
  339. }
  340. }
  341. }
  342. /*------------------------------------------------------------------------------
  343. Memorises the given parameters in port_config structure.
  344. Counter, Error, TimeOut, TxSize and RxSize fields are updated.
  345. ------------------------------------------------------------------------------*/
  346. port_config[Handle].Counter = 1;
  347. port_config[Handle].Error = 0;
  348. port_config[Handle].TimeOut = Param->TimeOut;
  349. port_config[Handle].TxSize = Param->TxSize;
  350. port_config[Handle].RxSize = Param->RxSize;
  351. /*------------------------------------------------------------------------------
  352. <= the handle value.
  353. ------------------------------------------------------------------------------*/
  354. return (Handle);
  355. }
  356. /*******************************************************************************
  357. * INT16 G_SerPortAddUser
  358. * (
  359. * const INT16 Port
  360. * )
  361. *
  362. * Description :
  363. * -------------
  364. * Add a new user on a port. This function return the handle of a previously
  365. * opened port.
  366. *
  367. * Remarks :
  368. * -------------
  369. * When this function is successful, it is mandatory to call G_SerPortClose
  370. * to decrement the user number.
  371. *
  372. * In :
  373. * -------------
  374. * - Port indicates the selected port: G_COM2 (1), G_COM2 (2), G_COM3 (3) or
  375. * G_COM4 (4).
  376. *
  377. * Out :
  378. * -------------
  379. * Nothing.
  380. *
  381. * Responses :
  382. * -------------
  383. * If everything is OK:
  384. * a handle on the port channel (>= 0)
  385. * If an error condition is raised:
  386. * - GE_HOST_PORT_CLOSE (-412) if port is closed.
  387. * - GE_HOST_RESOURCES (-430) if too many users hold the port.
  388. * - GE_HOST_PARAMETERS (-450) if the given handle is out of the allowed range.
  389. *
  390. Extern var :
  391. -------------
  392. Nothing.
  393. Global var :
  394. -------------
  395. port_config memorises the port configuration.
  396. *******************************************************************************/
  397. INT16 G_SerPortAddUser
  398. (
  399. const INT16 Port
  400. )
  401. {
  402. /*------------------------------------------------------------------------------
  403. Controls the given parameters:
  404. <= Test the port handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  405. ------------------------------------------------------------------------------*/
  406. if ((Port < G_COM1) || (Port > G_COM4))
  407. {
  408. return (GE_HOST_PARAMETERS);
  409. }
  410. /*------------------------------------------------------------------------------
  411. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  412. ------------------------------------------------------------------------------*/
  413. if (port_config[Port - 1].Counter == 0)
  414. {
  415. return (GE_HOST_PORT_CLOSE);
  416. }
  417. /*------------------------------------------------------------------------------
  418. <= Test port_config.Counter [!= 65535): GE_HOST_RESOURCES
  419. ------------------------------------------------------------------------------*/
  420. if (port_config[Port - 1].Counter == 65535lu)
  421. {
  422. return (GE_HOST_RESOURCES);
  423. }
  424. /*------------------------------------------------------------------------------
  425. Increments the port_config.Counter.
  426. ------------------------------------------------------------------------------*/
  427. port_config[Port - 1].Counter += 1;
  428. /*------------------------------------------------------------------------------
  429. <= Port number.
  430. ------------------------------------------------------------------------------*/
  431. return (Port - 1);
  432. }
  433. /*******************************************************************************
  434. * INT16 G_SerPortClose
  435. * (
  436. * const INT16 Handle
  437. * )
  438. *
  439. * Description :
  440. * -------------
  441. * This routine closes a previously opened serial port.
  442. *
  443. * Remarks :
  444. * -------------
  445. * When port is shared, the close will be effective only when all clients will
  446. * have closed the port.
  447. *
  448. * In :
  449. * -------------
  450. * - Handle holds the port handle.
  451. *
  452. * Out :
  453. * -------------
  454. * Nothing.
  455. *
  456. * Responses :
  457. * -------------
  458. * If everything is OK:
  459. * - G_OK ( 0).
  460. * If an error condition is raised:
  461. * - GE_HOST_PORT_CLOSE (-412) if the selected port is already closed.
  462. * - GE_HOST_PARAMETERS (-450) if the given handle is out of the allowed range.
  463. *
  464. Extern var :
  465. -------------
  466. Nothing.
  467. Global var :
  468. -------------
  469. port_config is updated to closed state.
  470. *******************************************************************************/
  471. INT16 G_SerPortClose (const INT16 Handle)
  472. {
  473. /*------------------------------------------------------------------------------
  474. Local variables:
  475. - response holds the called function responses.
  476. ------------------------------------------------------------------------------*/
  477. INT16
  478. response;
  479. /*------------------------------------------------------------------------------
  480. Controls the given parameters:
  481. <= Test the port handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  482. ------------------------------------------------------------------------------*/
  483. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  484. {
  485. return (GE_HOST_PORT_ABS);
  486. }
  487. /*------------------------------------------------------------------------------
  488. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  489. ------------------------------------------------------------------------------*/
  490. if (port_config[Handle].Counter == 0)
  491. {
  492. return (GE_HOST_PORT_CLOSE);
  493. }
  494. /*------------------------------------------------------------------------------
  495. Decrements the port_config.Counter field.
  496. If is the last connection on the port
  497. Then
  498. Set the access state to TRUE.
  499. ------------------------------------------------------------------------------*/
  500. port_config[Handle].Counter -= 1;
  501. if (port_config[Handle].Counter == 0)
  502. {
  503. port_config[Handle].Access = TRUE;
  504. }
  505. /*------------------------------------------------------------------------------
  506. Closes really the port for the last user:
  507. If port_config.Counter = 0
  508. Then
  509. The queues are flushed by calling PurgeComm function.
  510. ------------------------------------------------------------------------------*/
  511. if (port_config[Handle].Counter == 0)
  512. {
  513. GDDKNT_PurgeComm(Handle,SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_TXABORT);
  514. }
  515. else
  516. {
  517. response = G_OK;
  518. }
  519. /*------------------------------------------------------------------------------
  520. <= Last Response
  521. ------------------------------------------------------------------------------*/
  522. return (response);
  523. }
  524. /*******************************************************************************
  525. * INT16 G_SerPortWrite
  526. * (
  527. * const INT16 Handle,
  528. * const WORD16 Length,
  529. * const BYTE Buffer[]
  530. * )
  531. *
  532. * Description :
  533. * -------------
  534. * This routine writes bytes on a previously opened serial port.
  535. *
  536. * Remarks :
  537. * -------------
  538. * WARNING: Application must verify that it remains enough place to send all the
  539. * bytes.
  540. *
  541. * In :
  542. * -------------
  543. * - Handle holds the port handle.
  544. * - Length holds the number of bytes to write.
  545. * - Buffer holds the bytes to write.
  546. *
  547. * Out :
  548. * -------------
  549. * Nothing.
  550. *
  551. * Responses :
  552. * -------------
  553. * If everything is OK:
  554. * - G_OK ( 0).
  555. * If an error condition is raised:
  556. * - GE_HI_LEN (-311) if there is not enough available space is in Tx
  557. * queue.
  558. * - GE_HOST_PORT_BREAK (-404) if the bytes cannot be sent.
  559. * - GE_HOST_PORT_CLOSE (-412) if port is closed.
  560. * - GE_HOST_PARAMETERS (-450) if the given handle is out of the allowed range.
  561. *
  562. Extern var :
  563. -------------
  564. Nothing.
  565. Global var :
  566. -------------
  567. port_config memorises the port configuration.
  568. *******************************************************************************/
  569. INT16 G_SerPortWrite
  570. (
  571. const INT16 Handle,
  572. const WORD16 Length,
  573. const BYTE Buffer[]
  574. )
  575. {
  576. /*------------------------------------------------------------------------------
  577. Local variables:
  578. ------------------------------------------------------------------------------*/
  579. NTSTATUS
  580. status;
  581. SERIAL_STATUS
  582. SerialStatus;
  583. WORD16
  584. LengthOut;
  585. ASSERT(Buffer != NULL);
  586. /*------------------------------------------------------------------------------
  587. Controls the given parameters:
  588. <= Test the port handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  589. ------------------------------------------------------------------------------*/
  590. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  591. {
  592. return (GE_HOST_PORT_ABS);
  593. }
  594. /*------------------------------------------------------------------------------
  595. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  596. ------------------------------------------------------------------------------*/
  597. if (port_config[Handle].Counter == 0)
  598. {
  599. return (GE_HOST_PORT_CLOSE);
  600. }
  601. /*------------------------------------------------------------------------------
  602. Control if the write can be made in one time:
  603. - The windows port status is read by calling GetCommError to know how many
  604. bytes remain in Tx queue (port_config.Error field is updated if needed).
  605. - If the write length is greater than the available space in Tx queue
  606. Then
  607. <= GE_HI_LEN
  608. ------------------------------------------------------------------------------*/
  609. GDDKNT_GetCommStatus(Handle,&SerialStatus);
  610. port_config[Handle].Error |= (WORD16)(SERIAL_ERROR_OVERRUN & SerialStatus.Errors);
  611. if (Length > ( port_config[Handle].TxSize - SerialStatus.AmountInOutQueue))
  612. {
  613. return (GE_HI_LEN);
  614. }
  615. /*------------------------------------------------------------------------------
  616. Writes the given byte in Tx queue by calling the WriteComm function.
  617. If an error occurs during this operation
  618. Then
  619. The ClearCommError function is called to unblock the port
  620. (port_config.Error field is updated if needed).
  621. <= GE_HOST_PORT_BREAK
  622. ------------------------------------------------------------------------------*/
  623. LengthOut = 0;
  624. status = GDDKNT_SerPortIoRequest(Handle,
  625. GTSER_IOCTL_WRITE,
  626. 500UL,
  627. Length,
  628. Buffer,
  629. &LengthOut,
  630. NULL);
  631. if (!NT_SUCCESS(status))
  632. {
  633. GDDKNT_GetCommStatus(Handle,&SerialStatus);
  634. port_config[Handle].Error |= (WORD16)(SERIAL_ERROR_OVERRUN & SerialStatus.Errors);
  635. GDDKNT_ResetComm(Handle);
  636. return (GE_HOST_PORT_BREAK);
  637. }
  638. return (G_OK);
  639. }
  640. /*******************************************************************************
  641. * INT16 G_SerPortRead
  642. * (
  643. * const INT16 Handle,
  644. * WORD16 *Length,
  645. * BYTE Buffer[]
  646. * )
  647. *
  648. * Description :
  649. * -------------
  650. * This routine reads bytes on a previously opened serial port.
  651. *
  652. * Remarks :
  653. * -------------
  654. * It ends when required length = read length or when a character level timeout
  655. * is detected.
  656. *
  657. * In :
  658. * -------------
  659. * - Handle holds the port handle.
  660. * - Length holds the number of bytes to read.
  661. * - Buffer is a free area of, at least, Length bytes.
  662. *
  663. * Out :
  664. * -------------
  665. * - Length holds the real number of read bytes.
  666. * - Buffer holds the read bytes.
  667. *
  668. * Responses :
  669. * -------------
  670. * If everything is OK:
  671. * - G_OK ( 0).
  672. * If an error condition is raised:
  673. * - GE_IFD_MUTE (-201) if a character timeout is detected.
  674. * - GE_HI_COMM (-300) if a communication error occurs.
  675. * - GE_HI_PARITY (-301) if a parity error is encountered.
  676. * - GE_HI_PROTOCOL (-310) if a frame error is encountered.
  677. * - GE_HOST_PORT_CLOSE (-412) if port is closed.
  678. * - GE_HOST_PARAMETERS (-450) if the given handle is out of the allowed range.
  679. *
  680. Extern var :
  681. -------------
  682. Nothing.
  683. Global var :
  684. -------------
  685. port_config memorises the port configuration.
  686. *******************************************************************************/
  687. INT16 G_SerPortRead
  688. (
  689. const INT16 Handle,
  690. WORD16 *Length,
  691. BYTE Buffer[]
  692. )
  693. {
  694. /*------------------------------------------------------------------------------
  695. Local variables:
  696. - end_tick is used to manage timeout.
  697. - ptr point on the next position in buffer. The HUGE modifier is used to avoid
  698. wraparound.
  699. - status will hold Windows port status.
  700. - nb_of_read_byte memorises the number of read bytes.
  701. - byte_to read holds the number of bytes to read in one loop.
  702. - read_byte holds the number of bytes which have been really read in a loop.
  703. - response holds called function responses.
  704. ------------------------------------------------------------------------------*/
  705. NTSTATUS
  706. status;
  707. WORD32
  708. end_tick;
  709. INT16
  710. response,i;
  711. DWORD
  712. error;
  713. TIME
  714. CurrentTime;
  715. SERIAL_STATUS
  716. SerialStatus;
  717. ASSERT(Buffer != NULL);
  718. /*------------------------------------------------------------------------------
  719. Controls the given parameters:
  720. <= Test the port Handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  721. ------------------------------------------------------------------------------*/
  722. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  723. {
  724. return (GE_HOST_PORT_ABS);
  725. }
  726. /*------------------------------------------------------------------------------
  727. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  728. ------------------------------------------------------------------------------*/
  729. if (port_config[Handle].Counter == 0)
  730. {
  731. *Length = 0;
  732. return (GE_HOST_PORT_CLOSE);
  733. }
  734. /*------------------------------------------------------------------------------
  735. Try to read the bytes.
  736. ------------------------------------------------------------------------------*/
  737. status = GDDKNT_SerPortIoRequest(Handle,
  738. GTSER_IOCTL_READ,
  739. port_config[Handle].TimeOut,
  740. 0,
  741. NULL,
  742. Length,
  743. Buffer);
  744. /*------------------------------------------------------------------------------
  745. If an error occurs (response == FALSE)
  746. Then
  747. VCOMM_GetLastError
  748. According to the detected error, a status is returned:
  749. CE_RXPARITY
  750. <= GE_HI_PARITY
  751. CE_FRAME
  752. <= GE_HI_PROTOCOL
  753. other cases
  754. <= GE_HI_COMM
  755. ------------------------------------------------------------------------------*/
  756. if (!NT_SUCCESS(status))
  757. {
  758. GDDKNT_GetCommStatus(Handle,&SerialStatus);
  759. error = (WORD16)(SerialStatus.Errors);
  760. if (error & SERIAL_ERROR_PARITY)
  761. {
  762. return (GE_HI_PARITY);
  763. }
  764. else if (error & SERIAL_ERROR_FRAMING)
  765. {
  766. return (GE_HI_PROTOCOL);
  767. }
  768. else
  769. {
  770. return (GE_HI_COMM);
  771. }
  772. }
  773. /*------------------------------------------------------------------------------
  774. Else
  775. Then
  776. Length is updated with the number of read byte.
  777. <= GE_IFD_MUTE
  778. ------------------------------------------------------------------------------*/
  779. else
  780. {
  781. if (*Length == 0)
  782. {
  783. return (GE_IFD_MUTE);
  784. }
  785. }
  786. /*------------------------------------------------------------------------------
  787. <= G_OK
  788. ------------------------------------------------------------------------------*/
  789. return (G_OK);
  790. }
  791. /*******************************************************************************
  792. * INT16 G_SerPortFlush
  793. * (
  794. * const INT16 Handle,
  795. * const WORD16 Select
  796. * )
  797. *
  798. * Description :
  799. * -------------
  800. * This function clears Tx and Rx buffers.
  801. *
  802. * Remarks :
  803. * -------------
  804. * When RX_QUEUE is selected, the RX_OVER flag is reseted.
  805. *
  806. * In :
  807. * -------------
  808. * - Handle holds the port handle.
  809. * - Select holds the buffers to clear:
  810. * HGTSER_TX_QUEUE
  811. * HGTSER_RX_QUEUE
  812. * HGTSER_TX_QUEUE | HGTSER_RX_QUEUE
  813. *
  814. * Out :
  815. * -------------
  816. * Nothing.
  817. *
  818. * Responses :
  819. * -------------
  820. * If everything is OK:
  821. * - G_OK ( 0).
  822. * If an error condition is raised:
  823. * - GE_HOST_PORT_CLOSE (-412) if port is closed.
  824. * - GE_HOST_PARAMETERS (-450) if the given handle is out of the allowed range.
  825. * - GE_HOST_PORT_BREAK (-404) if the port cannot be flush.
  826. *
  827. Extern var :
  828. -------------
  829. Nothing.
  830. Global var :
  831. -------------
  832. port_config memorises the port configuration.
  833. *******************************************************************************/
  834. INT16 G_SerPortFlush
  835. (
  836. const INT16 Handle,
  837. const WORD16 Select
  838. )
  839. {
  840. NTSTATUS
  841. status;
  842. /*------------------------------------------------------------------------------
  843. Controls the given parameters:
  844. <= Test the port handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  845. ------------------------------------------------------------------------------*/
  846. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  847. {
  848. return (GE_HOST_PORT_ABS);
  849. }
  850. /*------------------------------------------------------------------------------
  851. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  852. ------------------------------------------------------------------------------*/
  853. if (port_config[Handle].Counter == 0)
  854. {
  855. return (GE_HOST_PORT_CLOSE);
  856. }
  857. /*------------------------------------------------------------------------------
  858. Clears the selected queues:
  859. If HGTSER_TX_QUEUE is selected
  860. Then
  861. Flushes the Tx queue by calling FlushComm.
  862. ------------------------------------------------------------------------------*/
  863. if (Select & HGTSER_TX_QUEUE)
  864. {
  865. status = GDDKNT_PurgeComm(Handle,SERIAL_PURGE_TXCLEAR);
  866. if (!NT_SUCCESS(status))
  867. {
  868. return (GE_HOST_PORT_BREAK);
  869. }
  870. }
  871. /*------------------------------------------------------------------------------
  872. If HGTSER_RX_QUEUE is selected
  873. Then
  874. Flushes the Rx queue by calling FlushComm.
  875. Reset port_config.error field.
  876. ------------------------------------------------------------------------------*/
  877. if (Select & HGTSER_RX_QUEUE)
  878. {
  879. status = GDDKNT_PurgeComm(Handle,SERIAL_PURGE_RXCLEAR);
  880. if (!NT_SUCCESS(status))
  881. {
  882. return (GE_HOST_PORT_BREAK);
  883. }
  884. port_config[Handle].Error = 0;
  885. }
  886. return(G_OK);
  887. }
  888. /*******************************************************************************
  889. * INT16 G_SerPortStatus
  890. * (
  891. * const INT16 Handle,
  892. * WORD16 *TxLength,
  893. * WORD16 *RxLength,
  894. * TGTSER_STATUS *Status
  895. * )
  896. *
  897. * Description :
  898. * -------------
  899. * Return information about communication state.
  900. *
  901. * Remarks :
  902. * -------------
  903. * Nothing.
  904. *
  905. * In :
  906. * -------------
  907. * Handle holds the port handle.
  908. *
  909. * Out :
  910. * -------------
  911. * - TxLength holds the used Tx buffer length.
  912. * - RxLength holds the used Rx buffer length.
  913. * - Status can hold the following flags:
  914. * HGTSER_RX_OVER when a character has been lost since last call to this
  915. * function.
  916. *
  917. * Responses :
  918. * -------------
  919. * If everything is OK:
  920. * - G_OK ( 0).
  921. * If an error condition is raised:
  922. * - GE_HOST_PORT_CLOSE (-412) if port is closed.
  923. * - GE_HOST_PARAMETERS (-450) if the given handle is out of the allowed range.
  924. *
  925. Extern var :
  926. -------------
  927. Nothing.
  928. Global var :
  929. -------------
  930. port_config memorises the port configuration.
  931. *******************************************************************************/
  932. INT16 G_SerPortStatus
  933. (
  934. const INT16 Handle,
  935. WORD16 *TxLength,
  936. WORD16 *RxLength,
  937. TGTSER_STATUS *Status
  938. )
  939. {
  940. /*------------------------------------------------------------------------------
  941. Local variables:
  942. - status will hold Windows port status.
  943. ------------------------------------------------------------------------------*/
  944. NTSTATUS
  945. status;
  946. SERIAL_STATUS
  947. SerialStatus;
  948. ASSERT(TxLength != NULL);
  949. ASSERT(RxLength != NULL);
  950. ASSERT(Status != NULL);
  951. /*------------------------------------------------------------------------------
  952. Controls the given parameters:
  953. <= Test the port Handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  954. ------------------------------------------------------------------------------*/
  955. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  956. {
  957. return (GE_HOST_PORT_ABS);
  958. }
  959. /*------------------------------------------------------------------------------
  960. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  961. ------------------------------------------------------------------------------*/
  962. if (port_config[Handle].Counter == 0)
  963. {
  964. return (GE_HOST_PORT_CLOSE);
  965. }
  966. /*------------------------------------------------------------------------------
  967. Updates the given parameters:
  968. The current windows state is read and port_config.Error field is updated.
  969. ------------------------------------------------------------------------------*/
  970. status = GDDKNT_GetCommStatus(Handle,&SerialStatus);
  971. if (!NT_SUCCESS(status))
  972. {
  973. return (GE_HOST_PORT_BREAK);
  974. }
  975. /*------------------------------------------------------------------------------
  976. TxLength, RxLength and Status parameter fields are updated.
  977. ------------------------------------------------------------------------------*/
  978. *TxLength = (WORD16)SerialStatus.AmountInOutQueue;
  979. *RxLength = (WORD16)SerialStatus.AmountInInQueue;
  980. *Status = 0;
  981. /*------------------------------------------------------------------------------
  982. The Error field is reseted.
  983. ------------------------------------------------------------------------------*/
  984. port_config[Handle].Error = 0;
  985. /*------------------------------------------------------------------------------
  986. <= G_OK
  987. ------------------------------------------------------------------------------*/
  988. return (G_OK);
  989. }
  990. /*******************************************************************************
  991. * INT16 G_SerPortGetState
  992. * (
  993. * TGTSER_PORT *Param,
  994. * WORD16 *UserNb
  995. * )
  996. *
  997. * Description :
  998. * -------------
  999. * This routine read the currently in use parameters for an opened serial port.
  1000. *
  1001. * Remarks :
  1002. * -------------
  1003. * Nothing.
  1004. *
  1005. * In :
  1006. * -------------
  1007. * The following field of Param must be filled:
  1008. * - Port indicates the selected port: G_COM1 (1), G_COM2 (2), G_COM3 (3) or
  1009. * G_COM4 (4).
  1010. *
  1011. * Out :
  1012. * -------------
  1013. * The following fields of Param are updated by the call:
  1014. * - BaudRate holds the currently selected port baud rate: 110, 150, 300, 600,
  1015. * 1200, 2400, 4800, 9600, 19200, 38400 or 57600.
  1016. * - Mode gathers
  1017. * * word size WORD_5 (0), WORD_6 (1), WORD_7 (2) or WORD_8 (3),
  1018. * * stop bit number STOP_BIT_1 (0) or STOP_BIT_2 (4) and
  1019. * * parity NO_PARITY (0), ODD_PARITY (8) or EVEN_PARITY (24).
  1020. * - TimeOut indicates the time out value, in milli-seconds, at character level.
  1021. * - TxSize is the transmit buffer size, in bytes.
  1022. * - RxSize is the reception buffer size, in mbytes.
  1023. *
  1024. * Responses :
  1025. * -------------
  1026. * If everything is OK:
  1027. * - G_OK ( 0).
  1028. * If an error condition is raised:
  1029. * - GE_HOST_PORT_OS (-410) if a unexpected value has been returned by the
  1030. * operating system.
  1031. * - GE_HOST_PORT_CLOSE (-412) if the selected port is closed.
  1032. * - GE_HOST_PARAMETERS (-450) if the given handle is out of the allowed range.
  1033. *
  1034. Extern var :
  1035. -------------
  1036. Nothing.
  1037. Global var :
  1038. -------------
  1039. port_config is read.
  1040. *******************************************************************************/
  1041. INT16 G_SerPortGetState
  1042. (
  1043. TGTSER_PORT *Param,
  1044. WORD16 *UserNb
  1045. )
  1046. {
  1047. /*------------------------------------------------------------------------------
  1048. Local variables:
  1049. - handle holds the handle associated to the given port. It is calculated by the
  1050. following formula Port - 1.
  1051. - response holds the called function responses.
  1052. - current_dcb is used to read parameters in the device control block.
  1053. ------------------------------------------------------------------------------*/
  1054. NTSTATUS
  1055. status;
  1056. INT16
  1057. Handle = (INT16)(Param->Port - 1);
  1058. SERIAL_READER_CONFIG
  1059. SerialConfig;
  1060. ASSERT(Param != NULL);
  1061. ASSERT(UserNb != NULL);
  1062. /*------------------------------------------------------------------------------
  1063. Controls the given parameters:
  1064. <= Test the port Handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  1065. ------------------------------------------------------------------------------*/
  1066. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  1067. {
  1068. return (GE_HOST_PORT_ABS);
  1069. }
  1070. /*------------------------------------------------------------------------------
  1071. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  1072. ------------------------------------------------------------------------------*/
  1073. if (port_config[Handle].Counter == 0)
  1074. {
  1075. return (GE_HOST_PORT_CLOSE);
  1076. }
  1077. /*------------------------------------------------------------------------------
  1078. The current port state is read and stored in current_dcb structure by calling
  1079. GetCommState function.
  1080. If an error has occured (response < 0)
  1081. Then
  1082. <= GE_HOST_PORT_OS
  1083. ------------------------------------------------------------------------------*/
  1084. status = GDDKNT_GetCommState(Handle,&SerialConfig);
  1085. if (!NT_SUCCESS(status))
  1086. {
  1087. return (GE_HOST_PORT_OS);
  1088. }
  1089. /*------------------------------------------------------------------------------
  1090. The parameters are updated with the read values.
  1091. ------------------------------------------------------------------------------*/
  1092. Param->BaudRate = SerialConfig.BaudRate.BaudRate;
  1093. /*------------------------------------------------------------------------------
  1094. If the byte size is not supported
  1095. Then
  1096. <= GE_HOST_PORT_OS
  1097. ------------------------------------------------------------------------------*/
  1098. switch (SerialConfig.LineControl.WordLength)
  1099. {
  1100. case 5:
  1101. Param->Mode = HGTSER_WORD_5;
  1102. break;
  1103. case 6:
  1104. Param->Mode = HGTSER_WORD_6;
  1105. break;
  1106. case 7:
  1107. Param->Mode = HGTSER_WORD_7;
  1108. break;
  1109. case 8:
  1110. Param->Mode = HGTSER_WORD_8;
  1111. break;
  1112. default:
  1113. return (GE_HOST_PORT_OS);
  1114. }
  1115. /*------------------------------------------------------------------------------
  1116. If the parity is not supported
  1117. Then
  1118. <= GE_HOST_PORT_OS
  1119. ------------------------------------------------------------------------------*/
  1120. switch (SerialConfig.LineControl.Parity)
  1121. {
  1122. case NO_PARITY:
  1123. Param->Mode |= HGTSER_NO_PARITY;
  1124. break;
  1125. case ODD_PARITY:
  1126. Param->Mode |= HGTSER_ODD_PARITY;
  1127. break;
  1128. case EVEN_PARITY:
  1129. Param->Mode |= HGTSER_EVEN_PARITY;
  1130. break;
  1131. case SERIAL_PARITY_MARK:
  1132. case SERIAL_PARITY_SPACE:
  1133. default:
  1134. return (GE_HOST_PORT_OS);
  1135. }
  1136. /*------------------------------------------------------------------------------
  1137. If the stop bit number is not supported
  1138. Then
  1139. <= GE_HOST_PORT_OS
  1140. ------------------------------------------------------------------------------*/
  1141. switch (SerialConfig.LineControl.StopBits)
  1142. {
  1143. case STOP_BIT_1:
  1144. Param->Mode |= HGTSER_STOP_BIT_1;
  1145. break;
  1146. case STOP_BITS_2:
  1147. Param->Mode |= HGTSER_STOP_BIT_2;
  1148. break;
  1149. case STOP_BITS_1_5:
  1150. default:
  1151. return (GE_HOST_PORT_OS);
  1152. }
  1153. /*------------------------------------------------------------------------------
  1154. Updates the library fields ITNumber, TimeOut, TxSize and RxSize.
  1155. ------------------------------------------------------------------------------*/
  1156. Param->ITNumber = DEFAULT_IT;
  1157. Param->TimeOut = port_config[Handle].TimeOut;
  1158. Param->TxSize = port_config[Handle].TxSize;
  1159. Param->RxSize = port_config[Handle].RxSize;
  1160. /*------------------------------------------------------------------------------
  1161. The UserNb parameter is filled with the port_config.Counter.
  1162. ------------------------------------------------------------------------------*/
  1163. *UserNb = port_config[Handle].Counter;
  1164. /*------------------------------------------------------------------------------
  1165. <= G_OK
  1166. ------------------------------------------------------------------------------*/
  1167. return (G_OK);
  1168. }
  1169. /*******************************************************************************
  1170. * INT16 G_SerPortSetState
  1171. * (
  1172. * TGTSER_PORT *Param
  1173. * )
  1174. *
  1175. * Description :
  1176. * -------------
  1177. * This routine alters the currently in use parameters for an opened serial port.
  1178. *
  1179. * Remarks :
  1180. * -------------
  1181. * Nothing.
  1182. *
  1183. * In :
  1184. * -------------
  1185. * The following field of Param must be filled:
  1186. * - Port indicates the selected port: G_COM1 (1), G_COM2 (2), G_COM3 (3) or
  1187. * G_COM4 (4).
  1188. * - BaudRate holds the currently selected port baud rate: 110, 150, 300, 600,
  1189. * 1200, 2400, 4800, 9600, 19200, 38400 or 57600.
  1190. * - Mode gathers
  1191. * * word size WORD_5 (0), WORD_6 (1), WORD_7 (2) or WORD_8 (3),
  1192. * * stop bit number STOP_BIT_1 (0) or STOP_BIT_2 (4) and
  1193. * * parity NO_PARITY (0), ODD_PARITY (8) or EVEN_PARITY (24).
  1194. * - TimeOut indicates the time out value, in milli-seconds, at character level.
  1195. *
  1196. * Out :
  1197. * -------------
  1198. * The following fields of Param are updated by the call:
  1199. * - TxSize is the transmit buffer size, in bytes.
  1200. * - RxSize is the reception buffer size, in mbytes.
  1201. *
  1202. * Responses :
  1203. * -------------
  1204. * If everything is OK:
  1205. * - G_OK ( 0).
  1206. * If an error condition is raised:
  1207. * - GE_HOST_PORT_ABS (- 401) if port is not found on host or is locked by
  1208. * another device.
  1209. * - GE_HOST_PORT_OS (- 410) if a unexpected value has been returned by the
  1210. * operating system.
  1211. * - GE_HOST_PORT_CLOSE (- 412) if the selected port is closed.
  1212. * - GE_HOST_MEMORY (- 420) if a memory allocation fails.
  1213. * - GE_HOST_PARAMETERS (- 450) if one of the given parameters is out of the
  1214. * allowed range or is not supported by hardware.
  1215. * - GE_UNKNOWN_PB (-1000) if an unexpected problem is encountered.
  1216. *
  1217. Extern var :
  1218. -------------
  1219. Nothing.
  1220. Global var :
  1221. -------------
  1222. port_config is set with the selected configuration.
  1223. *******************************************************************************/
  1224. INT16 G_SerPortSetState
  1225. (
  1226. TGTSER_PORT *Param
  1227. )
  1228. {
  1229. NTSTATUS
  1230. status;
  1231. INT16
  1232. response = G_OK,
  1233. Handle = (INT16)(Param->Port - 1);
  1234. SERIAL_READER_CONFIG
  1235. SerialConfig;
  1236. DWORD
  1237. error = 0;
  1238. ASSERT(Param != NULL);
  1239. /*------------------------------------------------------------------------------
  1240. Controls the given parameters:
  1241. <= Test the port handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  1242. ------------------------------------------------------------------------------*/
  1243. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  1244. {
  1245. return (GE_HOST_PORT_ABS);
  1246. }
  1247. /*------------------------------------------------------------------------------
  1248. <= Test the port state (Counter > 0): GE_HOST_PORT_CLOSE.
  1249. ------------------------------------------------------------------------------*/
  1250. if (port_config[Handle].Counter == 0)
  1251. {
  1252. return (GE_HOST_PORT_CLOSE);
  1253. }
  1254. status = GDDKNT_GetCommState(Handle,&SerialConfig);
  1255. if (NT_SUCCESS(status))
  1256. {
  1257. SerialConfig.BaudRate.BaudRate = Param->BaudRate;
  1258. SerialConfig.LineControl.WordLength = WORD_LEN(Param->Mode);
  1259. SerialConfig.LineControl.Parity = PARITY(Param->Mode);
  1260. SerialConfig.LineControl.StopBits = STOP(Param->Mode);
  1261. status = GDDKNT_SetCommState(Handle,&SerialConfig);
  1262. }
  1263. /*------------------------------------------------------------------------------
  1264. Else
  1265. error is set with GE_HOST_PARAMETERS error value.
  1266. ------------------------------------------------------------------------------*/
  1267. else
  1268. {
  1269. return(GE_HOST_PARAMETERS);
  1270. }
  1271. if (!NT_SUCCESS(status))
  1272. {
  1273. switch (status)
  1274. {
  1275. case STATUS_BUFFER_TOO_SMALL:
  1276. case STATUS_INVALID_PARAMETER:
  1277. response = GE_HOST_PARAMETERS;
  1278. break;
  1279. default :
  1280. response = GE_UNKNOWN_PB;
  1281. break;
  1282. }
  1283. }
  1284. return(response);
  1285. }
  1286. /*******************************************************************************
  1287. * INT32 G_SerPortLockComm
  1288. * (
  1289. * const INT16 Handle,
  1290. * const DWORD WaitRelease
  1291. * )
  1292. *
  1293. * Description :
  1294. * -------------
  1295. * Take the mutex for a serial port communication if is free or wait
  1296. * the release
  1297. *
  1298. * Remarks :
  1299. * -------------
  1300. * Nothing.
  1301. *
  1302. * In :
  1303. * -------------
  1304. * Handle hold the port handle
  1305. * WaitRelease old the new time to wait the release
  1306. *
  1307. * Out :
  1308. * -------------
  1309. * Nothing.
  1310. *
  1311. * Responses :
  1312. * -------------
  1313. * If everything is OK: TRUE
  1314. * else FALSE
  1315. *
  1316. Extern var :
  1317. -------------
  1318. Nothing.
  1319. Global var :
  1320. -------------
  1321. Nothing
  1322. *******************************************************************************/
  1323. INT32 G_SerPortLockComm
  1324. (
  1325. const INT16 Handle,
  1326. const DWORD WaitRelease
  1327. )
  1328. {
  1329. NTSTATUS
  1330. status;
  1331. LARGE_INTEGER
  1332. timeout;
  1333. /*------------------------------------------------------------------------------
  1334. Controls the given parameters:
  1335. <= Test the port handle (0 <= Handle < HGTSER_MAX_PORT): GE_HOST_PARAMETERS.
  1336. ------------------------------------------------------------------------------*/
  1337. if ((Handle < 0) || (Handle >= HGTSER_MAX_PORT))
  1338. {
  1339. return (FALSE);
  1340. }
  1341. /*------------------------------------------------------------------------------
  1342. Wait the release of the mutex
  1343. ------------------------------------------------------------------------------*/
  1344. timeout.QuadPart = -((LONGLONG)(
  1345. port_config[Handle].WaitRelease > GTSER_DEF_WAIT_RELEASE ?
  1346. port_config[Handle].WaitRelease : GTSER_DEF_WAIT_RELEASE)*10*1000);
  1347. status = KeWaitForMutexObject(
  1348. port_config[Handle].pExchangeMutex,
  1349. Executive,
  1350. KernelMode,
  1351. FALSE,
  1352. &timeout
  1353. );
  1354. if (status != STATUS_SUCCESS)
  1355. {
  1356. return(FALSE);
  1357. }
  1358. else
  1359. {
  1360. port_config[Handle].WaitRelease = WaitRelease;
  1361. return(TRUE);
  1362. }
  1363. }
  1364. /*******************************************************************************
  1365. * void G_SerPortUnlockComm
  1366. * (
  1367. * const INT16 Handle
  1368. * )
  1369. *
  1370. * Description :
  1371. * -------------
  1372. * Release the mutex for a serial port communication.
  1373. *
  1374. * Remarks :
  1375. * -------------
  1376. * Nothing.
  1377. *
  1378. * In : Handle hold the port handle
  1379. * -------------
  1380. * Nothing
  1381. *
  1382. * Out :
  1383. * -------------
  1384. *
  1385. * Responses :
  1386. * -------------
  1387. * Nothing
  1388. *
  1389. Extern var :
  1390. -------------
  1391. Nothing.
  1392. Global var :
  1393. -------------
  1394. Nothing
  1395. *******************************************************************************/
  1396. void G_SerPortUnlockComm
  1397. (
  1398. const INT16 Handle
  1399. )
  1400. {
  1401. NTSTATUS
  1402. status;
  1403. /*------------------------------------------------------------------------------
  1404. Controls the given parameters:
  1405. ------------------------------------------------------------------------------*/
  1406. if ((Handle >= 0) && (Handle < HGTSER_MAX_PORT))
  1407. {
  1408. status = KeReleaseMutex(port_config[Handle].pExchangeMutex,FALSE);
  1409. }
  1410. }
  1411. /******************************************************************************
  1412. * NTSTATUS GDDKNT_SerPortIoRequest
  1413. * (
  1414. * IN CONST INT16 Handle,
  1415. * IN CONST ULONG SerialIoControlCode,
  1416. * IN CONST ULONG CmdTimeout,
  1417. * IN CONST WORD16 LengthIn,
  1418. * IN CONST BYTE *BufferIn,
  1419. * IN OUT WORD16 *pLengthOut,
  1420. * OUT BYTE *BufferOut
  1421. * )
  1422. *
  1423. * Description :
  1424. * -------------
  1425. * This function sends IOCTL's to the serial driver. It waits on for their
  1426. * completion, and then returns.
  1427. *
  1428. * Remarks :
  1429. * -------------
  1430. * Nothing.
  1431. *
  1432. * In :
  1433. * -------------
  1434. * - Handle holds the port handle.
  1435. * - CmdTimeout is the current command timeout.
  1436. *
  1437. * Out :
  1438. * -------------
  1439. * Nothing.
  1440. *
  1441. * Responses :
  1442. * -------------
  1443. * If everything is Ok:
  1444. * STATUS_SUCCESS ( 0).
  1445. *
  1446. *******************************************************************************/
  1447. NTSTATUS GDDKNT_SerPortIoRequest
  1448. (
  1449. IN CONST INT16 Handle,
  1450. IN CONST ULONG SerialIoControlCode,
  1451. IN CONST ULONG CmdTimeout,
  1452. IN CONST WORD16 LengthIn,
  1453. IN CONST BYTE *BufferIn,
  1454. IN OUT WORD16 *pLengthOut,
  1455. OUT BYTE *BufferOut
  1456. )
  1457. {
  1458. NTSTATUS
  1459. status;
  1460. PIRP
  1461. irp;
  1462. PIO_STACK_LOCATION
  1463. irpNextStack;
  1464. IO_STATUS_BLOCK
  1465. ioStatus;
  1466. KEVENT
  1467. event;
  1468. LARGE_INTEGER
  1469. timeout;
  1470. KeInitializeEvent(&event,NotificationEvent,FALSE);
  1471. /*------------------------------------------------------------------------------
  1472. Build an Irp to be send to serial driver
  1473. ------------------------------------------------------------------------------*/
  1474. irp = IoBuildDeviceIoControlRequest
  1475. (
  1476. SerialIoControlCode,
  1477. port_config[Handle].pSerialPortDevice,
  1478. (PVOID)BufferIn,
  1479. (ULONG)LengthIn,
  1480. (PVOID)BufferOut,
  1481. (ULONG)(*pLengthOut),
  1482. FALSE,
  1483. &event,
  1484. &ioStatus
  1485. );
  1486. if (irp == NULL)
  1487. {
  1488. return STATUS_INSUFFICIENT_RESOURCES;
  1489. }
  1490. irpNextStack = IoGetNextIrpStackLocation(irp);
  1491. switch (SerialIoControlCode)
  1492. {
  1493. case GTSER_IOCTL_WRITE:
  1494. irpNextStack->MajorFunction = IRP_MJ_WRITE;
  1495. irpNextStack->Parameters.Write.Length = (ULONG)LengthIn;
  1496. break;
  1497. case GTSER_IOCTL_READ:
  1498. irpNextStack->MajorFunction = IRP_MJ_READ;
  1499. irpNextStack->Parameters.Read.Length = (ULONG)(*pLengthOut);
  1500. break;
  1501. }
  1502. status = IoCallDriver(port_config[Handle].pSerialPortDevice,irp);
  1503. if (status == STATUS_PENDING)
  1504. {
  1505. timeout.QuadPart = -((LONGLONG) CmdTimeout*10*1000);
  1506. status = KeWaitForSingleObject(&event,
  1507. Suspended,
  1508. KernelMode,
  1509. FALSE,
  1510. &timeout);
  1511. if (status == STATUS_TIMEOUT)
  1512. {
  1513. IoCancelIrp(irp);
  1514. KeWaitForSingleObject(&event,
  1515. Suspended,
  1516. KernelMode,
  1517. FALSE,
  1518. NULL);
  1519. }
  1520. }
  1521. status = ioStatus.Status;
  1522. switch (SerialIoControlCode)
  1523. {
  1524. case GTSER_IOCTL_WRITE:
  1525. if (ioStatus.Status == STATUS_TIMEOUT)
  1526. {
  1527. // STATUS_TIMEOUT isn't correctly mapped
  1528. // to a WIN32 error, that's why we change it here to STATUS_IO_TIMEOUT
  1529. status = STATUS_IO_TIMEOUT;
  1530. }
  1531. break;
  1532. case GTSER_IOCTL_READ:
  1533. if (ioStatus.Status == STATUS_TIMEOUT)
  1534. {
  1535. // STATUS_TIMEOUT isn't correctly mapped
  1536. // to a WIN32 error, that's why we change it here to STATUS_IO_TIMEOUT
  1537. status = STATUS_IO_TIMEOUT;
  1538. *pLengthOut = 0;
  1539. }
  1540. break;
  1541. default:
  1542. *pLengthOut = (WORD16)(ioStatus.Information);
  1543. break;
  1544. }
  1545. return status;
  1546. }
  1547. /******************************************************************************
  1548. * NTSTATUS GDDKNT_SetCommState
  1549. * (
  1550. * const INT16 Handle,
  1551. * SERIAL_READER_CONFIG *SerialConfig
  1552. * )
  1553. *
  1554. * Description :
  1555. * -------------
  1556. * This routine will appropriately configure the serial port.
  1557. * It makes synchronous calls to the serial port.
  1558. *
  1559. * Remarks :
  1560. * -------------
  1561. * Nothing.
  1562. *
  1563. * In :
  1564. * -------------
  1565. * - Handle holds the port handle.
  1566. *
  1567. * Out :
  1568. * -------------
  1569. * Nothing.
  1570. *
  1571. * Responses :
  1572. * -------------
  1573. * If everything is Ok:
  1574. * STATUS_SUCCESS ( 0).
  1575. *
  1576. *******************************************************************************/
  1577. NTSTATUS GDDKNT_SetCommState
  1578. (
  1579. const INT16 Handle,
  1580. SERIAL_READER_CONFIG *SerialConfig
  1581. )
  1582. {
  1583. NTSTATUS
  1584. status = STATUS_SUCCESS;
  1585. USHORT
  1586. i;
  1587. ULONG
  1588. SerialIoControlCode;
  1589. WORD16
  1590. LengthIn,
  1591. LengthOut;
  1592. PUCHAR
  1593. pBufferIn;
  1594. ASSERT(SerialConfig != NULL);
  1595. for (i=0; NT_SUCCESS(status); i++)
  1596. {
  1597. switch (i)
  1598. {
  1599. case 0:
  1600. // Set up baudrate
  1601. SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE;
  1602. pBufferIn = (PUCHAR)&SerialConfig->BaudRate;
  1603. LengthIn = sizeof(SERIAL_BAUD_RATE);
  1604. break;
  1605. case 1:
  1606. // Set up line control parameters
  1607. SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL;
  1608. pBufferIn = (PUCHAR)&SerialConfig->LineControl;
  1609. LengthIn = sizeof(SERIAL_LINE_CONTROL);
  1610. break;
  1611. case 2:
  1612. // Set serial special characters
  1613. SerialIoControlCode = IOCTL_SERIAL_SET_CHARS;
  1614. pBufferIn = (PUCHAR)&SerialConfig->SerialChars;
  1615. LengthIn = sizeof(SERIAL_CHARS);
  1616. break;
  1617. case 3:
  1618. // Set up timeouts
  1619. SerialIoControlCode = IOCTL_SERIAL_SET_TIMEOUTS;
  1620. pBufferIn = (PUCHAR)&SerialConfig->Timeouts;
  1621. LengthIn = sizeof(SERIAL_TIMEOUTS);
  1622. break;
  1623. case 4:
  1624. // Set flowcontrol and handshaking
  1625. SerialIoControlCode = IOCTL_SERIAL_SET_HANDFLOW;
  1626. pBufferIn = (PUCHAR)&SerialConfig->HandFlow;
  1627. LengthIn = sizeof(SERIAL_HANDFLOW);
  1628. break;
  1629. case 5:
  1630. // Set break off
  1631. SerialIoControlCode = IOCTL_SERIAL_SET_BREAK_OFF;
  1632. LengthIn = 0;
  1633. break;
  1634. case 6:
  1635. return STATUS_SUCCESS;
  1636. }
  1637. LengthOut = 0;
  1638. status = GDDKNT_SerPortIoRequest(Handle,
  1639. SerialIoControlCode,
  1640. 500UL,
  1641. LengthIn,
  1642. pBufferIn,
  1643. &LengthOut,
  1644. NULL);
  1645. }
  1646. return status;
  1647. }
  1648. /******************************************************************************
  1649. * NTSTATUS GDDKNT_GetCommState
  1650. * (
  1651. * const INT16 Handle,
  1652. * SERIAL_READER_CONFIG *SerialConfig
  1653. * )
  1654. *
  1655. * Description :
  1656. * -------------
  1657. * This routine will appropriately configure the serial port.
  1658. * It makes synchronous calls to the serial port.
  1659. *
  1660. * Remarks :
  1661. * -------------
  1662. * Nothing.
  1663. *
  1664. * In :
  1665. * -------------
  1666. * - Handle holds the port handle.
  1667. *
  1668. * Out :
  1669. * -------------
  1670. * Nothing.
  1671. *
  1672. * Responses :
  1673. * -------------
  1674. * If everything is Ok:
  1675. * STATUS_SUCCESS ( 0).
  1676. *
  1677. *******************************************************************************/
  1678. NTSTATUS GDDKNT_GetCommState
  1679. (
  1680. const INT16 Handle,
  1681. SERIAL_READER_CONFIG *SerialConfig
  1682. )
  1683. {
  1684. NTSTATUS
  1685. status = STATUS_SUCCESS;
  1686. USHORT
  1687. i;
  1688. ULONG
  1689. SerialIoControlCode;
  1690. WORD16
  1691. LengthOut;
  1692. PUCHAR
  1693. pBufferOut;
  1694. ASSERT(SerialConfig != NULL);
  1695. for (i=0; NT_SUCCESS(status); i++)
  1696. {
  1697. switch (i)
  1698. {
  1699. case 0:
  1700. // Get up baudrate
  1701. SerialIoControlCode = IOCTL_SERIAL_GET_BAUD_RATE;
  1702. pBufferOut = (PUCHAR)&SerialConfig->BaudRate;
  1703. LengthOut = sizeof(SERIAL_BAUD_RATE);
  1704. break;
  1705. case 1:
  1706. // Get up line control parameters
  1707. SerialIoControlCode = IOCTL_SERIAL_GET_LINE_CONTROL;
  1708. pBufferOut = (PUCHAR)&SerialConfig->LineControl;
  1709. LengthOut = sizeof(SERIAL_LINE_CONTROL);
  1710. break;
  1711. case 2:
  1712. // Get serial special characters
  1713. SerialIoControlCode = IOCTL_SERIAL_GET_CHARS;
  1714. pBufferOut = (PUCHAR)&SerialConfig->SerialChars;
  1715. LengthOut = sizeof(SERIAL_CHARS);
  1716. break;
  1717. case 3:
  1718. // Get up timeouts
  1719. SerialIoControlCode = IOCTL_SERIAL_GET_TIMEOUTS;
  1720. pBufferOut = (PUCHAR)&SerialConfig->Timeouts;
  1721. LengthOut = sizeof(SERIAL_TIMEOUTS);
  1722. break;
  1723. case 4:
  1724. // Get flowcontrol and handshaking
  1725. SerialIoControlCode = IOCTL_SERIAL_GET_HANDFLOW;
  1726. pBufferOut = (PUCHAR)&SerialConfig->HandFlow;
  1727. LengthOut = sizeof(SERIAL_HANDFLOW);
  1728. break;
  1729. case 5:
  1730. return STATUS_SUCCESS;
  1731. }
  1732. status = GDDKNT_SerPortIoRequest(Handle,
  1733. SerialIoControlCode,
  1734. 500UL,
  1735. 0,
  1736. NULL,
  1737. &LengthOut,
  1738. pBufferOut);
  1739. }
  1740. return status;
  1741. }
  1742. /******************************************************************************
  1743. * NTSTATUS GDDKNT_SetupComm
  1744. * (
  1745. * const INT16 Handle,
  1746. * const ULONG InSize,
  1747. * const ULONG OutSize
  1748. * )
  1749. *
  1750. * Description :
  1751. * -------------
  1752. * This routine will appropriately resize the driver's internal typeahead
  1753. * and input buffers of the serial port.
  1754. * It makes synchronous calls to the serial port.
  1755. *
  1756. * Remarks :
  1757. * -------------
  1758. * Nothing.
  1759. *
  1760. * In :
  1761. * -------------
  1762. * - Handle holds the port handle.
  1763. * - InSize is the input buffer size.
  1764. * - OutSize is the output buffer size.
  1765. *
  1766. * Out :
  1767. * -------------
  1768. * Nothing.
  1769. *
  1770. * Responses :
  1771. * -------------
  1772. * If everything is Ok:
  1773. * STATUS_SUCCESS ( 0).
  1774. *
  1775. *******************************************************************************/
  1776. static NTSTATUS GDDKNT_SetupComm
  1777. (
  1778. const INT16 Handle,
  1779. const ULONG InSize,
  1780. const ULONG OutSize
  1781. )
  1782. {
  1783. NTSTATUS
  1784. status = STATUS_SUCCESS;
  1785. SERIAL_QUEUE_SIZE
  1786. SerialQueueSize;
  1787. WORD16
  1788. LengthOut = 0;
  1789. // Set up queue size
  1790. SerialQueueSize.InSize = InSize;
  1791. SerialQueueSize.OutSize = OutSize;
  1792. status = GDDKNT_SerPortIoRequest(Handle,
  1793. IOCTL_SERIAL_SET_QUEUE_SIZE,
  1794. 500UL,
  1795. sizeof(SERIAL_QUEUE_SIZE),
  1796. (PUCHAR)&SerialQueueSize,
  1797. &LengthOut,
  1798. NULL);
  1799. return status;
  1800. }
  1801. /******************************************************************************
  1802. * NTSTATUS GDDKNT_GetCommStatus
  1803. * (
  1804. * const INT16 Handle,
  1805. * SERIAL_STATUS *SerialStatus
  1806. * )
  1807. *
  1808. * Description :
  1809. * -------------
  1810. * This routine will appropriately get status information of the serial port.
  1811. * It makes synchronous calls to the serial port.
  1812. *
  1813. * Remarks :
  1814. * -------------
  1815. * Nothing.
  1816. *
  1817. * In :
  1818. * -------------
  1819. * - Handle holds the port handle.
  1820. *
  1821. * Out :
  1822. * -------------
  1823. * - SerialStatus is the pointer to the status information returned.
  1824. *
  1825. * Responses :
  1826. * -------------
  1827. * If everything is Ok:
  1828. * STATUS_SUCCESS ( 0).
  1829. *
  1830. *******************************************************************************/
  1831. static NTSTATUS GDDKNT_GetCommStatus
  1832. (
  1833. const INT16 Handle,
  1834. SERIAL_STATUS *SerialStatus
  1835. )
  1836. {
  1837. NTSTATUS
  1838. status = STATUS_SUCCESS;
  1839. WORD16
  1840. LengthOut;
  1841. ASSERT(SerialStatus != NULL);
  1842. LengthOut = sizeof(SERIAL_STATUS);
  1843. status = GDDKNT_SerPortIoRequest(Handle,
  1844. IOCTL_SERIAL_GET_COMMSTATUS,
  1845. 500UL,
  1846. 0,
  1847. NULL,
  1848. &LengthOut,
  1849. (PUCHAR)SerialStatus);
  1850. return status;
  1851. }
  1852. /******************************************************************************
  1853. * NTSTATUS GDDKNT_ResetComm
  1854. * (
  1855. * const INT16 Handle
  1856. * )
  1857. *
  1858. * Description :
  1859. * -------------
  1860. * This routine will appropriately get status information of the serial port.
  1861. * It makes synchronous calls to the serial port.
  1862. *
  1863. * Remarks :
  1864. * -------------
  1865. * Nothing.
  1866. *
  1867. * In :
  1868. * -------------
  1869. * - Handle holds the port handle.
  1870. *
  1871. * Out :
  1872. * -------------
  1873. * Nothing.
  1874. *
  1875. * Responses :
  1876. * -------------
  1877. * If everything is Ok:
  1878. * STATUS_SUCCESS ( 0).
  1879. *
  1880. *******************************************************************************/
  1881. static NTSTATUS GDDKNT_ResetComm
  1882. (
  1883. const INT16 Handle
  1884. )
  1885. {
  1886. NTSTATUS
  1887. status = STATUS_SUCCESS;
  1888. WORD16
  1889. LengthOut = 0;
  1890. status = GDDKNT_SerPortIoRequest(Handle,
  1891. IOCTL_SERIAL_RESET_DEVICE,
  1892. 500UL,
  1893. 0,
  1894. NULL,
  1895. &LengthOut,
  1896. NULL);
  1897. return status;
  1898. }
  1899. /******************************************************************************
  1900. * NTSTATUS GDDKNT_PurgeComm
  1901. * (
  1902. * const INT16 Handle,
  1903. * const ULONG Select
  1904. * )
  1905. *
  1906. * Description :
  1907. * -------------
  1908. * This routine flush the data in the serial port.
  1909. *
  1910. * Remarks :
  1911. * -------------
  1912. * Nothing.
  1913. *
  1914. * In :
  1915. * -------------
  1916. * - Handle holds the port handle.
  1917. * - Select holds the buffers to clear:
  1918. * SERIAL_PURGE_TXCLEAR
  1919. * SERIAL_PURGE_RXCLEAR
  1920. * SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR
  1921. *
  1922. * Out :
  1923. * -------------
  1924. * Nothing.
  1925. *
  1926. * Responses :
  1927. * -------------
  1928. * If everything is Ok:
  1929. * STATUS_SUCCESS ( 0).
  1930. *
  1931. *******************************************************************************/
  1932. static NTSTATUS GDDKNT_PurgeComm
  1933. (
  1934. const INT16 Handle,
  1935. const ULONG Select
  1936. )
  1937. {
  1938. NTSTATUS
  1939. status = STATUS_SUCCESS;
  1940. ULONG
  1941. PurgeMask = Select;
  1942. WORD16
  1943. LengthOut = 0;
  1944. status = GDDKNT_SerPortIoRequest(Handle,
  1945. IOCTL_SERIAL_PURGE,
  1946. 500UL,
  1947. sizeof(PurgeMask),
  1948. (PUCHAR)&PurgeMask,
  1949. &LengthOut,
  1950. NULL);
  1951. return status;
  1952. }