Advertisement
Guest User

Untitled

a guest
Jul 21st, 2013
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.36 KB | None | 0 0
  1. /**
  2. * File:
  3. * sr.c
  4. *
  5. * Notes:
  6. * This file contains native routines for sending and receiving data from
  7. * a specified serial device.
  8. *
  9. * History:
  10. * 2013/07/06 Written by Simon Platten
  11. */
  12. #include <errno.h>
  13. #include <fcntl.h>
  14. #include <termios.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <time.h>
  21. #include <unistd.h>
  22.  
  23. #include "sr.h"
  24. // Constants
  25. #define BUFFER_SIZE 32
  26. #define TD_BUFFER_SIZE 80
  27. #define BILLION ((long)1000000000)
  28. #define SERIAL_TIMEOUT 1000
  29. // Buffer to receive data into
  30. static char arycData[BUFFER_SIZE];
  31. // End of line
  32. static char* pstrEOL = ".\n";
  33. // Reference time used for detecting timeout
  34. struct timespec tsStartTime;
  35. // THe number of bytes in the receive buffer
  36. static int intTotalReceived;
  37. /**
  38. * Function:
  39. * elapsedTime
  40. *
  41. * Parameters:
  42. * ptsRef, a pointer to the reference time
  43. *
  44. * Returns:
  45. * The number of seconds between the reference time and now
  46. */
  47. static double elapsedTime(struct timespec* ptsRef) {
  48. // Get the time now
  49. struct timespec tsNow;
  50. if( ptsRef == NULL || clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &tsNow ) == -1 ) {
  51. return 0;
  52. }
  53. return ((tsNow.tv_sec - ptsRef->tv_sec) +
  54. (double)(tsNow.tv_nsec - ptsRef->tv_nsec) / (double)BILLION);
  55. }
  56. /**
  57. * Returns a pointer to a human readable time and date stamp
  58. */
  59. static char* getTimestamp(void) {
  60. // Get the current time
  61. static char strBuffer[TD_BUFFER_SIZE];
  62. time_t curtime = time(NULL);
  63. // Convert time to local time representation
  64. struct tm* pLocalTime = localtime(&curtime);
  65. strftime(strBuffer, TD_BUFFER_SIZE, "%a, %Y-%b-%d %T", pLocalTime);
  66. return strBuffer;
  67. }
  68. /**
  69. * Function:
  70. * readDevice
  71. *
  72. * Parameters:
  73. * intFD, the port file descriptor
  74. * blnDebug, JNI_TRUE to enable debug messages
  75. *
  76. * Returns:
  77. * A pointer to the start of the input buffer or NULL if no content
  78. */
  79. static char* readDevice(int intFD, jboolean blnDebug) {
  80. int intRead, intSpaceInBuffer = sizeof(arycData)-1;
  81. char* pBuffer = arycData;
  82. intTotalReceived = 0;
  83. memset( arycData, 0, sizeof(arycData) );
  84. while( (intRead = read( intFD, pBuffer, 1 )) > 0 ) {
  85. pBuffer += intRead;
  86. intTotalReceived += intRead;
  87. intSpaceInBuffer -= intRead;
  88.  
  89. if ( pBuffer[-1] == '\n' || intSpaceInBuffer <= 0 ) {
  90. break;
  91. }
  92. }
  93. if ( blnDebug == JNI_TRUE && intTotalReceived > 0 ) {
  94. int i;
  95. printf("%s, receive[%d]: ", getTimestamp(), intTotalReceived);
  96. for( i=0; i<intTotalReceived; i++ ) {
  97. printf("%c", arycData[i]);
  98. }
  99. printf(pstrEOL);
  100. }
  101. return ( intTotalReceived > 0 ) ? arycData : NULL;
  102. }
  103. /*
  104. * Class: cantley_co_uk_clsMain
  105. * Method: openDevice
  106. * Signature: (Ljava/lang/String;Z)I
  107. */
  108. JNIEXPORT jint JNICALL Java_cantley_co_uk_clsMain_openDevice
  109. (JNIEnv *pEnv, jclass obj, jstring strDevice, jboolean blnRx, jboolean blnDebug) {
  110. const char *pstrDevice = (*pEnv)->GetStringUTFChars(pEnv, strDevice, NULL);
  111. // Try to open the port
  112. int intFD = open(pstrDevice, O_RDWR | O_NOCTTY | O_NDELAY);
  113.  
  114. if ( intFD >= 0 ) {
  115. struct termios options;
  116. // Get the current options for the port...
  117. tcgetattr(intFD, &options);
  118. // Set the baud rates to 115200...
  119. cfsetispeed(&options, B115200);
  120. cfsetospeed(&options, B115200);
  121. options.c_cflag |= (CLOCAL | CREAD);
  122. // No parity, 8 data bits 1 stop bit
  123. options.c_cflag &= ~PARENB;
  124. options.c_cflag &= ~CSTOPB;
  125. options.c_cflag &= ~CSIZE;
  126. options.c_cflag |= CS8;
  127. options.c_cflag &= ~CRTSCTS;
  128. // Disable Xon/Xoff ctrl
  129. options.c_cflag &= ~(IXON | IXOFF | IXANY);
  130. options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  131. options.c_oflag &= ~OPOST;
  132. options.c_cc[VMIN] = 0;
  133. options.c_cc[VTIME] = 1;
  134. tcsetattr(intFD, TCSANOW, &options);
  135. fcntl(intFD, F_SETFL, FNDELAY);
  136.  
  137. if ( blnRx == JNI_TRUE ) {
  138. // Device is being used for Rx flush any data that hasn't been received yet
  139. while( readDevice(intFD, JNI_FALSE) != NULL ) {
  140. }
  141. if ( blnDebug == JNI_TRUE ) {
  142. printf("%s port flushed%s", pstrDevice, pstrEOL);
  143. }
  144. // Get the start reference time
  145. clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tsStartTime);
  146. }
  147. if ( blnDebug == JNI_TRUE ) {
  148. printf("%s opened and ready for use%s", pstrDevice, pstrEOL);
  149. }
  150. } else if ( blnDebug == JNI_TRUE ) {
  151. printf("%s, port not ready%s", pstrDevice, pstrEOL);
  152. }
  153. (*pEnv)->ReleaseStringUTFChars(pEnv, strDevice, pstrDevice);
  154. return intFD;
  155. }
  156. /*
  157. * Class: cantley_co_uk_clsMain
  158. * Method: receive
  159. * Signature: (I)Ljava/lang/String;
  160. */
  161. JNIEXPORT jbyteArray JNICALL Java_cantley_co_uk_clsMain_receive
  162. (JNIEnv* pEnv, jclass obj, jint intFD, jboolean blnDebug) {
  163. jbyteArray aryRC = NULL;
  164.  
  165. if ( intFD >= 0 ) {
  166. int intRead, intSpaceInBuffer = BUFFER_SIZE;
  167. char *pBuffer;
  168. // Loop until a packet has been received or a timeout occurs
  169. while( 1 ) {
  170. // Look for data in the receive buffer from the device
  171. pBuffer = readDevice(intFD, blnDebug);
  172.  
  173. if ( pBuffer == NULL || arycData[0] != '$' ) {
  174. // Has timeout occurred?
  175. double lfElapsedTime = elapsedTime(&tsStartTime);
  176.  
  177. if ( lfElapsedTime > SERIAL_TIMEOUT ) {
  178. if ( blnDebug == JNI_TRUE ) {
  179. printf("%s, receive timeout%s", getTimestamp(), pstrEOL);
  180. }
  181. return NULL;
  182. }
  183. } else {
  184. // A valid packet has been received, or it looks like it
  185. break;
  186. }
  187. }
  188. // Reset reference time
  189. clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tsStartTime);
  190. aryRC = (*pEnv)->NewByteArray(pEnv, BUFFER_SIZE);
  191.  
  192. if ( aryRC ) {
  193. (*pEnv)->SetByteArrayRegion(pEnv, aryRC, 0,
  194. intTotalReceived, (jbyte*)pBuffer);
  195. }
  196. }
  197. return aryRC;
  198. }
  199. /*
  200. * Class: cantley_co_uk_clsMain
  201. * Method: send
  202. * Signature: (ILjava/lang/String;)V
  203. */
  204. JNIEXPORT void JNICALL Java_cantley_co_uk_clsMain_send
  205. (JNIEnv* pEnv, jclass obj, jint intFD, jstring strData, jboolean blnDebug) {
  206. const char *pstrData = (*pEnv)->GetStringUTFChars(pEnv, strData, NULL);
  207. int intLength;
  208.  
  209. if ( intFD >= 0 && pstrData && (intLength = strlen(pstrData)) > 0 ) {
  210. // Write to the device
  211. int intWritten = write(intFD, pstrData, intLength);
  212.  
  213. if ( blnDebug == JNI_TRUE ) {
  214. if ( intWritten <= 0 ) {
  215. printf("%s, send: failed%s",
  216. getTimestamp(), pstrEOL);
  217. } else {
  218. printf("%s, send[%d]: %s",
  219. getTimestamp(), intWritten, pstrData);
  220. }
  221. }
  222. }
  223. (*pEnv)->ReleaseStringUTFChars(pEnv, strData, pstrData);
  224. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement