/platform/ChibiOS/os/hal/ports/simulator/win32/serial_lld.c

https://gitlab.com/fuggles/ucos · C · 278 lines · 169 code · 44 blank · 65 comment · 45 complexity · f9dc073948cc647d76c244ac271cbbe8 MD5 · raw file

  1. /*
  2. ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. /**
  14. * @file serial_lld.c
  15. * @brief Win32 simulator low level serial driver code.
  16. *
  17. * @addtogroup WIN32_SERIAL
  18. * @{
  19. */
  20. #include "hal.h"
  21. #if HAL_USE_SERIAL || defined(__DOXYGEN__)
  22. /*===========================================================================*/
  23. /* Driver exported variables. */
  24. /*===========================================================================*/
  25. /** @brief Serial driver 1 identifier.*/
  26. #if USE_WIN32_SERIAL1 || defined(__DOXYGEN__)
  27. SerialDriver SD1;
  28. #endif
  29. /** @brief Serial driver 2 identifier.*/
  30. #if USE_WIN32_SERIAL2 || defined(__DOXYGEN__)
  31. SerialDriver SD2;
  32. #endif
  33. /*===========================================================================*/
  34. /* Driver local variables and types. */
  35. /*===========================================================================*/
  36. /** @brief Driver default configuration.*/
  37. static const SerialConfig default_config = {
  38. };
  39. static u_long nb = 1;
  40. /*===========================================================================*/
  41. /* Driver local functions. */
  42. /*===========================================================================*/
  43. static void init(SerialDriver *sdp, uint16_t port) {
  44. struct sockaddr_in sad;
  45. struct protoent *prtp;
  46. if ((prtp = getprotobyname("tcp")) == NULL) {
  47. printf("%s: Error mapping protocol name to protocol number\n", sdp->com_name);
  48. goto abort;
  49. }
  50. sdp->com_listen = socket(PF_INET, SOCK_STREAM, prtp->p_proto);
  51. if (sdp->com_listen == INVALID_SOCKET) {
  52. printf("%s: Error creating simulator socket\n", sdp->com_name);
  53. goto abort;
  54. }
  55. if (ioctlsocket(sdp->com_listen, FIONBIO, &nb) != 0) {
  56. printf("%s: Unable to setup non blocking mode on socket\n", sdp->com_name);
  57. goto abort;
  58. }
  59. memset(&sad, 0, sizeof(sad));
  60. sad.sin_family = AF_INET;
  61. sad.sin_addr.s_addr = INADDR_ANY;
  62. sad.sin_port = htons(port);
  63. if (bind(sdp->com_listen, (struct sockaddr *)&sad, sizeof(sad))) {
  64. printf("%s: Error binding socket\n", sdp->com_name);
  65. goto abort;
  66. }
  67. if (listen(sdp->com_listen, 1) != 0) {
  68. printf("%s: Error listening socket\n", sdp->com_name);
  69. goto abort;
  70. }
  71. printf("Full Duplex Channel %s listening on port %d\n", sdp->com_name, port);
  72. return;
  73. abort:
  74. if (sdp->com_listen != INVALID_SOCKET)
  75. closesocket(sdp->com_listen);
  76. WSACleanup();
  77. exit(1);
  78. }
  79. static bool connint(SerialDriver *sdp) {
  80. if (sdp->com_data == INVALID_SOCKET) {
  81. struct sockaddr addr;
  82. int addrlen = sizeof(addr);
  83. if ((sdp->com_data = accept(sdp->com_listen, &addr, &addrlen)) == INVALID_SOCKET)
  84. return FALSE;
  85. if (ioctlsocket(sdp->com_data, FIONBIO, &nb) != 0) {
  86. printf("%s: Unable to setup non blocking mode on data socket\n", sdp->com_name);
  87. goto abort;
  88. }
  89. chSysLockFromISR();
  90. chnAddFlagsI(sdp, CHN_CONNECTED);
  91. chSysUnlockFromISR();
  92. return TRUE;
  93. }
  94. return FALSE;
  95. abort:
  96. if (sdp->com_listen != INVALID_SOCKET)
  97. closesocket(sdp->com_listen);
  98. if (sdp->com_data != INVALID_SOCKET)
  99. closesocket(sdp->com_data);
  100. WSACleanup();
  101. exit(1);
  102. }
  103. static bool inint(SerialDriver *sdp) {
  104. if (sdp->com_data != INVALID_SOCKET) {
  105. int i;
  106. uint8_t data[32];
  107. /*
  108. * Input.
  109. */
  110. int n = recv(sdp->com_data, (char *)data, sizeof(data), 0);
  111. switch (n) {
  112. case 0:
  113. closesocket(sdp->com_data);
  114. sdp->com_data = INVALID_SOCKET;
  115. chSysLockFromISR();
  116. chnAddFlagsI(sdp, CHN_DISCONNECTED);
  117. chSysUnlockFromISR();
  118. return FALSE;
  119. case SOCKET_ERROR:
  120. if (WSAGetLastError() == WSAEWOULDBLOCK)
  121. return FALSE;
  122. closesocket(sdp->com_data);
  123. sdp->com_data = INVALID_SOCKET;
  124. return FALSE;
  125. }
  126. for (i = 0; i < n; i++) {
  127. chSysLockFromISR();
  128. sdIncomingDataI(sdp, data[i]);
  129. chSysUnlockFromISR();
  130. }
  131. return TRUE;
  132. }
  133. return FALSE;
  134. }
  135. static bool outint(SerialDriver *sdp) {
  136. if (sdp->com_data != INVALID_SOCKET) {
  137. int n;
  138. uint8_t data[1];
  139. /*
  140. * Input.
  141. */
  142. chSysLockFromISR();
  143. n = sdRequestDataI(sdp);
  144. chSysUnlockFromISR();
  145. if (n < 0)
  146. return FALSE;
  147. data[0] = (uint8_t)n;
  148. n = send(sdp->com_data, (char *)data, sizeof(data), 0);
  149. switch (n) {
  150. case 0:
  151. closesocket(sdp->com_data);
  152. sdp->com_data = INVALID_SOCKET;
  153. chSysLockFromISR();
  154. chnAddFlagsI(sdp, CHN_DISCONNECTED);
  155. chSysUnlockFromISR();
  156. return FALSE;
  157. case SOCKET_ERROR:
  158. if (WSAGetLastError() == WSAEWOULDBLOCK)
  159. return FALSE;
  160. closesocket(sdp->com_data);
  161. sdp->com_data = INVALID_SOCKET;
  162. return FALSE;
  163. }
  164. return TRUE;
  165. }
  166. return FALSE;
  167. }
  168. /*===========================================================================*/
  169. /* Driver interrupt handlers. */
  170. /*===========================================================================*/
  171. /*===========================================================================*/
  172. /* Driver exported functions. */
  173. /*===========================================================================*/
  174. /**
  175. * Low level serial driver initialization.
  176. */
  177. void sd_lld_init(void) {
  178. #if USE_WIN32_SERIAL1
  179. sdObjectInit(&SD1, NULL, NULL);
  180. SD1.com_listen = INVALID_SOCKET;
  181. SD1.com_data = INVALID_SOCKET;
  182. SD1.com_name = "SD1";
  183. #endif
  184. #if USE_WIN32_SERIAL1
  185. sdObjectInit(&SD2, NULL, NULL);
  186. SD2.com_listen = INVALID_SOCKET;
  187. SD2.com_data = INVALID_SOCKET;
  188. SD2.com_name = "SD2";
  189. #endif
  190. }
  191. /**
  192. * @brief Low level serial driver configuration and (re)start.
  193. *
  194. * @param[in] sdp pointer to a @p SerialDriver object
  195. * @param[in] config the architecture-dependent serial driver configuration.
  196. * If this parameter is set to @p NULL then a default
  197. * configuration is used.
  198. */
  199. void sd_lld_start(SerialDriver *sdp, const SerialConfig *config) {
  200. if (config == NULL)
  201. config = &default_config;
  202. #if USE_WIN32_SERIAL1
  203. if (sdp == &SD1)
  204. init(&SD1, SD1_PORT);
  205. #endif
  206. #if USE_WIN32_SERIAL1
  207. if (sdp == &SD2)
  208. init(&SD2, SD2_PORT);
  209. #endif
  210. }
  211. /**
  212. * @brief Low level serial driver stop.
  213. * @details De-initializes the USART, stops the associated clock, resets the
  214. * interrupt vector.
  215. *
  216. * @param[in] sdp pointer to a @p SerialDriver object
  217. */
  218. void sd_lld_stop(SerialDriver *sdp) {
  219. (void)sdp;
  220. }
  221. bool sd_lld_interrupt_pending(void) {
  222. bool b;
  223. CH_IRQ_PROLOGUE();
  224. b = connint(&SD1) || connint(&SD2) ||
  225. inint(&SD1) || inint(&SD2) ||
  226. outint(&SD1) || outint(&SD2);
  227. CH_IRQ_EPILOGUE();
  228. return b;
  229. }
  230. #endif /* HAL_USE_SERIAL */
  231. /** @} */