rs232d.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /*!
  2. * Copyright (C) 2013 by Ole Reinhardt <ole.reinhardt@embedded-it.de>
  3. * Copyright (C) 2001-2005 by egnite Software GmbH.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. /*!
  36. * $Id: rs232d.c 4999 2013-02-22 10:59:22Z olereinhardt $
  37. */
  38. /*!
  39. * \example rs232d_select/rs232d_select.c
  40. *
  41. * Simple RS232 server implemented using select(). No extra threads are
  42. * needed as we can wait for activity on both filedescriptors (uart and
  43. * socket) at the same time using the select() call.
  44. *
  45. * Use a serial cable to connect the RS232 port
  46. * of the Ethernut Board with a COM port of a PC. Start a terminal
  47. * program and a telnet client on the PC. Telnet should connect to
  48. * the Ethernut Board.
  49. *
  50. * Characters typed in the telnet window will appear in the terminal
  51. * program window and vice versa. Baudrate is 9600.
  52. *
  53. */
  54. #include <dev/board.h>
  55. #include <sys/heap.h>
  56. #include <sys/thread.h>
  57. #include <sys/timer.h>
  58. #include <sys/socket.h>
  59. #include <sys/select.h>
  60. #include <sys/confnet.h>
  61. #include <stdlib.h>
  62. #include <stdio.h>
  63. #include <string.h>
  64. #include <io.h>
  65. #include <fcntl.h>
  66. #include <arpa/inet.h>
  67. #include <net/if_var.h>
  68. #include <pro/dhcp.h>
  69. #define BUFFERSIZE 128
  70. #define TCPPORT 23
  71. #define max(a,b) ((a)>=(b)?(a):(b))
  72. typedef struct {
  73. FILE *cd_rs232;
  74. FILE *cd_tcpip;
  75. } CHANNEL;
  76. /*
  77. * Transfer data from input stream to output stream. Wait for incomming data
  78. * on both streams using the select() function.
  79. */
  80. void StreamCopy(FILE * stream_sock, FILE * stream_uart)
  81. {
  82. fd_set rfds;
  83. int rc;
  84. char *buff;
  85. size_t cnt;
  86. buff = malloc(BUFFERSIZE);
  87. for(;;) {
  88. FD_ZERO(&rfds);
  89. /* Request read notification for the socket and the uart stream*/
  90. FD_SET(_fileno(stream_sock), &rfds);
  91. FD_SET(_fileno(stream_uart), &rfds);
  92. /* Wait for notification on the rfds descriptor set. Wait with infinite timeout.
  93. If the socket is closed by the foreign host, select will return a notification
  94. of stream_sock as well, but fread will return 0, which indicates the closed socket.
  95. */
  96. rc = select(max(_fileno (stream_sock), _fileno (stream_uart)) + 1, &rfds, NULL, NULL, NULL);
  97. if (rc > 0) {
  98. if (FD_ISSET(_fileno(stream_sock), &rfds)) {
  99. /* Copy the data from socket to uart. Return if an error occured during read or write. */
  100. if ((cnt = fread(buff, 1, BUFFERSIZE, stream_sock)) == 0)
  101. break;
  102. if ((cnt = fwrite(buff, 1, cnt, stream_uart)) == 0)
  103. break;
  104. if (fflush(stream_uart))
  105. break;
  106. }
  107. if (FD_ISSET(_fileno(stream_uart), &rfds)) {
  108. /* Copy the data from uart to socket. Return if an error occured during read or write. */
  109. if ((cnt = fread(buff, 1, BUFFERSIZE, stream_uart)) == 0)
  110. break;
  111. if ((cnt = fwrite(buff, 1, cnt, stream_sock)) == 0)
  112. break;
  113. if (fflush(stream_sock))
  114. break;
  115. }
  116. } else
  117. if (rc < 0) {
  118. /* An error occured during select. Free allocated buffer and return... */
  119. free(buff);
  120. return;
  121. }
  122. }
  123. /* Free allocated buffer */
  124. free(buff);
  125. }
  126. /*
  127. * Main application routine.
  128. *
  129. * Nut/OS automatically calls this entry after initialization.
  130. */
  131. int main(void)
  132. {
  133. TCPSOCKET *sock;
  134. CHANNEL cd;
  135. uint32_t baud = 9600;
  136. /*
  137. * Register our devices.
  138. */
  139. NutRegisterDevice(&DEV_UART, 0, 0);
  140. #ifndef DEV_ETHER
  141. for (;;);
  142. #else
  143. NutRegisterDevice(&DEV_ETHER, 0x8300, 5);
  144. /*
  145. * Setup the uart device.
  146. */
  147. cd.cd_rs232 = fopen(DEV_UART_NAME, "r+b");
  148. _ioctl(_fileno(cd.cd_rs232), UART_SETSPEED, &baud);
  149. /*
  150. * Setup the ethernet device. Try DHCP first. If this is
  151. * the first time boot with empty EEPROM and no DHCP server
  152. * was found, use hardcoded values.
  153. */
  154. if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
  155. /* No valid EEPROM contents, use hard coded MAC. */
  156. uint8_t my_mac[] = { 0x00, 0x06, 0x98, 0x20, 0x00, 0x00 };
  157. if (NutDhcpIfConfig("eth0", my_mac, 60000)) {
  158. /* No DHCP server found, use hard coded IP address. */
  159. uint32_t ip_addr = inet_addr("192.168.192.100");
  160. uint32_t ip_mask = inet_addr("255.255.255.0");
  161. NutNetIfConfig("eth0", my_mac, ip_addr, ip_mask);
  162. /* If not in a local network, we must also call
  163. NutIpRouteAdd() to configure the routing. */
  164. }
  165. }
  166. /*
  167. * Now loop endless for connections.
  168. */
  169. for (;;) {
  170. /*
  171. * Create a socket and listen for a client.
  172. */
  173. sock = NutTcpCreateSocket();
  174. NutTcpAccept(sock, TCPPORT);
  175. /*
  176. * Open a stdio stream assigned to the connected socket.
  177. */
  178. cd.cd_tcpip = _fdopen((int) sock, "r+b");
  179. /*
  180. * Call Socket <-> RS232 copy routine. On return we will be
  181. * disconnected again.
  182. */
  183. StreamCopy(cd.cd_tcpip, cd.cd_rs232);
  184. /*
  185. * Close the stream.
  186. */
  187. fclose(cd.cd_tcpip);
  188. /*
  189. * Close our socket.
  190. */
  191. NutTcpCloseSocket(sock);
  192. }
  193. #endif
  194. return 0;
  195. }