comm_sercx_sys.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /**
  2. * WinPR: Windows Portable Runtime
  3. * Serial Communication API
  4. *
  5. * Copyright 2011 O.S. Systems Software Ltda.
  6. * Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
  7. * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  8. * Copyright 2014 Hewlett-Packard Development Company, L.P.
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. */
  22. #if defined __linux__ && !defined ANDROID
  23. #include <assert.h>
  24. #include <termios.h>
  25. #include <winpr/wlog.h>
  26. #include "comm_serial_sys.h"
  27. static BOOL _set_handflow(WINPR_COMM* pComm, const SERIAL_HANDFLOW* pHandflow)
  28. {
  29. SERIAL_HANDFLOW SerCxHandflow;
  30. BOOL result = TRUE;
  31. SERIAL_DRIVER* pSerialSys = SerialSys_s();
  32. memcpy(&SerCxHandflow, pHandflow, sizeof(SERIAL_HANDFLOW));
  33. /* filter out unsupported bits by SerCx.sys
  34. *
  35. * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
  36. */
  37. SerCxHandflow.ControlHandShake =
  38. pHandflow->ControlHandShake &
  39. (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
  40. SerCxHandflow.FlowReplace =
  41. pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
  42. if (SerCxHandflow.ControlHandShake != pHandflow->ControlHandShake)
  43. {
  44. if (pHandflow->ControlHandShake & SERIAL_DCD_HANDSHAKE)
  45. {
  46. CommLog_Print(WLOG_WARN,
  47. "SERIAL_DCD_HANDSHAKE not supposed to be implemented by SerCx.sys");
  48. }
  49. if (pHandflow->ControlHandShake & SERIAL_DSR_SENSITIVITY)
  50. {
  51. CommLog_Print(WLOG_WARN,
  52. "SERIAL_DSR_SENSITIVITY not supposed to be implemented by SerCx.sys");
  53. }
  54. if (pHandflow->ControlHandShake & SERIAL_ERROR_ABORT)
  55. {
  56. CommLog_Print(WLOG_WARN,
  57. "SERIAL_ERROR_ABORT not supposed to be implemented by SerCx.sys");
  58. }
  59. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  60. result = FALSE;
  61. }
  62. if (SerCxHandflow.FlowReplace != pHandflow->FlowReplace)
  63. {
  64. if (pHandflow->ControlHandShake & SERIAL_AUTO_TRANSMIT)
  65. {
  66. CommLog_Print(WLOG_WARN,
  67. "SERIAL_AUTO_TRANSMIT not supposed to be implemented by SerCx.sys");
  68. }
  69. if (pHandflow->ControlHandShake & SERIAL_AUTO_RECEIVE)
  70. {
  71. CommLog_Print(WLOG_WARN,
  72. "SERIAL_AUTO_RECEIVE not supposed to be implemented by SerCx.sys");
  73. }
  74. if (pHandflow->ControlHandShake & SERIAL_ERROR_CHAR)
  75. {
  76. CommLog_Print(WLOG_WARN,
  77. "SERIAL_ERROR_CHAR not supposed to be implemented by SerCx.sys");
  78. }
  79. if (pHandflow->ControlHandShake & SERIAL_NULL_STRIPPING)
  80. {
  81. CommLog_Print(WLOG_WARN,
  82. "SERIAL_NULL_STRIPPING not supposed to be implemented by SerCx.sys");
  83. }
  84. if (pHandflow->ControlHandShake & SERIAL_BREAK_CHAR)
  85. {
  86. CommLog_Print(WLOG_WARN,
  87. "SERIAL_BREAK_CHAR not supposed to be implemented by SerCx.sys");
  88. }
  89. if (pHandflow->ControlHandShake & SERIAL_XOFF_CONTINUE)
  90. {
  91. CommLog_Print(WLOG_WARN,
  92. "SERIAL_XOFF_CONTINUE not supposed to be implemented by SerCx.sys");
  93. }
  94. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  95. result = FALSE;
  96. }
  97. if (!pSerialSys->set_handflow(pComm, &SerCxHandflow))
  98. return FALSE;
  99. return result;
  100. }
  101. static BOOL _get_handflow(WINPR_COMM* pComm, SERIAL_HANDFLOW* pHandflow)
  102. {
  103. BOOL result;
  104. SERIAL_DRIVER* pSerialSys = SerialSys_s();
  105. result = pSerialSys->get_handflow(pComm, pHandflow);
  106. /* filter out unsupported bits by SerCx.sys
  107. *
  108. * http://msdn.microsoft.com/en-us/library/windows/hardware/jj680685%28v=vs.85%29.aspx
  109. */
  110. pHandflow->ControlHandShake =
  111. pHandflow->ControlHandShake &
  112. (SERIAL_DTR_CONTROL | SERIAL_DTR_HANDSHAKE | SERIAL_CTS_HANDSHAKE | SERIAL_DSR_HANDSHAKE);
  113. pHandflow->FlowReplace = pHandflow->FlowReplace & (SERIAL_RTS_CONTROL | SERIAL_RTS_HANDSHAKE);
  114. return result;
  115. }
  116. /* http://msdn.microsoft.com/en-us/library/windows/hardware/hh439605%28v=vs.85%29.aspx */
  117. static const ULONG _SERCX_SYS_SUPPORTED_EV_MASK = SERIAL_EV_RXCHAR |
  118. /* SERIAL_EV_RXFLAG | */
  119. SERIAL_EV_TXEMPTY | SERIAL_EV_CTS |
  120. SERIAL_EV_DSR | SERIAL_EV_RLSD | SERIAL_EV_BREAK |
  121. SERIAL_EV_ERR | SERIAL_EV_RING /* |
  122. SERIAL_EV_PERR |
  123. SERIAL_EV_RX80FULL |
  124. SERIAL_EV_EVENT1 |
  125. SERIAL_EV_EVENT2*/
  126. ;
  127. static BOOL _set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
  128. {
  129. ULONG possibleMask;
  130. SERIAL_DRIVER* pSerialSys = SerialSys_s();
  131. possibleMask = *pWaitMask & _SERCX_SYS_SUPPORTED_EV_MASK;
  132. if (possibleMask != *pWaitMask)
  133. {
  134. CommLog_Print(WLOG_WARN,
  135. "Not all wait events supported (SerCx.sys), requested events= 0x%08" PRIX32
  136. ", possible events= 0x%08" PRIX32 "",
  137. *pWaitMask, possibleMask);
  138. /* FIXME: shall we really set the possibleMask and return FALSE? */
  139. pComm->WaitEventMask = possibleMask;
  140. return FALSE;
  141. }
  142. /* NB: All events that are supported by SerCx.sys are supported by Serial.sys*/
  143. return pSerialSys->set_wait_mask(pComm, pWaitMask);
  144. }
  145. /* specific functions only */
  146. static SERIAL_DRIVER _SerCxSys = {
  147. .id = SerialDriverSerCxSys,
  148. .name = _T("SerCx.sys"),
  149. .set_baud_rate = NULL,
  150. .get_baud_rate = NULL,
  151. .get_properties = NULL,
  152. .set_serial_chars = NULL,
  153. .get_serial_chars = NULL,
  154. .set_line_control = NULL,
  155. .get_line_control = NULL,
  156. .set_handflow = _set_handflow,
  157. .get_handflow = _get_handflow,
  158. .set_timeouts = NULL,
  159. .get_timeouts = NULL,
  160. .set_dtr = NULL,
  161. .clear_dtr = NULL,
  162. .set_rts = NULL,
  163. .clear_rts = NULL,
  164. .get_modemstatus = NULL,
  165. .set_wait_mask = _set_wait_mask,
  166. .get_wait_mask = NULL,
  167. .wait_on_mask = NULL,
  168. .set_queue_size = NULL,
  169. .purge = NULL,
  170. .get_commstatus = NULL,
  171. .set_break_on = NULL,
  172. .set_break_off = NULL,
  173. .set_xoff = NULL,
  174. .set_xon = NULL,
  175. .get_dtrrts = NULL,
  176. .config_size = NULL, /* not supported by SerCx.sys */
  177. .immediate_char = NULL,
  178. .reset_device = NULL, /* not supported by SerCx.sys */
  179. };
  180. SERIAL_DRIVER* SerCxSys_s()
  181. {
  182. /* _SerCxSys completed with inherited functions from SerialSys */
  183. SERIAL_DRIVER* pSerialSys = SerialSys_s();
  184. _SerCxSys.set_baud_rate = pSerialSys->set_baud_rate;
  185. _SerCxSys.get_baud_rate = pSerialSys->get_baud_rate;
  186. _SerCxSys.get_properties = pSerialSys->get_properties;
  187. _SerCxSys.set_serial_chars = pSerialSys->set_serial_chars;
  188. _SerCxSys.get_serial_chars = pSerialSys->get_serial_chars;
  189. _SerCxSys.set_line_control = pSerialSys->set_line_control;
  190. _SerCxSys.get_line_control = pSerialSys->get_line_control;
  191. _SerCxSys.set_timeouts = pSerialSys->set_timeouts;
  192. _SerCxSys.get_timeouts = pSerialSys->get_timeouts;
  193. _SerCxSys.set_dtr = pSerialSys->set_dtr;
  194. _SerCxSys.clear_dtr = pSerialSys->clear_dtr;
  195. _SerCxSys.set_rts = pSerialSys->set_rts;
  196. _SerCxSys.clear_rts = pSerialSys->clear_rts;
  197. _SerCxSys.get_modemstatus = pSerialSys->get_modemstatus;
  198. _SerCxSys.set_wait_mask = pSerialSys->set_wait_mask;
  199. _SerCxSys.get_wait_mask = pSerialSys->get_wait_mask;
  200. _SerCxSys.wait_on_mask = pSerialSys->wait_on_mask;
  201. _SerCxSys.set_queue_size = pSerialSys->set_queue_size;
  202. _SerCxSys.purge = pSerialSys->purge;
  203. _SerCxSys.get_commstatus = pSerialSys->get_commstatus;
  204. _SerCxSys.set_break_on = pSerialSys->set_break_on;
  205. _SerCxSys.set_break_off = pSerialSys->set_break_off;
  206. _SerCxSys.set_xoff = pSerialSys->set_xoff;
  207. _SerCxSys.set_xon = pSerialSys->set_xon;
  208. _SerCxSys.get_dtrrts = pSerialSys->get_dtrrts;
  209. _SerCxSys.immediate_char = pSerialSys->immediate_char;
  210. return &_SerCxSys;
  211. }
  212. #endif /* __linux__ */