PageRenderTime 25ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/software/ubd/src/serial.c

https://github.com/schneider42/uberbus
C | 190 lines | 161 code | 18 blank | 11 comment | 32 complexity | bd4b3b7396f9970f89f5d20cb1198e3a MD5 | raw file
  1. #include <config.h>
  2. #include <stdio.h>
  3. #include <glib.h>
  4. #include <fcntl.h>
  5. #include <termios.h>
  6. #include <stdint.h>
  7. #include <string.h>
  8. #include "debug.h"
  9. #include "serial.h"
  10. #include <unistd.h>
  11. #include <errno.h>
  12. #include <syslog.h>
  13. uint8_t serial_buffer[SERIAL_BUFFERLEN];
  14. int fd;
  15. GTimeVal start;
  16. static uint16_t serial_in(uint8_t data);
  17. inline int serial_putc(uint8_t c)
  18. {
  19. return write(fd,&c,1);
  20. }
  21. inline void serial_putcenc(uint8_t c)
  22. {
  23. if(c == SERIAL_ESCAPE)
  24. serial_putc(SERIAL_ESCAPE);
  25. serial_putc(c);
  26. }
  27. void serial_putsenc(char * s)
  28. {
  29. while(*s){
  30. if(*s == SERIAL_ESCAPE)
  31. serial_putc(SERIAL_ESCAPE);
  32. serial_putc(*s++);
  33. }
  34. }
  35. void serial_putenc(uint8_t * d, uint16_t n)
  36. {
  37. uint16_t i;
  38. for(i=0;i<n;i++){
  39. if(*d == SERIAL_ESCAPE)
  40. serial_putc(SERIAL_ESCAPE);
  41. serial_putc(*d++);
  42. }
  43. }
  44. inline void serial_putStart(void)
  45. {
  46. serial_putc(SERIAL_ESCAPE);
  47. serial_putc(SERIAL_START);
  48. }
  49. inline void serial_putStop(void)
  50. {
  51. serial_putc(SERIAL_ESCAPE);
  52. serial_putc(SERIAL_END);
  53. }
  54. void serial_sendFrames(char * s)
  55. {
  56. serial_putStart();
  57. serial_putsenc(s);
  58. serial_putStop();
  59. }
  60. void serial_sendFramec(uint8_t c)
  61. {
  62. serial_putStart();
  63. serial_putcenc(c);
  64. serial_putStop();
  65. }
  66. static uint16_t serial_in(uint8_t data)
  67. {
  68. static int fill = -1;
  69. static uint8_t escaped = 0;
  70. int tmp;
  71. /*syslog(LOG_DEBUG,"serial: in:");
  72. debug_hexdump(&data,1);
  73. syslog(LOG_DEBUG,"\n");*/
  74. if(data == SERIAL_ESCAPE){
  75. if(!escaped){
  76. escaped = 1;
  77. return 0;
  78. }
  79. escaped = 0;
  80. }else if(escaped){
  81. escaped = 0;
  82. if(data == SERIAL_START){
  83. g_get_current_time(&start);
  84. fill = 0;
  85. return 0;
  86. }else if( data == SERIAL_END){
  87. ub_assert(fill != -1);
  88. tmp = fill;
  89. fill = -1;
  90. return tmp;
  91. }
  92. }
  93. if( fill > -1 ){
  94. //TODO: prevent overflow!
  95. serial_buffer[fill++] = data;
  96. }else if(fill >= SERIAL_BUFFERLEN){
  97. fill = -1;
  98. }
  99. return 0;
  100. }
  101. void serial_readMessage(struct message * msg)
  102. {
  103. uint8_t len;
  104. while( 1 ){
  105. uint8_t c;
  106. int rc = read(fd,&c,1);
  107. if( rc > 0){
  108. len = serial_in(c);
  109. if( len ){
  110. if( serial_buffer[0] != 'P' ){
  111. syslog(LOG_DEBUG,"%ld.%04ld serial: new message: ->",start.tv_sec,start.tv_usec);
  112. debug_hexdump(serial_buffer, len);syslog(LOG_DEBUG,"<-\n");
  113. }
  114. msg->len = len;
  115. if( sizeof(msg->data) >= len ){
  116. memcpy(msg->data,serial_buffer,msg->len);
  117. return;
  118. }else{
  119. //TODO: log this error
  120. ub_assert( sizeof(msg->data) >= len);
  121. }
  122. }
  123. }else if( rc == 0){
  124. syslog(LOG_WARNING,"timeout on serial line\n");
  125. }else if( rc < 0){
  126. syslog(LOG_ERR,"error while reading from serial line: rc=%d errno=%d\n",rc,errno);
  127. }
  128. }
  129. }
  130. void serial_writeMessage(struct message * outmsg)
  131. {
  132. //syslog(LOG_DEBUG,"serial: write message: ->");debug_hexdump(outmsg->data, outmsg->len);
  133. //syslog(LOG_DEBUG,"<-\n");
  134. serial_putStart();
  135. serial_putenc((uint8_t*) outmsg->data, outmsg->len);
  136. serial_putStop();
  137. //tcdrain(fd);
  138. //tcflush(fd,TCOFLUSH);
  139. }
  140. void serial_switch(void)
  141. {
  142. syslog(LOG_INFO,"switching serial node to bridge mode\n");
  143. serial_sendFrames("B");
  144. struct message m;
  145. //return;
  146. while(1){
  147. serial_readMessage(&m);
  148. if( m.len == 1 && m.data[0] == 'B' )
  149. break;
  150. }
  151. syslog(LOG_INFO,"done\n");
  152. //usleep(1000*1000*2);
  153. }
  154. int serial_open (char * device)
  155. {
  156. fd = open(device, O_RDWR|O_NOCTTY);// |O_SYNC);//|O_NONBLOCK);
  157. if( fd == -1 ){
  158. return -1;
  159. }
  160. struct termios tio;
  161. bzero(&tio, sizeof(tio));
  162. tio.c_cflag = CREAD | CLOCAL | B115200 | CS8;
  163. tio.c_iflag = IGNPAR | IGNBRK;
  164. tio.c_oflag = 0;
  165. tio.c_lflag = 0;
  166. tio.c_cc[VTIME] = 100;
  167. tio.c_cc[VMIN] = 1;
  168. tcsetattr (fd, TCSANOW, &tio);
  169. tcflush (fd, TCIFLUSH);
  170. tcflush (fd, TCOFLUSH);
  171. return 0;
  172. }