Testing out the PPD42 Air Quality Sensor, with an MSP430 Launchpad and graphing the data with GNUplot.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5405 lines
147 KiB

5 years ago
  1. /*-------------------------------------------------------------------------
  2. | rxtx is a native interface to serial ports in java.
  3. | Copyright 1997-2004 by Trent Jarvi taj@www.linux.org.uk
  4. |
  5. | This library is free software; you can redistribute it and/or
  6. | modify it under the terms of the GNU Library General Public
  7. | License as published by the Free Software Foundation; either
  8. | version 2 of the License, or (at your option) any later version.
  9. |
  10. | This library is distributed in the hope that it will be useful,
  11. | but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. | Library General Public License for more details.
  14. |
  15. | You should have received a copy of the GNU Library General Public
  16. | License along with this library; if not, write to the Free
  17. | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. --------------------------------------------------------------------------*/
  19. #include "gnu/io/RXTXPort.h" /* dima */
  20. #include "gnu/io/RXTXCommDriver.h" /* dima */
  21. #include "gnu/io/PortInUseException.h"
  22. #if defined(__MWERKS__) /* dima */
  23. #else /* dima */
  24. #include "config.h"
  25. #endif /* dima */
  26. #ifndef __LCC__
  27. # include <unistd.h>
  28. #else /* windows lcc compiler for fd_set. probably wrong */
  29. # include<winsock.h>
  30. #endif /* __LCC__ */
  31. #include <time.h>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <errno.h>
  36. #include <limits.h>
  37. #include <sys/stat.h>
  38. #ifndef WIN32
  39. #include <sys/ioctl.h>
  40. #include <sys/param.h>
  41. #include <sys/utsname.h>
  42. #include <pthread.h>
  43. #else
  44. # include <win32termios.h>
  45. /* FIXME returns 0 in all cases on win32
  46. #define S_ISCHR(m) (((m)&S_IFMT) == S_IFCHR)
  47. */
  48. # if !defined(S_ISCHR)
  49. # define S_ISCHR(m) (1)
  50. # endif /* S_ISCHR(m) */
  51. #endif /* WIN32 */
  52. #ifdef HAVE_ASM_TERMBITS_H
  53. //# include <asm/termbits.h>
  54. #endif /* HAVE_ASM_TERMBITS_H */
  55. #ifdef HAVE_TERMIOS_H
  56. # include <termios.h>
  57. #endif /* HAVE_TERMIOS_H */
  58. #ifdef HAVE_SIGNAL_H
  59. # include <signal.h>
  60. #endif /* HAVE_SIGNAL_H */
  61. #ifdef HAVE_SYS_SIGNAL_H
  62. # include <sys/signal.h>
  63. #endif /* HAVE_SYS_SIGNAL_H */
  64. #include <sys/types.h>
  65. #ifdef HAVE_SYS_TIME_H
  66. # include <sys/time.h>
  67. #endif /* HAVE_SYS_TIME_H */
  68. # include <fcntl.h>
  69. #ifdef HAVE_SYS_FCNTL_H
  70. # include <sys/fcntl.h>
  71. #endif /* HAVE_SYS_FCNTL_H */
  72. #ifdef HAVE_SYS_FILE_H
  73. # include <sys/file.h>
  74. #endif /* HAVE_SYS_FILE_H */
  75. #ifdef LFS /* File Lock Server */
  76. # include <sys/socket.h>
  77. # include <netinet/in.h>
  78. # include <arpa/inet.h>
  79. #endif /* FLS */
  80. #if defined(__linux__)
  81. # include <linux/types.h> /* fix for linux-2.3.4? kernels */
  82. # include <linux/serial.h>
  83. # include <linux/version.h>
  84. #endif /* __linux__ */
  85. #if defined(__sun__)
  86. # include <sys/filio.h>
  87. # include <sys/mkdev.h>
  88. #endif /* __sun__ */
  89. #if defined(__hpux__)
  90. # include <sys/modem.h>
  91. #endif /* __hpux__ */
  92. /* FIXME -- new file */
  93. #if defined(__APPLE__)
  94. # include <CoreFoundation/CoreFoundation.h>
  95. # include <IOKit/IOKitLib.h>
  96. # include <IOKit/serial/IOSerialKeys.h>
  97. # include <IOKit/IOBSD.h>
  98. #endif /* __APPLE__ */
  99. #ifdef __unixware__
  100. # include <sys/filio.h>
  101. #endif /* __unixware__ */
  102. #ifdef HAVE_PWD_H
  103. #include <pwd.h>
  104. #endif /* HAVE_PWD_H */
  105. #ifdef HAVE_GRP_H
  106. #include <grp.h>
  107. #endif /* HAVE_GRP_H */
  108. #include <math.h>
  109. extern int errno;
  110. #include "SerialImp.h"
  111. #include <gcj/cni.h>
  112. #include <java/lang/System.h>
  113. #include <java/io/PrintStream.h>
  114. #include <java/lang/String.h>
  115. #include <java/io/IOException.h>
  116. #include <gnu/io/UnsupportedCommOperationException.h>
  117. #include <java/lang/ArrayIndexOutOfBoundsException.h>
  118. //#define TRENT_IS_HERE_DEBUGGING_ENUMERATION
  119. struct preopened *preopened_port = NULL;
  120. #if defined(__sun__) || defined(__hpux__)
  121. /*----------------------------------------------------------
  122. cfmakeraw
  123. accept: termios to be set to raw
  124. perform: initializes the termios structure.
  125. return: int 0 on success
  126. exceptions: none
  127. comments: this is how linux cfmakeraw works.
  128. termios(3) manpage
  129. ----------------------------------------------------------*/
  130. int cfmakeraw ( struct termios *term )
  131. {
  132. ENTER( "cfmakeraw" );
  133. term->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
  134. term->c_oflag &= ~OPOST;
  135. term->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
  136. term->c_cflag &= ~(CSIZE|PARENB);
  137. term->c_cflag |= CS8;
  138. LEAVE( "cfmakeraw" );
  139. return( 0 );
  140. }
  141. #endif /* __sun__ || __hpux__ */
  142. #ifdef DEBUG_TIMING
  143. struct timeval snow, enow, seloop, eeloop;
  144. #define report_time_eventLoop( ) { \
  145. if ( seloop.tv_sec == eeloop.tv_sec && seloop.tv_usec == eeloop.tv_usec ) \
  146. { \
  147. gettimeofday(&eeloop, NULL); \
  148. seloop.tv_sec = eeloop.tv_sec; \
  149. seloop.tv_usec = eeloop.tv_usec; \
  150. printf("%8i sec : %8i usec\n", eeloop.tv_sec - seloop.tv_sec, eeloop.tv_usec - seloop.tv_usec); \
  151. } \
  152. }
  153. #define report_time( ) \
  154. { \
  155. struct timeval now; \
  156. gettimeofday(&now, NULL); \
  157. mexPrintf("%8s : %5i : %8i sec : %8i usec\n", __TIME__, __LINE__, now.tv_sec, now.tv_usec); \
  158. }
  159. #define report_time_start( ) \
  160. { \
  161. gettimeofday(&snow, NULL); \
  162. mexPrintf("%8s : %5i : %8i sec : %8i usec", __TIME__, __LINE__, snow.tv_sec, snow.tv_usec); \
  163. }
  164. #define report_time_end( ) \
  165. { \
  166. gettimeofday(&enow, NULL); \
  167. mexPrintf("%8i sec : %8i usec\n", enow.tv_sec - snow.tv_sec, enow.tv_sec - snow.tv_sec?snow.tv_usec-enow.tv_usec:enow.tv_usec - snow.tv_usec); \
  168. }
  169. #else
  170. #define report_time_eventLoop( ){};
  171. #define report_time( ) {}
  172. #define report_time_start( ) {}
  173. #define report_time_end( ) {}
  174. #endif /* DEBUG_TIMING */
  175. struct event_info_struct *master_index = NULL;
  176. /*----------------------------------------------------------
  177. RXTXPort.Initialize
  178. accept: none
  179. perform: Initialize the native library
  180. return: none
  181. exceptions: none
  182. comments: Basically this just causes rxtx to ignore signals. signal
  183. handlers where tried but the VM (circa 1.1) did not like it.
  184. It also allows for some sanity checks on linux boxes if DEBUG
  185. is enabled.
  186. ----------------------------------------------------------*/
  187. void gnu::io::RXTXPort::Initialize(
  188. )
  189. {
  190. #if defined DEBUG && defined(__linux__)
  191. struct utsname name;
  192. char message[80];
  193. #endif /* DEBUG && __linux__ */
  194. /* This bit of code checks to see if there is a signal handler installed
  195. for SIGIO, and installs SIG_IGN if there is not. This is necessary
  196. for the native threads jdk, but we don't want to do it with green
  197. threads, because it slows things down. Go figure. */
  198. /* POSIX signal handling functions */
  199. #if !defined(WIN32)
  200. struct sigaction old_action;
  201. sigaction(SIGIO, NULL, &old_action);
  202. /* green threads already has handler, no touch */
  203. if (old_action.sa_handler == NULL) {
  204. /* no handler when using native threads, set to ignore */
  205. struct sigaction new_action;
  206. sigset_t block_mask;
  207. sigemptyset(&block_mask);
  208. new_action.sa_handler = SIG_IGN;
  209. #ifdef SA_RESTART
  210. new_action.sa_flags = SA_RESTART;
  211. #endif /* SA_RESTART */
  212. new_action.sa_mask = block_mask;
  213. sigaction(SIGIO, &new_action, NULL);
  214. }
  215. #endif /* !WIN32 */
  216. ENTER( "RXTXPort:Initialize" );
  217. #ifdef PRERELEASE
  218. /* this is just for avoiding confusion while testing new libraries */
  219. #ifdef DEBUG_MW
  220. mexPrintf("RXTX Prerelease for testing Tue Feb 19 18:00:27 EST 2002\n");
  221. #else
  222. printf("RXTX Prerelease for testing Thu Feb 21 19:31:38\n");
  223. #endif /* DEBUG_MW */
  224. #endif /* PRERELEASE */
  225. #if DEBUG_TIMING
  226. gettimeofday(&seloop, NULL);
  227. #endif /* DEBUG_TIMING */
  228. #if defined(DEBUG) && defined(__linux__)
  229. /* Lets let people who upgraded kernels know they may have problems */
  230. if (uname (&name) == -1)
  231. {
  232. report( "RXTX WARNING: cannot get system name\n" );
  233. LEAVE( "RXTXPort:Initialize" );
  234. return;
  235. }
  236. if(strcmp(name.release,UTS_RELEASE)!=0)
  237. {
  238. sprintf( message, LINUX_KERNEL_VERSION_ERROR, UTS_RELEASE,
  239. name.release );
  240. report( message );
  241. getchar();
  242. }
  243. LEAVE( "RXTXPort:Initialize" );
  244. #endif /* DEBUG && __linux__ */
  245. }
  246. /*----------------------------------------------------------
  247. RXTXPort.find_preopened_ports
  248. accept: The device to find if preopened. ie "/dev/ttyS0"
  249. perform: find the filedescriptor if preopened
  250. return: fd
  251. exceptions: none
  252. comments: see
  253. RXTXPort.nativeStaticSetDSR
  254. RXTXPort.nativeStaticSetDTR
  255. RXTXPort.nativeStaticSetRTS
  256. RXTXPort.nativeStaticSetSerialPortParams
  257. This is used so people can setDTR low before calling the
  258. Java open().
  259. ----------------------------------------------------------*/
  260. int find_preopened_ports( const char *filename )
  261. {
  262. int fd;
  263. struct preopened *p = preopened_port;
  264. if( !p )
  265. {
  266. return(0);
  267. }
  268. for(;;)
  269. {
  270. if( !strcmp( p->filename, filename) )
  271. {
  272. fd = p->fd;
  273. if( p->prev && p->next )
  274. {
  275. p->prev->next = p->next;
  276. p->next->prev = p->prev;
  277. }
  278. else if ( p->prev )
  279. {
  280. p->prev->next = NULL;
  281. }
  282. else if ( p->next )
  283. {
  284. p->next->prev = NULL;
  285. }
  286. else
  287. {
  288. free( p );
  289. preopened_port = NULL;
  290. return( fd );
  291. }
  292. free( p );
  293. return( fd );
  294. }
  295. if( p->next )
  296. {
  297. p = p->next;
  298. }
  299. else
  300. {
  301. return(0);
  302. }
  303. }
  304. }
  305. /*----------------------------------------------------------
  306. configure_port
  307. accept: env, file descriptor
  308. perform: set the termios struct to sane settings and
  309. return: 0 on success
  310. exceptions: IOExcepiton
  311. comments: Very often people complain about not being able to get past
  312. this function and it turns out to be permissions on the
  313. device file or bios has the device disabled.
  314. ----------------------------------------------------------*/
  315. int configure_port( int fd )
  316. {
  317. struct termios ttyset;
  318. if( fd < 0 ) goto fail;
  319. if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
  320. ttyset.c_iflag = INPCK;
  321. ttyset.c_lflag = 0;
  322. ttyset.c_oflag = 0;
  323. ttyset.c_cflag = CREAD | CS8 | CLOCAL;
  324. ttyset.c_cc[ VMIN ] = 0;
  325. ttyset.c_cc[ VTIME ] = 0;
  326. #ifdef __FreeBSD__
  327. if( cfsetspeed( &ttyset, B9600 ) < 0 ) goto fail;
  328. #else
  329. if( cfsetispeed( &ttyset, B9600 ) < 0 ) goto fail;
  330. if( cfsetospeed( &ttyset, B9600 ) < 0 ) goto fail;
  331. #endif
  332. if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 ) goto fail;
  333. #ifndef WIN32
  334. fcntl( fd, F_SETOWN, getpid() );
  335. #endif /* WIN32 */
  336. #ifdef FASYNC
  337. fcntl( fd, F_SETFL, FASYNC );
  338. #endif /* FASYNC */
  339. return 0;
  340. fail:
  341. return 1;
  342. }
  343. /*----------------------------------------------------------
  344. get_java_baudrate
  345. accept: the native speed setting
  346. perform: translate the native speed to a Java speed
  347. return: the Java speed
  348. exceptions: none
  349. comments: This is used by open() (indirectly) and
  350. nativeStaticGetBaudRate()
  351. ----------------------------------------------------------*/
  352. int get_java_baudrate( int native_speed )
  353. {
  354. switch( native_speed )
  355. {
  356. case B0: return 0;
  357. case B50: return 50;
  358. case B75: return 75;
  359. case B110: return 110;
  360. case B134: return 134;
  361. case B150: return 150;
  362. case B200: return 200;
  363. case B300: return 300;
  364. case B600: return 600;
  365. case B1200: return 1200;
  366. case B1800: return 1800;
  367. case B2400: return 2400;
  368. case B4800: return 4800;
  369. case B9600: return 9600;
  370. case B19200: return 19200;
  371. case B38400: return 38400;
  372. case B57600: return 57600;
  373. default: return -1;
  374. }
  375. }
  376. /*----------------------------------------------------------
  377. set_java_vars
  378. accept: fd of the preopened device
  379. perform: Now that the object is instatiated, set the Java variables
  380. to the preopened states.
  381. return: none
  382. exceptions: none
  383. comments: preopened refers to the fact that the serial port has
  384. been configured before the Java open() has been called.
  385. ----------------------------------------------------------*/
  386. void set_java_vars( gnu::io::RXTXPort *p,
  387. int fd
  388. )
  389. {
  390. struct termios ttyset;
  391. int databits = -1;
  392. int jparity = -1;
  393. int stop_bits = STOPBITS_1_5;
  394. int baudrate;
  395. if( tcgetattr( fd, &ttyset ) < 0 )
  396. {
  397. report( "Cannot Get Serial Port Settings\n" );
  398. return;
  399. }
  400. switch( ttyset.c_cflag&CSIZE ) {
  401. case CS5: databits = JDATABITS_5; break;
  402. case CS6: databits = JDATABITS_6; break;
  403. case CS7: databits = JDATABITS_7; break;
  404. case CS8: databits = JDATABITS_8; break;
  405. }
  406. #ifdef CMSPAR
  407. switch( ttyset.c_cflag&(PARENB|PARODD|CMSPAR ) ) {
  408. #else
  409. switch( ttyset.c_cflag&(PARENB|PARODD) ) {
  410. #endif /* CMSPAR */
  411. case 0: jparity = JPARITY_NONE; break;
  412. case PARENB: jparity = JPARITY_EVEN; break;
  413. case PARENB | PARODD: jparity = JPARITY_ODD; break;
  414. #ifdef CMSPAR
  415. case PARENB | PARODD | CMSPAR: jparity = JPARITY_MARK; break;
  416. case PARENB | CMSPAR: jparity = JPARITY_SPACE; break;
  417. #endif /* CMSPAR */
  418. }
  419. switch( ttyset.c_cflag&(CSTOPB) ) {
  420. case 0: stop_bits = STOPBITS_1; break;
  421. case CSTOPB: stop_bits = STOPBITS_2; break;
  422. }
  423. /*
  424. dima writes:
  425. Trent, here is something I found with google:
  426. (freebsd list freebsd-current@freebsd.org)
  427. Andrzej Bialecki <abial@korin.warman.org.pl> asked:
  428. I tried to compile a piece of software, probably for Linux, and I noticed
  429. that we don't define CBAUD constant. I'm not sure, but I think POSIX
  430. defines and uses it. Should(n't) we?
  431. Bruce Evans <bde@zeta.org.au> answered:
  432. CBAUD is for SYSV compatibility. It is considerably inferior to POSIX's
  433. cf{get,set}{i,o}speed and shouldn't be provided or used.
  434. */
  435. #if defined(CBAUD)/* dima */
  436. baudrate = ttyset.c_cflag&CBAUD;
  437. #else
  438. baudrate = cfgetispeed(&ttyset);
  439. #endif
  440. p->speed = ( jint ) get_java_baudrate(baudrate) ;
  441. p->dataBits = ( jint ) databits ;
  442. p->stopBits = ( jint ) stop_bits ;
  443. p->parity = ( jint ) jparity ;
  444. }
  445. /*----------------------------------------------------------
  446. RXTXPort.open
  447. accept: The device to open. ie "/dev/ttyS0"
  448. perform: open the device, set the termios struct to sane settings and
  449. return the filedescriptor
  450. return: fd
  451. exceptions: IOExcepiton
  452. comments: Very often people complain about not being able to get past
  453. this function and it turns out to be permissions on the
  454. device file or bios has the device disabled.
  455. ----------------------------------------------------------*/
  456. jint gnu::io::RXTXPort::open(
  457. java::lang::String *jstr
  458. )
  459. {
  460. int fd =0, i;
  461. int pid = -1;
  462. char message[80];
  463. report_time_start( );
  464. char filename[80];
  465. for( i=0;i<jstr->length();i++)
  466. filename[i] = jstr->charAt(i);
  467. filename[i] = '\0';
  468. #ifndef WIN32
  469. pid = getpid();
  470. #endif /* WIN32 */
  471. this->pid = pid;
  472. /*
  473. LOCK is one of three functions defined in SerialImp.h
  474. uucp_lock Solaris
  475. fhs_lock Linux
  476. system_does_not_lock Win32
  477. */
  478. ENTER( "RXTXPort:open" );
  479. if ( LOCK( filename, pid ) )
  480. {
  481. sprintf( message, "open: locking has failed for %s\n",
  482. filename );
  483. report( message );
  484. goto fail;
  485. }
  486. else
  487. {
  488. sprintf( message, "open: locking worked for %s\n", filename );
  489. report( message );
  490. }
  491. /* This is used so DTR can remain low on 'open()' */
  492. if( fd )
  493. {
  494. return (jint)fd;
  495. }
  496. do {
  497. fd=::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
  498. } while (fd < 0 && errno==EINTR);
  499. if( configure_port( fd ) ) goto fail;
  500. sprintf( message, "open: fd returned is %i\n", fd );
  501. report( message );
  502. LEAVE( "RXTXPort:open" );
  503. report_time_end( );
  504. return (jint)fd;
  505. fail:
  506. LEAVE( "RXTXPort:open" );
  507. snprintf(message, 79, "%s %s",strerror(errno)," in open");
  508. throw new gnu::io::PortInUseException( JvNewStringUTF( message ) );
  509. //throw new PortInUseException;
  510. return -1;
  511. }
  512. /*----------------------------------------------------------
  513. RXTXPort.nativeClose
  514. accept: none
  515. perform: get the fd from the java end and close it
  516. return: none
  517. exceptions: none
  518. ----------------------------------------------------------*/
  519. void gnu::io::RXTXPort::nativeClose(
  520. java::lang::String *jstr
  521. )
  522. {
  523. int result = -1, i;
  524. char filename[80];
  525. for( i=0;i<jstr->length();i++)
  526. filename[i] = jstr->charAt(i);
  527. filename[i] = '\0';
  528. report_time_start( );
  529. #ifndef WIN32
  530. #endif /* WIN32 */
  531. /*
  532. UNLOCK is one of three functions defined in SerialImp.h
  533. uucp_unlock Solaris
  534. fhs_unlock Linux
  535. system_does_not_unlock Win32
  536. */
  537. ENTER( "RXTXPort:nativeClose" );
  538. if (this->fd > 0)
  539. {
  540. do {
  541. result=::CLOSE (this->fd);
  542. } while ( result < 0 && errno == EINTR );
  543. UNLOCK( filename, this->pid );
  544. }
  545. LEAVE( "RXTXPort:nativeClose" );
  546. report_time_end( );
  547. return;
  548. }
  549. /*----------------------------------------------------------
  550. RXTXPort.set_port_params
  551. accept: env, fd, speed, data bits, stop bits, parity
  552. perform: set the serial port parameters
  553. return: 1 on error
  554. exceptions: UnsupportedCommOperationException
  555. comments: There is a static method and an instance method that use this
  556. function. The static method gets a fd first. The instance
  557. method can get the fd from the object.
  558. see: nativeSetSerialPortParams & nativeStaticSerialPortParams
  559. ----------------------------------------------------------*/
  560. int set_port_params(
  561. int fd,
  562. int cspeed,
  563. int dataBits,
  564. int stopBits,
  565. int parity
  566. )
  567. {
  568. struct termios ttyset;
  569. int result = 0;
  570. #if defined(TIOCGSERIAL)
  571. struct serial_struct sstruct;
  572. #endif /* TIOCGSERIAL */
  573. if( tcgetattr( fd, &ttyset ) < 0 )
  574. {
  575. report( "set_port_params: Cannot Get Serial Port Settings\n" );
  576. return(1);
  577. }
  578. if( translate_data_bits( &(ttyset.c_cflag), dataBits ) )
  579. {
  580. report( "set_port_params: Invalid Data Bits Selected\n" );
  581. return(1);
  582. }
  583. if( translate_stop_bits( &(ttyset.c_cflag), stopBits ) )
  584. {
  585. report( "set_port_params: Invalid Stop Bits Selected\n" );
  586. return(1);
  587. }
  588. if( translate_parity( &(ttyset.c_cflag), parity ) )
  589. {
  590. report( "set_port_params: Invalid Parity Selected\n" );
  591. return(1);
  592. }
  593. #ifdef __FreeBSD__
  594. if( cfsetspeed( &ttyset, cspeed ) < 0 )
  595. {
  596. report( "set_port_params: Cannot Set Speed\n" );
  597. return( 1 );
  598. }
  599. #endif /* __FreeBSD__ */
  600. if( !cspeed )
  601. {
  602. /* hang up the modem aka drop DTR */
  603. /* Unix should handle this */
  604. /*
  605. mexPrintf("dropping DTR\n");
  606. printf("dropping DTR\n");
  607. */
  608. ioctl( fd, TIOCMGET, &result );
  609. result &= ~TIOCM_DTR;
  610. ioctl( fd, TIOCMSET, &result );
  611. }
  612. if( cfsetispeed( &ttyset, cspeed ) < 0 ||
  613. cfsetospeed( &ttyset, cspeed ) < 0 )
  614. {
  615. /*
  616. Some people need to set the baud rate to ones not defined
  617. in termios.h
  618. This includes some baud rates which are supported by CommAPI
  619. in Unix ( 14400, 28800, 128000, 256000 )
  620. If the above fails, we assume this is not a defined
  621. baud rate on Unix. With Win32, It is assumed the kernel
  622. will do this for us.
  623. The baud_base and desired speed are used to
  624. calculate a custom divisor.
  625. On linux the setserial man page covers this.
  626. */
  627. #if defined(TIOCGSERIAL)
  628. sstruct.custom_divisor = ( sstruct.baud_base/cspeed );
  629. cspeed = B38400;
  630. #endif /* TIOCGSERIAL */
  631. if( cfsetispeed( &ttyset, cspeed ) < 0 ||
  632. cfsetospeed( &ttyset, cspeed ) < 0 )
  633. {
  634. /* OK, we tried everything */
  635. report( "nativeSetSerialPortParams: Cannot Set Speed\n" );
  636. return( 1 );
  637. }
  638. #if defined(TIOCSSERIAL)
  639. /* It is assumed Win32 does this for us */
  640. if ( sstruct.baud_base < 1 ||
  641. ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
  642. {
  643. return( 1 );
  644. }
  645. #endif /* TIOCSSERIAL */
  646. }
  647. if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 )
  648. {
  649. report("tcsetattr returns nonzero value!\n");
  650. return( 1 );
  651. }
  652. return(0);
  653. }
  654. /*----------------------------------------------------------
  655. RXTXPort.nativeSetSerialPortParams
  656. accept: speed, data bits, stop bits, parity
  657. perform: set the serial port parameters
  658. return: jboolean 1 on error
  659. exceptions: UnsupportedCommOperationException
  660. ----------------------------------------------------------*/
  661. jboolean gnu::io::RXTXPort::nativeSetSerialPortParams(
  662. jint speed,
  663. jint dataBits,
  664. jint stopBits,
  665. jint parity
  666. )
  667. {
  668. int fd = (int) this->fd;
  669. int cspeed = translate_speed( speed );
  670. ENTER( "RXTXPort:nativeSetSerialPortParams" );
  671. report_time_start( );
  672. if (cspeed < 0 )
  673. {
  674. report(" invalid cspeed\n");
  675. /*
  676. For some reason the native exceptions are not being caught. Moving this
  677. to the Java side fixed the issue. taj.
  678. throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
  679. "", "BaudRate could not be set to the specified value" );
  680. */
  681. return(1);
  682. }
  683. if( set_port_params( fd, cspeed, dataBits, stopBits, parity ) )
  684. {
  685. report("set_port_params failed\n");
  686. LEAVE( "RXTXPort:nativeSetSerialPortParams" );
  687. /*
  688. For some reason the native exceptions are not being caught. Moving this
  689. to the Java side fixed the issue. taj.
  690. throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
  691. "nativeSetSerialPortParams", strerror( errno ) );
  692. */
  693. return(1);
  694. }
  695. LEAVE( "RXTXPort:nativeSetSerialPortParams" );
  696. report_time_end( );
  697. return(0);
  698. }
  699. /*----------------------------------------------------------
  700. translate_speed
  701. accept: speed in bits-per-second
  702. perform: convert bits-per-second to a speed_t constant
  703. return: speed_t constant
  704. exceptions: returns -1 and the calling method throws the exception so
  705. it may be caught in java.
  706. comments: Only the lowest level code should know about
  707. the magic constants.
  708. ----------------------------------------------------------*/
  709. int translate_speed(
  710. jint speed
  711. )
  712. {
  713. LEAVE( "RXTXPort:translate_speed" );
  714. switch( speed ) {
  715. case 0: return B0;
  716. case 50: return B50;
  717. case 75: return B75;
  718. case 110: return B110;
  719. case 134: return B134;
  720. case 150: return B150;
  721. case 200: return B200;
  722. case 300: return B300;
  723. case 600: return B600;
  724. case 1200: return B1200;
  725. case 1800: return B1800;
  726. case 2400: return B2400;
  727. case 4800: return B4800;
  728. case 9600: return B9600;
  729. case 19200: return B19200;
  730. case 38400: return B38400;
  731. #ifdef B57600
  732. case 57600: return B57600;
  733. #endif /* B57600 */
  734. #ifdef B115200
  735. case 115200: return B115200;
  736. #endif /* B115200 */
  737. #ifdef B230400
  738. case 230400: return B230400;
  739. #endif /* B230400 */
  740. #ifdef B460800
  741. case 460800: return B460800;
  742. #endif /* B460800 */
  743. #ifdef B14400
  744. case 14400: return B14400;
  745. #endif /* B14400 */
  746. #ifdef B28800
  747. case 28800: return B28800;
  748. #endif /* B28800 */
  749. #ifdef B128000 /* dima */
  750. case 128000: return B128000;
  751. #endif /* dima */
  752. #ifdef B256000 /* dima */
  753. case 256000: return B256000;
  754. #endif /* dima */
  755. }
  756. /* Handle custom speeds */
  757. if( speed >= 0 ) return speed;
  758. else
  759. {
  760. LEAVE( "RXTXPort:translate_speed: Error condition" );
  761. return -1;
  762. }
  763. }
  764. /*----------------------------------------------------------
  765. translate_data_bits
  766. accept: gnu.io.SerialPort.DATABITS_* constant
  767. perform: set proper termios c_cflag bits
  768. return: 1 on error
  769. exceptions: UnsupportedCommOperationException
  770. ----------------------------------------------------------*/
  771. int translate_data_bits(
  772. tcflag_t *cflag,
  773. jint dataBits
  774. )
  775. {
  776. int temp = (*cflag) & ~CSIZE;
  777. ENTER( "translate_date_bits" );
  778. switch( dataBits ) {
  779. case JDATABITS_5:
  780. (*cflag) = temp | CS5;
  781. return 0;
  782. case JDATABITS_6:
  783. (*cflag) = temp | CS6;
  784. return 0;
  785. case JDATABITS_7:
  786. (*cflag) = temp | CS7;
  787. return 0;
  788. case JDATABITS_8:
  789. (*cflag) = temp | CS8;
  790. return 0;
  791. }
  792. LEAVE( "RXTXPort:translate_date_bits" );
  793. /*
  794. For some reason the native exceptions are not being caught. Moving this
  795. to the Java side fixed the issue. taj.
  796. throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
  797. "", "databit value not supported" );
  798. */
  799. return 1;
  800. }
  801. /*----------------------------------------------------------
  802. translate_stop_bits
  803. accept: gnu.io.SerialPort.STOPBITS_* constant
  804. perform: set proper termios c_cflag bits
  805. return: 1 on error
  806. exceptions: UnsupportedCommOperationException
  807. comments: If you specify 5 data bits and 2 stop bits, the port will
  808. allegedly use 1.5 stop bits. Does anyone care?
  809. ----------------------------------------------------------*/
  810. int translate_stop_bits(
  811. tcflag_t *cflag,
  812. jint stopBits
  813. )
  814. {
  815. ENTER( "translate_stop_bits" );
  816. switch( stopBits ) {
  817. case STOPBITS_1:
  818. (*cflag) &= ~CSTOPB;
  819. LEAVE( "RXTXPort:translate_stop_bits" );
  820. return 0;
  821. /* ok.. lets try putting it in and see if anyone notices */
  822. case STOPBITS_1_5:
  823. if ( translate_data_bits( cflag, JDATABITS_5 ) )
  824. return( 1 );
  825. return 0;
  826. case STOPBITS_2:
  827. (*cflag) |= CSTOPB;
  828. LEAVE( "RXTXPort:translate_stop_bits" );
  829. return 0;
  830. }
  831. LEAVE( "RXTXPort:translate_stop_bits" );
  832. /*
  833. For some reason the native exceptions are not being caught. Moving this
  834. to the Java side fixed the issue. taj.
  835. throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
  836. "", "stopbit value not supported" );
  837. */
  838. return 1;
  839. }
  840. jint gnu::io::RXTXPort::nativeGetFlowControlMode(
  841. jint fd
  842. )
  843. {
  844. struct termios ttyset;
  845. int ret = 0;
  846. tcgetattr( fd, &ttyset );
  847. if( ttyset.c_cflag & HARDWARE_FLOW_CONTROL )
  848. {
  849. ret |= ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT );
  850. }
  851. if ( ttyset.c_iflag & IXOFF )
  852. {
  853. ret |= FLOWCONTROL_XONXOFF_IN;
  854. }
  855. if ( ttyset.c_iflag & IXON )
  856. {
  857. ret |= FLOWCONTROL_XONXOFF_OUT;
  858. }
  859. return( (jint) ret );
  860. }
  861. jint gnu::io::RXTXPort::nativeGetParity(
  862. jint fd
  863. )
  864. {
  865. struct termios ttyset;
  866. if( tcgetattr( fd, &ttyset ) < 0 )
  867. {
  868. report("nativeGetParity: tcgetattr failed\n");
  869. return( -1 );
  870. }
  871. #ifdef CMSPAR
  872. if ( ( ttyset.c_cflag & PARENB ) &&
  873. ( ttyset.c_cflag & PARODD ) &&
  874. ( ttyset.c_cflag & CMSPAR ) )
  875. {
  876. return( JPARITY_MARK );
  877. }
  878. else if ( ttyset.c_cflag & ( PARENB &&
  879. ttyset.c_cflag & CMSPAR ) )
  880. {
  881. return( JPARITY_SPACE );
  882. }
  883. #endif /* CMSPAR */
  884. if ( ttyset.c_cflag & PARENB &&
  885. ttyset.c_cflag & PARODD )
  886. {
  887. return( JPARITY_ODD );
  888. }
  889. else if ( ttyset.c_cflag & PARENB )
  890. {
  891. return( JPARITY_EVEN );
  892. }
  893. else
  894. {
  895. return( JPARITY_NONE );
  896. }
  897. }
  898. /*----------------------------------------------------------
  899. translate_parity
  900. accept: javax.comm.SerialPort.PARITY_* constant
  901. perform: set proper termios c_cflag bits
  902. return: 1 on error
  903. exceptions: UnsupportedCommOperationException
  904. comments: The CMSPAR bit should be used for 'mark' and 'space' parity,
  905. but it's not in glibc's includes. Oh well, rarely used anyway.
  906. ----------------------------------------------------------*/
  907. int translate_parity(
  908. tcflag_t *cflag,
  909. jint parity
  910. )
  911. {
  912. ENTER( "translate_parity" );
  913. #ifdef CMSPAR
  914. (*cflag) &= ~(PARENB | PARODD | CMSPAR );
  915. #endif /* CMSPAR */
  916. switch( parity ) {
  917. case JPARITY_NONE:
  918. LEAVE( "translate_parity" );
  919. return 0;
  920. case JPARITY_EVEN:
  921. (*cflag) |= PARENB;
  922. LEAVE( "translate_parity" );
  923. return 0;
  924. case JPARITY_ODD:
  925. (*cflag) |= PARENB | PARODD;
  926. LEAVE( "translate_parity" );
  927. return 0;
  928. #ifdef CMSPAR
  929. case JPARITY_MARK:
  930. (*cflag) |= PARENB | PARODD | CMSPAR;
  931. LEAVE( "translate_parity" );
  932. return 0;
  933. case JPARITY_SPACE:
  934. (*cflag) |= PARENB | CMSPAR;
  935. LEAVE( "translate_parity" );
  936. return 0;
  937. #endif /* CMSPAR */
  938. default:
  939. printf("Parity missed %i\n", (int) parity );
  940. }
  941. LEAVE( "translate_parity" );
  942. /*
  943. For some reason the native exceptions are not being caught. Moving this
  944. to the Java side fixed the issue. taj.
  945. throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
  946. "", "parity value not supported" );
  947. */
  948. return 1;
  949. }
  950. #if !defined(TIOCSERGETLSR) && !defined(WIN32)
  951. /*----------------------------------------------------------
  952. drain_loop()
  953. accept:
  954. perform: call tcdrain() and report an event when it succeds
  955. return: none
  956. exceptions:
  957. comments:
  958. ----------------------------------------------------------*/
  959. void *drain_loop( void *arg )
  960. {
  961. struct event_info_struct *eis = ( struct event_info_struct * ) arg;
  962. /* char msg[80]; */
  963. int i;
  964. pthread_detach( pthread_self() );
  965. for(i=0;;i++)
  966. {
  967. report_verbose("drain_loop: looping\n");
  968. #if defined(__sun__)
  969. /* FIXME: No time to test on all OS's for production */
  970. usleep(5000);
  971. #else
  972. usleep(1000000);
  973. #endif /* __sun__ */
  974. /*
  975. system_wait();
  976. */
  977. if( eis->eventloop_interrupted )
  978. {
  979. goto end;
  980. }
  981. if( tcdrain( eis->fd ) == 0 )
  982. {
  983. if( eis && eis->writing )
  984. {
  985. /*
  986. sprintf(msg, "drain_loop: setting OUTPUT_BUFFER_EMPTY\n" );
  987. report( msg );
  988. */
  989. eis->output_buffer_empty_flag = 1;
  990. eis->writing=false;
  991. }
  992. else
  993. {
  994. if( !eis )
  995. {
  996. goto end;
  997. }
  998. report_verbose("drain_loop: writing not set\n");
  999. }
  1000. }
  1001. else
  1002. {
  1003. report("drain_loop: tcdrain bad fd\n");
  1004. goto end;
  1005. }
  1006. }
  1007. end:
  1008. report("------------------ drain_loop exiting ---------------------\n");
  1009. eis->closing = 1;
  1010. pthread_exit( NULL );
  1011. return( NULL );
  1012. }
  1013. #endif /* !defined(TIOCSERGETLSR) && !defined(WIN32) */
  1014. /*----------------------------------------------------------
  1015. finalize_threads( )
  1016. accept: event_info_struct used to access java and communicate with
  1017. eventLoop().
  1018. perform: see comments
  1019. return: none
  1020. exceptions: none
  1021. comments:
  1022. The is the pthread spawned on systems that can't access the
  1023. LSR (Line Status Register). Without access to the LSR rxtx
  1024. cannot detect when the output buffer is empty in the Monitor
  1025. Thread. The solution is to return the value of write's return
  1026. but hang around in this thread waiting for tcdrain to finish.
  1027. once the drain has finished, we let the eventLoop know that the
  1028. output buffer is empty and the Signal is sent.
  1029. ----------------------------------------------------------*/
  1030. void finalize_threads( struct event_info_struct *eis )
  1031. {
  1032. #if !defined(TIOCSERGETLSR) && !defined( WIN32 )
  1033. /* used to shut down any remaining write threads */
  1034. eis->output_buffer_empty_flag = 0;
  1035. ENTER("finalize_threads\n");
  1036. /* need to clean up again after working events */
  1037. LEAVE("---------------- finalize_threads ---------------");
  1038. #endif /* TIOCSERGETLSR & !WIN32 */
  1039. }
  1040. #if !defined(TIOCSERGETLSR) && !defined( WIN32 )
  1041. static void warn_sig_abort( int signo )
  1042. {
  1043. char msg[80];
  1044. sprintf( msg, "RXTX Recieved Signal %i\n", signo );
  1045. /*
  1046. report_error( msg );
  1047. */
  1048. }
  1049. #endif /* TIOCSERGETLSR */
  1050. /*----------------------------------------------------------
  1051. init_threads( )
  1052. accept: none
  1053. perform:
  1054. return: none
  1055. exceptions: none
  1056. comments:
  1057. ----------------------------------------------------------*/
  1058. int init_threads( gnu::io::RXTXPort *p, struct event_info_struct *eis )
  1059. {
  1060. #if !defined(TIOCSERGETLSR) & !defined(WIN32)
  1061. sigset_t newmask, oldmask;
  1062. struct sigaction newaction, oldaction;
  1063. pthread_t tid;
  1064. report_time_start( );
  1065. report("init_threads: start\n");
  1066. sigemptyset(&newmask);
  1067. sigaddset(&newmask, SIGCHLD);
  1068. newaction.sa_handler = warn_sig_abort;
  1069. sigemptyset( &newaction.sa_mask );
  1070. #ifdef SA_INTERRUPT
  1071. newaction.sa_flags = SA_INTERRUPT;
  1072. #endif /* SA_INTERRUPT */
  1073. #ifdef SA_RESTART
  1074. newaction.sa_flags = SA_RESTART;
  1075. #endif /* SA_RESTART */
  1076. sigaction(SIGABRT, &newaction, &oldaction);
  1077. sigaction(SIGCHLD, &newaction, &oldaction);
  1078. sigaction(SIGALRM, &newaction, &oldaction);
  1079. sigaction(SIGCONT, &newaction, &oldaction);
  1080. /*
  1081. sigaction(SIGPOLL, &newaction, &oldaction);
  1082. sigaction(SIGTRAP, &newaction, &oldaction);
  1083. sigaction(SIGBUS, &newaction, &oldaction);
  1084. sigaction(SIGSEGV, &newaction, &oldaction);
  1085. sigaction(SIGFPE, &newaction, &oldaction);
  1086. sigaction(SIGILL, &newaction, &oldaction);
  1087. sigfillset(&newmask);
  1088. sigprocmask( SIG_SETMASK, &newmask, &oldmask );
  1089. pthread_sigmask( SIG_BLOCK, &newmask, &oldmask );
  1090. */
  1091. sigprocmask( SIG_SETMASK, &newmask, &oldmask );
  1092. report("init_threads: creating drain_loop\n");
  1093. pthread_create( &tid, NULL, drain_loop, (void *) eis );
  1094. pthread_detach( tid );
  1095. #endif /* TIOCSERGETLSR */
  1096. report("init_threads: set eis\n");
  1097. p->eis = ( jint ) eis;
  1098. report("init_threads: stop\n");
  1099. report_time_end( );
  1100. return( 1 );
  1101. }
  1102. /*----------------------------------------------------------
  1103. RXTXPort.writeByte
  1104. accept: byte to write (passed as int)
  1105. jboolean interrupted (no events if true)
  1106. perform: write a single byte to the port
  1107. return: none
  1108. exceptions: IOException
  1109. ----------------------------------------------------------*/
  1110. void gnu::io::RXTXPort::writeByte(
  1111. jint ji,
  1112. jboolean interrupted
  1113. )
  1114. {
  1115. #ifndef TIOCSERGETLSR
  1116. struct event_info_struct *index = master_index;
  1117. #endif
  1118. unsigned char byte = (unsigned char)ji;
  1119. int fd = ( int ) this->fd;
  1120. int result;
  1121. char msg[80];
  1122. #if defined ( __sun__ )
  1123. int count;
  1124. #endif /* __sun__ */
  1125. report_time_start();
  1126. ENTER( "RXTXPort:writeByte" );
  1127. do {
  1128. sprintf( msg, "writeByte %c>>\n", byte );
  1129. report( msg );
  1130. result=WRITE (fd, (void * ) &byte, sizeof(unsigned char));
  1131. } while (result < 0 && errno==EINTR);
  1132. if ( result < 0 && errno != EINTR )
  1133. {
  1134. snprintf( msg, 79, "%s%s", strerror( errno ), " in writeByte" );
  1135. throw new java::io::IOException( JvNewStringUTF( msg ) );
  1136. /* On win32 I'm not sure how many bytes made it out */
  1137. return;
  1138. }
  1139. /*
  1140. This makes write for win32, glinux and Sol behave the same
  1141. #if defined ( __sun__ )
  1142. do {
  1143. report_verbose( "nativeDrain: trying tcdrain\n" );
  1144. result=tcdrain(fd);
  1145. count++;
  1146. } while (result && errno==EINTR && count <3);
  1147. #endif *//* __sun __ */
  1148. #ifndef TIOCSERGETLSR
  1149. if( ! interrupted )
  1150. {
  1151. index = master_index;
  1152. if( index )
  1153. {
  1154. while( index->fd != fd &&
  1155. index->next ) index = index->next;
  1156. }
  1157. index->writing = 1;
  1158. report( "writeByte: index->writing = 1" );
  1159. }
  1160. #endif
  1161. sprintf( msg, "RXTXPort:writeByte %i\n", result );
  1162. report( msg );
  1163. LEAVE( "RXTXPort:writeByte" );
  1164. if(result >= 0)
  1165. {
  1166. report_time_end();
  1167. return;
  1168. }
  1169. snprintf( msg, 79, "%s%s", strerror( errno ), " in writeByte" );
  1170. throw new java::io::IOException( JvNewStringUTF( msg ) );
  1171. }
  1172. /*----------------------------------------------------------
  1173. RXTXPort.writeArray
  1174. accept: jbarray: bytes used for writing
  1175. offset: offset in array to start writing
  1176. count: Number of bytes to write
  1177. jboolean interrupted (no events if true)
  1178. perform: write length bytes of jbarray
  1179. return: none
  1180. exceptions: IOException
  1181. ----------------------------------------------------------*/
  1182. void gnu::io::RXTXPort::writeArray(
  1183. jbyteArray jbarray,
  1184. jint offset,
  1185. jint count,
  1186. jboolean interrupted
  1187. )
  1188. {
  1189. #ifndef TIOCSERGETLSR
  1190. struct event_info_struct *index = master_index;
  1191. #endif /* TIOCSERGETLSR */
  1192. int fd;
  1193. int result=0,total=0;
  1194. jbyte *out = elements( jbarray );
  1195. char msg[80];
  1196. #if defined ( __sun__ )
  1197. int icount;
  1198. #endif /* __sun__ */
  1199. #if defined ( __sun__ )
  1200. struct timespec retspec;
  1201. retspec.tv_sec = 0;
  1202. retspec.tv_nsec = 50000;
  1203. #endif /* __sun__ */
  1204. fd = ( int ) this->fd;
  1205. report_time_start();
  1206. ENTER( "writeArray" );
  1207. /* warning Roy Rogers */
  1208. /*
  1209. sprintf( message, "::::RXTXPort:writeArray(%s);\n", (char *) body );
  1210. report_verbose( message );
  1211. */
  1212. do {
  1213. result=WRITE (fd, (void * ) ((char *) out + total + offset), count - total); /* dima */
  1214. if(result >0){
  1215. total += result;
  1216. }
  1217. report("writeArray()\n");
  1218. } while ( ( total < count ) && ( (result < 0 && errno==EINTR ) || ( result >= 0 ) ) ) ;
  1219. if ( result < 0 && errno != EINTR )
  1220. {
  1221. snprintf( msg, 79, "%s%s", strerror( errno ), " in writeArray" );
  1222. throw new java::io::IOException( JvNewStringUTF( msg ) );
  1223. /* On win32 I'm not sure how many bytes made it out */
  1224. return;
  1225. }
  1226. /*
  1227. This makes write for win32, glinux and Sol behave the same
  1228. #if defined ( __sun__ )
  1229. do {
  1230. report_verbose( "nativeDrain: trying tcdrain\n" );
  1231. result=tcdrain(fd);
  1232. icount++;
  1233. } while (result && errno==EINTR && icount <3);
  1234. #endif *//* __sun__ */
  1235. #ifndef TIOCSERGETLSR
  1236. if( !interrupted )
  1237. {
  1238. if( index )
  1239. {
  1240. while( index->fd != fd &&
  1241. index->next ) index = index->next;
  1242. }
  1243. index->writing = 1;
  1244. report( "writeArray: index->writing = 1" );
  1245. }
  1246. #endif /* TIOCSERGETLSR */
  1247. /*
  1248. 50 ms sleep to make sure read can get in
  1249. what I think is happening here is the data writen is causing
  1250. signals, the event loop can't select with data available
  1251. I think things like BlackBox with 2 ports open are getting
  1252. signals for both the reciever and transmitter since they
  1253. are the same PID.
  1254. Things just start spinning out of control after that.
  1255. */
  1256. LEAVE( "RXTXPort:writeArray" );
  1257. report_time_end();
  1258. return;
  1259. fail:
  1260. snprintf( msg, 79, "%s%s", strerror( errno ), " in writeArray" );
  1261. throw new java::io::IOException( JvNewStringUTF( msg ) );
  1262. }
  1263. /*----------------------------------------------------------
  1264. RXTXPort.nativeDrain
  1265. accept: jboolean interrupted (no events if true)
  1266. perform: wait until all data is transmitted
  1267. return: none
  1268. exceptions: IOException
  1269. comments: java.io.OutputStream.flush() is equivalent to tcdrain,
  1270. not tcflush, which throws away unsent bytes
  1271. count logic added to avoid infinite loops when EINTR is
  1272. true... Thread.yeild() was suggested.
  1273. ----------------------------------------------------------*/
  1274. jboolean gnu::io::RXTXPort::nativeDrain(
  1275. jboolean interrupted
  1276. )
  1277. {
  1278. int fd = ( int ) this->fd;
  1279. struct event_info_struct *eis = ( struct event_info_struct * ) this->eis;
  1280. int result, count=0;
  1281. char message[80];
  1282. ENTER( "SerialImp.c:drain()" );
  1283. report_time_start( );
  1284. do {
  1285. report_verbose( "nativeDrain: trying tcdrain\n" );
  1286. result=tcdrain(fd);
  1287. count++;
  1288. } while (result && errno==EINTR && count <3);
  1289. sprintf( message, "RXTXPort:drain() returns: %i\n", result );
  1290. report_verbose( message );
  1291. #if defined(__sun__)
  1292. /* FIXME: No time to test on all OS's for production */
  1293. return( true );
  1294. #endif /* __sun__ */
  1295. LEAVE( "RXTXPort:drain()" );
  1296. if( result )
  1297. {
  1298. snprintf( message, 79, "%s%s", strerror( errno ), " in nativeDrain" );
  1299. throw new java::io::IOException( JvNewStringUTF( message ) );
  1300. }
  1301. if( interrupted ) return( false );
  1302. #if !defined(TIOCSERGETLSR) && !defined(WIN32)
  1303. if( eis && eis->writing )
  1304. {
  1305. eis->writing=false;
  1306. eis->output_buffer_empty_flag = 0;
  1307. }
  1308. #endif /* !TIOCSERGETLSR !WIN32 */
  1309. if( eis && eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
  1310. {
  1311. send_event( this, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
  1312. }
  1313. report_time_end( );
  1314. return( false );
  1315. }
  1316. /*----------------------------------------------------------
  1317. RXTXPort.sendBreak
  1318. accept: duration in milliseconds.
  1319. perform: send break for actual time. not less than 0.25 seconds.
  1320. exceptions: none
  1321. comments: not very precise
  1322. ----------------------------------------------------------*/
  1323. void gnu::io::RXTXPort::sendBreak(
  1324. jint duration
  1325. )
  1326. {
  1327. int fd = ( int ) this->fd;
  1328. report_time_start( );
  1329. ENTER( "RXTXPort:sendBreak()" );
  1330. tcsendbreak( fd, (int)( duration / 250 ) );
  1331. report_time_end( );
  1332. LEAVE( "RXTXPort:sendBreak()" );
  1333. }
  1334. /*----------------------------------------------------------
  1335. RXTXPort.NativegetReceiveTimeout
  1336. accept: none
  1337. perform: get termios.c_cc[VTIME]
  1338. return: VTIME
  1339. comments: see NativeEnableReceiveTimeoutThreshold
  1340. ----------------------------------------------------------*/
  1341. jint gnu::io::RXTXPort::NativegetReceiveTimeout(
  1342. )
  1343. {
  1344. int fd = this->fd;
  1345. struct termios ttyset;
  1346. char msg[80];
  1347. ENTER( "RXTXPort:nativegetRecieveTimeout()" );
  1348. if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
  1349. LEAVE( "RXTXPort:nativegetRecieveTimeout()" );
  1350. return(ttyset.c_cc[ VTIME ] * 100);
  1351. fail:
  1352. LEAVE( "RXTXPort:nativegetRecieveTimeout()" );
  1353. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeGetRecieveTimeout()" );
  1354. throw new java::io::IOException( JvNewStringUTF( msg ) );
  1355. return -1;
  1356. }
  1357. /*----------------------------------------------------------
  1358. RXTXPort.NativeisReceiveTimeoutEnabled
  1359. accept: none
  1360. perform: determine if VTIME is none 0
  1361. return: true if VTIME > 0 else false
  1362. comments: see NativeEnableReceiveTimeoutThreshold
  1363. ----------------------------------------------------------*/
  1364. jboolean gnu::io::RXTXPort::NativeisReceiveTimeoutEnabled(
  1365. )
  1366. {
  1367. int fd = this->fd;
  1368. struct termios ttyset;
  1369. char msg[80];
  1370. ENTER( "RXTXPort:NativeisRecieveTimeoutEnabled()" );
  1371. if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
  1372. LEAVE( "RXTXPort:NativeisRecieveTimeoutEnabled()" );
  1373. return(ttyset.c_cc[ VTIME ] > 0 ? true:false);
  1374. fail:
  1375. LEAVE( "RXTXPort:NativeisRecieveTimeoutEnabled()" );
  1376. snprintf( msg, 79, "%s%s", strerror( errno ), " in isRecieveTimeoutEnabled()" );
  1377. throw new java::io::IOException( JvNewStringUTF( msg ) );
  1378. return false;
  1379. }
  1380. /*----------------------------------------------------------
  1381. RXTXPort.isDSR
  1382. accept: none
  1383. perform: check status of DSR
  1384. return: true if TIOCM_DSR is set
  1385. false if TIOCM_DSR is not set
  1386. exceptions: none
  1387. comments: DSR stands for Data Set Ready
  1388. ----------------------------------------------------------*/
  1389. jboolean gnu::io::RXTXPort::isDSR(
  1390. )
  1391. {
  1392. unsigned int result = 0;
  1393. int fd = this->fd;
  1394. char message[80];
  1395. ENTER( "RXTXPort:isDSR" );
  1396. ioctl( fd, TIOCMGET, &result );
  1397. sprintf( message, "RXTXPort:isDSR returns %i\n", result & TIOCM_DSR );
  1398. report( message );
  1399. LEAVE( "RXTXPort:isDSR" );
  1400. if( result & TIOCM_DSR ) return true;
  1401. else return false;
  1402. }
  1403. /*----------------------------------------------------------
  1404. RXTXPort.isCD
  1405. accept: none
  1406. perform: check status of CD
  1407. return: true if TIOCM_CD is set
  1408. false if TIOCM_CD is not set
  1409. exceptions: none
  1410. comments: CD stands for Carrier Detect
  1411. The following comment has been made...
  1412. "well, it works, there might ofcourse be a bug, but making DCD
  1413. permanently on fixed it for me so I don't care"
  1414. ----------------------------------------------------------*/
  1415. jboolean gnu::io::RXTXPort::isCD(
  1416. )
  1417. {
  1418. unsigned int result = 0;
  1419. int fd = ( int ) this->fd;
  1420. char message[80];
  1421. ENTER( "RXTXPort:isCD" );
  1422. ioctl( fd, TIOCMGET, &result );
  1423. sprintf( message, "RXTXPort:isCD returns %i\n", result & TIOCM_CD );
  1424. LEAVE( "RXTXPort:isCD" );
  1425. if( result & TIOCM_CD ) return true;
  1426. else return false;
  1427. }
  1428. /*----------------------------------------------------------
  1429. RXTXPort.isCTS
  1430. accept: none
  1431. perform: check status of CTS
  1432. return: true if TIOCM_CTS is set
  1433. false if TIOCM_CTS is not set
  1434. exceptions: none
  1435. comments: CTS stands for Clear To Send.
  1436. ----------------------------------------------------------*/
  1437. jboolean gnu::io::RXTXPort::isCTS(
  1438. )
  1439. {
  1440. unsigned int result = 0;
  1441. int fd = ( int ) this->fd;
  1442. char message[80];
  1443. ENTER( "RXTXPort:isCTS" );
  1444. ioctl( fd, TIOCMGET, &result );
  1445. sprintf( message, "RXTXPort:isCTS returns %i\n", result & TIOCM_CTS );
  1446. report( message );
  1447. LEAVE( "RXTXPort:isCTS" );
  1448. if( result & TIOCM_CTS ) return true;
  1449. else return false;
  1450. }
  1451. /*----------------------------------------------------------
  1452. RXTXPort.isRI
  1453. accept: none
  1454. perform: check status of RI
  1455. return: true if TIOCM_RI is set
  1456. false if TIOCM_RI is not set
  1457. exceptions: none
  1458. comments: RI stands for Ring Indicator
  1459. ----------------------------------------------------------*/
  1460. jboolean gnu::io::RXTXPort::isRI(
  1461. )
  1462. {
  1463. unsigned int result = 0;
  1464. int fd = ( int ) this->fd;
  1465. char message[80];
  1466. ENTER( "RXTXPort:isRI" );
  1467. ioctl( fd, TIOCMGET, &result );
  1468. sprintf( message, "RXTXPort:isRI returns %i\n", result & TIOCM_RI );
  1469. report( message );
  1470. LEAVE( "RXTXPort:isRI" );
  1471. if( result & TIOCM_RI ) return true;
  1472. else return false;
  1473. }
  1474. /*----------------------------------------------------------
  1475. RXTXPort.isRTS
  1476. accept: none
  1477. perform: check status of RTS
  1478. return: true if TIOCM_RTS is set
  1479. false if TIOCM_RTS is not set
  1480. exceptions: none
  1481. comments: tcgetattr with c_cflag CRTS_IFLOW
  1482. ----------------------------------------------------------*/
  1483. jboolean gnu::io::RXTXPort::isRTS(
  1484. )
  1485. {
  1486. unsigned int result = 0;
  1487. int fd = ( int ) this->fd;
  1488. char message[80];
  1489. ENTER( "RXTXPort:isRTS" );
  1490. ioctl( fd, TIOCMGET, &result );
  1491. sprintf( message, "RXTXPort:isRTS returns %i\n", result & TIOCM_RTS );
  1492. report( message );
  1493. LEAVE( "RXTXPort:isRTS" );
  1494. if( result & TIOCM_RTS ) return true;
  1495. else return false;
  1496. }
  1497. /*----------------------------------------------------------
  1498. RXTXPort.setRTS
  1499. accept: state flag to set/unset.
  1500. perform: depends on the state flag
  1501. if true TIOCM_RTS is set
  1502. if false TIOCM_RTS is unset
  1503. return: none
  1504. exceptions: none
  1505. comments: tcsetattr with c_cflag CRTS_IFLOW
  1506. ----------------------------------------------------------*/
  1507. void gnu::io::RXTXPort::setRTS(
  1508. jboolean state
  1509. )
  1510. {
  1511. unsigned int result = 0;
  1512. int fd = ( int ) this->fd;
  1513. char message[80];
  1514. ENTER( "RXTXPort:setRTS" );
  1515. ioctl( fd, TIOCMGET, &result );
  1516. if( state == true ) result |= TIOCM_RTS;
  1517. else result &= ~TIOCM_RTS;
  1518. ioctl( fd, TIOCMSET, &result );
  1519. sprintf( message, "setRTS( %i )\n", state );
  1520. report( message );
  1521. LEAVE( "RXTXPort:setRTS" );
  1522. return;
  1523. }
  1524. /*----------------------------------------------------------
  1525. RXTXPort.setDSR
  1526. accept: state flag to set/unset.
  1527. perform: depends on the state flag
  1528. if true TIOCM_DSR is set
  1529. if false TIOCM_DSR is unset
  1530. return: none
  1531. exceptions: none
  1532. comments: tcsetattr with c_cflag CRTS_IFLOW
  1533. ----------------------------------------------------------*/
  1534. void gnu::io::RXTXPort::setDSR(
  1535. jboolean state
  1536. )
  1537. {
  1538. unsigned int result = 0;
  1539. int fd = ( int ) this->fd;
  1540. char message[80];
  1541. ENTER( "RXTXPort:setDSR()" );
  1542. ioctl( fd, TIOCMGET, &result );
  1543. sprintf( message, "setDSR( %i )\n", state );
  1544. if( state == true ) result |= TIOCM_DSR;
  1545. else result &= ~TIOCM_DSR;
  1546. ioctl( fd, TIOCMSET, &result );
  1547. sprintf( message, "setDSR( %i )\n", state );
  1548. report( message );
  1549. LEAVE( "RXTXPort:setDSR()" );
  1550. return;
  1551. }
  1552. /*----------------------------------------------------------
  1553. RXTXPort.isDTR
  1554. accept: none
  1555. perform: check status of DTR
  1556. return: true if TIOCM_DTR is set
  1557. false if TIOCM_DTR is not set
  1558. exceptions: none
  1559. comments: DTR stands for Data Terminal Ready
  1560. ----------------------------------------------------------*/
  1561. jboolean gnu::io::RXTXPort::isDTR(
  1562. )
  1563. {
  1564. unsigned int result = 0;
  1565. int fd = ( int ) this->fd;
  1566. char message[80];
  1567. ENTER( "RXTXPort:isDTR" );
  1568. ioctl( fd, TIOCMGET, &result );
  1569. sprintf( message, "isDTR( ) returns %i\n", result& TIOCM_DTR );
  1570. report( message );
  1571. LEAVE( "RXTXPort:isDTR" );
  1572. if( result & TIOCM_DTR ) return true;
  1573. else return false;
  1574. }
  1575. /*----------------------------------------------------------
  1576. RXTXPort.setDTR
  1577. accept: new DTR state
  1578. perform: if state is true, TIOCM_DTR is set
  1579. if state is false, TIOCM_DTR is unset
  1580. return: none
  1581. exceptions: none
  1582. comments: DTR stands for Data Terminal Ready
  1583. ----------------------------------------------------------*/
  1584. void gnu::io::RXTXPort::setDTR(
  1585. jboolean state
  1586. )
  1587. {
  1588. unsigned int result = 0;
  1589. int fd = ( int ) this->fd;
  1590. char message[80];
  1591. ENTER( "RXTXPort:setDTR" );
  1592. ioctl( fd, TIOCMGET, &result );
  1593. if( state == true ) result |= TIOCM_DTR;
  1594. else result &= ~TIOCM_DTR;
  1595. ioctl( fd, TIOCMSET, &result );
  1596. sprintf( message, "setDTR( %i )\n", state );
  1597. report( message );
  1598. LEAVE( "RXTXPort:setDTR" );
  1599. return;
  1600. }
  1601. /*----------------------------------------------------------
  1602. RXTXPort.static_add_filename
  1603. accept: filename and fd to save
  1604. perform: add a struct holding the info to a linked list
  1605. return: none
  1606. exceptions: none
  1607. comments: the info is checked on open() if its in the list no
  1608. changes are performed on the file on open()
  1609. comments: see
  1610. RXTXPort.nativeStaticSetDSR
  1611. RXTXPort.nativeStaticSetDTR
  1612. RXTXPort.nativeStaticSetRTS
  1613. RXTXPort.nativeStaticSetSerialPortParams
  1614. This is used so people can setDTR low before calling the
  1615. -----------------------------------------------------------*/
  1616. void static_add_filename( const char *filename, int fd)
  1617. {
  1618. struct preopened *newp, *p = preopened_port;
  1619. newp = ( struct preopened *) malloc( sizeof( struct preopened ) );
  1620. strcpy( newp->filename, filename );
  1621. newp->fd = fd;
  1622. if( !p )
  1623. {
  1624. newp->next = NULL;
  1625. newp->prev = NULL;
  1626. preopened_port = newp;
  1627. return;
  1628. }
  1629. for(;;)
  1630. {
  1631. if( !strcmp( p->filename, filename) )
  1632. {
  1633. /* already open */
  1634. return;
  1635. }
  1636. if( p->next )
  1637. {
  1638. p = p->next;
  1639. }
  1640. else
  1641. {
  1642. /* end of list */
  1643. newp->next = NULL;
  1644. newp->prev = p;
  1645. p->next = newp;
  1646. preopened_port = p;
  1647. return;
  1648. }
  1649. }
  1650. }
  1651. /*----------------------------------------------------------
  1652. RXTXPort.nativeSetBaudBase
  1653. accept: The Baud Base for custom speeds
  1654. perform: set the Baud Base
  1655. return: 0 on success
  1656. exceptions: Unsupported Comm Operation on systems not supporting
  1657. TIOCGSERIAL
  1658. comments:
  1659. Set baud rate to 38400 before using this
  1660. First introduced in rxtx-2.1-3
  1661. ----------------------------------------------------------*/
  1662. jboolean gnu::io::RXTXPort::nativeSetBaudBase(
  1663. jint BaudBase
  1664. )
  1665. {
  1666. #if defined(TIOCGSERIAL)
  1667. int fd = ( int ) this->fd;
  1668. struct serial_struct sstruct;
  1669. if ( sstruct.baud_base < 1 ||
  1670. ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
  1671. {
  1672. return( true );
  1673. }
  1674. return( false );
  1675. #else
  1676. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetBaudBase" );
  1677. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  1678. return( true );
  1679. #endif /* TIOCGSERIAL */
  1680. }
  1681. /*----------------------------------------------------------
  1682. RXTXPort.nativeGetBaudBase
  1683. accept: the Baud Base used for custom speeds
  1684. perform:
  1685. return: Baud Base
  1686. exceptions: Unsupported Comm Operation on systems not supporting
  1687. TIOCGSERIAL
  1688. comments:
  1689. First introduced in rxtx-2.1-3
  1690. ----------------------------------------------------------*/
  1691. jint gnu::io::RXTXPort::nativeGetBaudBase(
  1692. )
  1693. {
  1694. #if defined(TIOCGSERIAL)
  1695. int fd = ( int ) this->fd;
  1696. struct serial_struct sstruct;
  1697. if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
  1698. {
  1699. return( ( jint ) -1 );
  1700. }
  1701. return( ( jint ) ( sstruct.baud_base ) );
  1702. #else
  1703. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeGetBaudBase" );
  1704. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  1705. return( ( jint ) -1 );
  1706. #endif /* TIOCGSERIAL */
  1707. }
  1708. /*----------------------------------------------------------
  1709. RXTXPort.nativeSetDivisor
  1710. accept: Divisor for custom speeds
  1711. perform: set the Divisor for custom speeds
  1712. return: 0 on success
  1713. exceptions: Unsupported Comm Operation on systems not supporting
  1714. TIOCGSERIAL
  1715. comments:
  1716. Set baud rate to 38400 before using this
  1717. First introduced in rxtx-2.1-3
  1718. ----------------------------------------------------------*/
  1719. jboolean gnu::io::RXTXPort::nativeSetDivisor(
  1720. jint Divisor
  1721. )
  1722. {
  1723. #if defined(TIOCGSERIAL)
  1724. int fd = ( int ) this->fd;
  1725. struct serial_struct sstruct;
  1726. if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
  1727. {
  1728. return( true );
  1729. }
  1730. if ( sstruct.custom_divisor < 1 ||
  1731. ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
  1732. {
  1733. return( true );
  1734. }
  1735. return( false );
  1736. #else
  1737. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetDivisor" );
  1738. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  1739. return( true );
  1740. #endif /* TIOCGSERIAL */
  1741. }
  1742. /*----------------------------------------------------------
  1743. RXTXPort.nativeGetDivisor
  1744. accept: none
  1745. perform: Find the Divisor used for custom speeds
  1746. return: Divisor
  1747. exceptions: Unsupported Comm Operation on systems not supporting
  1748. TIOCGSERIAL
  1749. comments:
  1750. First introduced in rxtx-2.1-3
  1751. ----------------------------------------------------------*/
  1752. jint gnu::io::RXTXPort::nativeGetDivisor(
  1753. )
  1754. {
  1755. #if defined(TIOCGSERIAL)
  1756. int fd = ( int ) this->fd;
  1757. struct serial_struct sstruct;
  1758. if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
  1759. {
  1760. return( ( jint ) -1 );
  1761. }
  1762. return( ( jint ) sstruct.custom_divisor );
  1763. #else
  1764. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeGetDivisor" );
  1765. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  1766. return( ( jint ) -1 );
  1767. #endif /* TIOCGSERIAL */
  1768. }
  1769. /*----------------------------------------------------------
  1770. RXTXPort.nativeStaticSetDSR
  1771. accept: new RTS state
  1772. perform: if flag is true, TIOCM_DSR is set
  1773. if flag is false, TIOCM_DSR is unset
  1774. return: none
  1775. exceptions: none
  1776. comments: Set the DSR so it does not raise on the next open
  1777. needed for some funky test boards?
  1778. This is static so we can not call the open() setDSR()
  1779. we dont have the jobject.
  1780. First introduced in rxtx-1.5-9
  1781. ----------------------------------------------------------*/
  1782. jboolean gnu::io::RXTXPort::nativeStaticSetDSR (
  1783. jstring jstr,
  1784. jboolean flag
  1785. )
  1786. {
  1787. int fd, i, pid = -1, result;
  1788. char filename[80];
  1789. for( i=0;i<jstr->length();i++)
  1790. filename[i] = jstr->charAt(i);
  1791. filename[i] = '\0';
  1792. ENTER( "RXTXPort:nativeStaticSetDSR" );
  1793. #ifndef WIN32
  1794. pid = getpid();
  1795. #endif /* WIN32 */
  1796. /* Open and lock the port so nothing else changes the setting */
  1797. if ( LOCK( filename, pid ) ) goto fail;;
  1798. fd = find_preopened_ports( filename );
  1799. if( !fd )
  1800. {
  1801. do {
  1802. fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
  1803. } while (fd < 0 && errno==EINTR);
  1804. if ( configure_port( fd ) ) goto fail;
  1805. }
  1806. if ( fd < 0 ) goto fail;
  1807. /* raise the DSR */
  1808. ioctl( fd, TIOCMGET, &result );
  1809. if( flag == true ) result |= TIOCM_DSR;
  1810. else result &= ~TIOCM_DSR;
  1811. ioctl( fd, TIOCMSET, &result );
  1812. /* Unlock the port. Good luck! :) */
  1813. UNLOCK( filename, pid );
  1814. static_add_filename( filename, fd );
  1815. /* dont close the port. Its not clear if the DSR would remain high */
  1816. LEAVE( "RXTXPort:nativeStaticSetDSR" );
  1817. return( true );
  1818. fail:
  1819. LEAVE( "RXTXPort:nativeStaticSetDSR" );
  1820. return( false );
  1821. }
  1822. /*----------------------------------------------------------
  1823. RXTXPort.nativeStaticSetRTS
  1824. accept: new RTS state
  1825. perform: if flag is true, TIOCM_RTS is set
  1826. if flag is false, TIOCM_RTS is unset
  1827. return: none
  1828. exceptions: none
  1829. comments: Set the RTS so it does not raise on the next open
  1830. needed for some funky test boards?
  1831. This is static so we can not call the open() setDTR()
  1832. we dont have the jobject.
  1833. First introduced in rxtx-1.5-9
  1834. ----------------------------------------------------------*/
  1835. jboolean gnu::io::RXTXPort::nativeStaticSetRTS (
  1836. jstring jstr,
  1837. jboolean flag
  1838. )
  1839. {
  1840. int fd, i, pid = -1, result;
  1841. char filename[80];
  1842. for( i=0;i<jstr->length();i++)
  1843. filename[i] = jstr->charAt(i);
  1844. filename[i] = '\0';
  1845. ENTER( "RXTXPort:nativeStaticSetRTS" );
  1846. #ifndef WIN32
  1847. pid = getpid();
  1848. #endif /* WIN32 */
  1849. /* Open and lock the port so nothing else changes the setting */
  1850. if ( LOCK( filename, pid ) ) goto fail;;
  1851. fd = find_preopened_ports( filename );
  1852. if( !fd )
  1853. {
  1854. do {
  1855. fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
  1856. } while (fd < 0 && errno==EINTR);
  1857. if ( configure_port( fd ) ) goto fail;
  1858. }
  1859. if ( fd < 0 ) goto fail;
  1860. /* raise the RTS */
  1861. ioctl( fd, TIOCMGET, &result );
  1862. if( flag == true ) result |= TIOCM_RTS;
  1863. else result &= ~TIOCM_RTS;
  1864. ioctl( fd, TIOCMSET, &result );
  1865. /* Unlock the port. Good luck! :) */
  1866. UNLOCK( filename, pid );
  1867. static_add_filename( filename, fd );
  1868. /* dont close the port. Its not clear if the RTS would remain high */
  1869. LEAVE( "RXTXPort:nativeStaticSetRTS" );
  1870. return( true );
  1871. fail:
  1872. LEAVE( "RXTXPort:nativeStaticSetRTS" );
  1873. return( false );
  1874. }
  1875. /*----------------------------------------------------------
  1876. RXTXPort.nativeStaticSetSerialPortParams
  1877. accept: string for the filename, int baudrate, int databits,
  1878. int stopbits, int parity
  1879. perform: set the serial port, set the params, save the fd in a linked
  1880. list.
  1881. return: none
  1882. exceptions: none
  1883. comments: Not set the speed on the next 'open'
  1884. This is static so we can not call the open() setDTR()
  1885. we dont have the jobject.
  1886. First introduced in rxtx-1.5-9
  1887. ----------------------------------------------------------*/
  1888. void gnu::io::RXTXPort::nativeStaticSetSerialPortParams (
  1889. jstring jstr,
  1890. jint baudrate,
  1891. jint dataBits,
  1892. jint stopBits,
  1893. jint parity
  1894. )
  1895. {
  1896. int fd, i, pid = -1, cspeed = translate_speed( baudrate );
  1897. char msg[80];
  1898. char filename[80];
  1899. for( i=0;i<jstr->length();i++)
  1900. filename[i] = jstr->charAt(i);
  1901. filename[i] = '\0';
  1902. ENTER( "RXTXPort:nativeStaticSetSerialPortParams" );
  1903. #ifndef WIN32
  1904. pid = getpid();
  1905. #endif /* WIN32 */
  1906. /* Open and lock the port so nothing else changes the setting */
  1907. if ( LOCK( filename, pid ) ) goto fail;
  1908. fd = find_preopened_ports( filename );
  1909. if( !fd )
  1910. {
  1911. do {
  1912. fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
  1913. } while (fd < 0 && errno==EINTR);
  1914. if ( configure_port( fd ) ) goto fail;
  1915. }
  1916. if ( fd < 0 )
  1917. {
  1918. LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
  1919. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeStaticSetSerialPortParams" );
  1920. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  1921. return;
  1922. }
  1923. if (cspeed == -1)
  1924. {
  1925. LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
  1926. snprintf( msg, 79, "%s%s", "BaudRate could not be set to the specified value", " in nativeStaticSetSerialPortParams" );
  1927. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  1928. return;
  1929. }
  1930. if( set_port_params( fd, cspeed, dataBits, stopBits, parity ) )
  1931. {
  1932. LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
  1933. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeStaticSetSerialPortParams" );
  1934. return;
  1935. }
  1936. /* Unlock the port. Good luck! :) */
  1937. UNLOCK( filename, pid );
  1938. static_add_filename( filename, fd );
  1939. /* dont close the port. */
  1940. LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
  1941. return;
  1942. fail:
  1943. LEAVE( "RXTXPort:nativeStaticSetSerialPortParams" );
  1944. return;
  1945. }
  1946. /*----------------------------------------------------------
  1947. RXTXPort.nativeStaticSetDTR
  1948. accept: new DTR state
  1949. perform: if flag is true, TIOCM_DTR is set
  1950. if flag is false, TIOCM_DTR is unset
  1951. return: none
  1952. exceptions: none
  1953. comments: Set the DTR so it does not raise on the next open
  1954. needed for some funky test boards?
  1955. This is static so we can not call the open() setDTR()
  1956. we dont have the jobject.
  1957. First introduced in rxtx-1.5-9
  1958. ----------------------------------------------------------*/
  1959. jboolean gnu::io::RXTXPort::nativeStaticSetDTR (
  1960. jstring jstr,
  1961. jboolean flag
  1962. )
  1963. {
  1964. int fd, i, pid = -1, result;
  1965. char filename[80];
  1966. for( i=0;i<jstr->length();i++)
  1967. filename[i] = jstr->charAt(i);
  1968. filename[i] = '\0';
  1969. ENTER( "RXTXPort:nativeStaticSetDTR" );
  1970. #ifndef WIN32
  1971. pid = getpid();
  1972. #endif /* WIN32 */
  1973. /* Open and lock the port so nothing else changes the setting */
  1974. if ( LOCK( filename, pid ) ) goto fail;;
  1975. fd = find_preopened_ports( filename );
  1976. if( !fd )
  1977. {
  1978. do {
  1979. fd = ::OPEN (filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
  1980. } while (fd < 0 && errno==EINTR);
  1981. if ( configure_port( fd ) ) goto fail;
  1982. }
  1983. if ( fd < 0 ) goto fail;
  1984. /* raise the DTR */
  1985. ioctl( fd, TIOCMGET, &result );
  1986. if( flag == true ) result |= TIOCM_DTR;
  1987. else result &= ~TIOCM_DTR;
  1988. ioctl( fd, TIOCMSET, &result );
  1989. /* Unlock the port. Good luck! :) */
  1990. UNLOCK( filename, pid );
  1991. static_add_filename( filename, fd );
  1992. /* dont close the port. Its not clear if the DTR would remain high */
  1993. LEAVE( "RXTXPort:nativeStaticSetDTR" );
  1994. return( true );
  1995. fail:
  1996. LEAVE( "RXTXPort:nativeStaticSetDTR" );
  1997. return( false );
  1998. }
  1999. /*----------------------------------------------------------
  2000. RXTXPort.nativeStaticIsRTS
  2001. accept: filename
  2002. perform: check status of RTS of preopened ports (setting lines/params
  2003. before calling the Java open()
  2004. return: true if TIOCM_RTS is set
  2005. false if TIOCM_RTS is not set
  2006. exceptions: none
  2007. comments: RTS stands for Request to Send
  2008. ----------------------------------------------------------*/
  2009. jboolean gnu::io::RXTXPort::nativeStaticIsRTS(
  2010. jstring jstr
  2011. )
  2012. {
  2013. unsigned int result = 0;
  2014. int i, fd;
  2015. char message[80];
  2016. char filename[80];
  2017. for( i=0;i<jstr->length();i++)
  2018. filename[i] = jstr->charAt(i);
  2019. filename[i] = '\0';
  2020. fd = find_preopened_ports( filename );
  2021. ENTER( "RXTXPort:nativeStaticIsRTS" );
  2022. if( !fd )
  2023. {
  2024. /* Exception? FIXME */
  2025. return false;
  2026. }
  2027. ioctl( fd, TIOCMGET, &result );
  2028. sprintf( message, "nativeStaticIsRTS( ) returns %i\n", result& TIOCM_RTS );
  2029. report( message );
  2030. LEAVE( "RXTXPort:nativeStaticIsRTS" );
  2031. if( result & TIOCM_RTS ) return true;
  2032. else return false;
  2033. }
  2034. /*----------------------------------------------------------
  2035. RXTXPort.nativeStaticIsDSR
  2036. accept: filename
  2037. perform: check status of DSR of preopened ports (setting lines/params
  2038. before calling the Java open()
  2039. return: true if TIOCM_DSR is set
  2040. false if TIOCM_DSR is not set
  2041. exceptions: none
  2042. comments:
  2043. ----------------------------------------------------------*/
  2044. jboolean gnu::io::RXTXPort::nativeStaticIsDSR(
  2045. jstring jstr
  2046. )
  2047. {
  2048. unsigned int result = 0;
  2049. int i, fd;
  2050. char message[80];
  2051. char filename[80];
  2052. for( i=0;i<jstr->length();i++)
  2053. filename[i] = jstr->charAt(i);
  2054. filename[i] = '\0';
  2055. fd = find_preopened_ports( filename );
  2056. ENTER( "RXTXPort:nativeStaticIsDSR" );
  2057. if( !fd )
  2058. {
  2059. /* Exception? FIXME */
  2060. return false;
  2061. }
  2062. ioctl( fd, TIOCMGET, &result );
  2063. sprintf( message, "nativeStaticIsDSR( ) returns %i\n", result& TIOCM_DSR );
  2064. report( message );
  2065. LEAVE( "RXTXPort:nativeStaticIsDSR" );
  2066. if( result & TIOCM_DSR ) return true;
  2067. else return false;
  2068. }
  2069. /*----------------------------------------------------------
  2070. RXTXPort.nativeStaticIsDTR
  2071. accept: filename
  2072. perform: check status of DTR of preopened ports (setting lines/params
  2073. before calling the Java open()
  2074. return: true if TIOCM_DTR is set
  2075. false if TIOCM_DTR is not set
  2076. exceptions: none
  2077. comments: DTR stands for Data Terminal Ready
  2078. ----------------------------------------------------------*/
  2079. jboolean gnu::io::RXTXPort::nativeStaticIsDTR(
  2080. jstring jstr
  2081. )
  2082. {
  2083. unsigned int result = 0;
  2084. int i, fd;
  2085. char message[80];
  2086. char filename[80];
  2087. for( i=0;i<jstr->length();i++)
  2088. filename[i] = jstr->charAt(i);
  2089. filename[i] = '\0';
  2090. fd = find_preopened_ports( filename );
  2091. ENTER( "RXTXPort:nativeStaticIsDTR" );
  2092. if( !fd )
  2093. {
  2094. /* Exception? FIXME */
  2095. return false;
  2096. }
  2097. ioctl( fd, TIOCMGET, &result );
  2098. sprintf( message, "nativeStaticIsDTR( ) returns %i\n", result& TIOCM_DTR );
  2099. report( message );
  2100. LEAVE( "RXTXPort:nativeStaticIsDTR" );
  2101. if( result & TIOCM_DTR ) return true;
  2102. else return false;
  2103. }
  2104. /*----------------------------------------------------------
  2105. RXTXPort.nativeStaticIsCD
  2106. accept: filename
  2107. perform: check status of CD of preopened ports (setting lines/params
  2108. before calling the Java open()
  2109. return: true if TIOCM_CD is set
  2110. false if TIOCM_CD is not set
  2111. exceptions: none
  2112. comments: CD stands for carrier detect
  2113. ----------------------------------------------------------*/
  2114. jboolean gnu::io::RXTXPort::nativeStaticIsCD(
  2115. jstring jstr
  2116. )
  2117. {
  2118. unsigned int result = 0;
  2119. int i, fd;
  2120. char message[80];
  2121. char filename[80];
  2122. for( i=0;i<jstr->length();i++)
  2123. filename[i] = jstr->charAt(i);
  2124. filename[i] = '\0';
  2125. fd = find_preopened_ports( filename );
  2126. ENTER( "RXTXPort:nativeStaticIsCD" );
  2127. if( !fd )
  2128. {
  2129. /* Exception? FIXME */
  2130. return false;
  2131. }
  2132. ioctl( fd, TIOCMGET, &result );
  2133. sprintf( message, "nativeStaticIsCD( ) returns %i\n", result& TIOCM_CD );
  2134. report( message );
  2135. LEAVE( "RXTXPort:nativeStaticIsCD" );
  2136. if( result & TIOCM_CD ) return true;
  2137. else return false;
  2138. }
  2139. /*----------------------------------------------------------
  2140. RXTXPort.nativeStaticIsCTS
  2141. accept: filename
  2142. perform: check status of CTS of preopened ports (setting lines/params
  2143. before calling the Java open()
  2144. return: true if TIOCM_CTS is set
  2145. false if TIOCM_CTS is not set
  2146. exceptions: none
  2147. comments: CTS stands for Clear To Send
  2148. ----------------------------------------------------------*/
  2149. jboolean gnu::io::RXTXPort::nativeStaticIsCTS(
  2150. jstring jstr
  2151. )
  2152. {
  2153. unsigned int result = 0;
  2154. int i, fd;
  2155. char message[80];
  2156. char filename[80];
  2157. for( i=0;i<jstr->length();i++)
  2158. filename[i] = jstr->charAt(i);
  2159. filename[i] = '\0';
  2160. fd = find_preopened_ports( filename );
  2161. ENTER( "RXTXPort:nativeStaticIsCTS" );
  2162. if( !fd )
  2163. {
  2164. /* Exception? FIXME */
  2165. return false;
  2166. }
  2167. ioctl( fd, TIOCMGET, &result );
  2168. sprintf( message, "nativeStaticIsCTS( ) returns %i\n", result& TIOCM_CTS );
  2169. report( message );
  2170. LEAVE( "RXTXPort:nativeStaticIsCTS" );
  2171. if( result & TIOCM_CTS ) return true;
  2172. else return false;
  2173. }
  2174. /*----------------------------------------------------------
  2175. RXTXPort.nativeStaticIsRI
  2176. accept: filename
  2177. perform: check status of RI of preopened ports (setting lines/params
  2178. before calling the Java open()
  2179. return: true if TIOCM_RI is set
  2180. false if TIOCM_RI is not set
  2181. exceptions: none
  2182. comments: RI stands for carrier detect
  2183. ----------------------------------------------------------*/
  2184. jboolean gnu::io::RXTXPort::nativeStaticIsRI(
  2185. jstring jstr
  2186. )
  2187. {
  2188. unsigned int result = 0;
  2189. int i, fd;
  2190. char message[80];
  2191. char filename[80];
  2192. for( i=0;i<jstr->length();i++)
  2193. filename[i] = jstr->charAt(i);
  2194. filename[i] = '\0';
  2195. fd = find_preopened_ports( filename );
  2196. ENTER( "RXTXPort:nativeStaticIsRI" );
  2197. if( !fd )
  2198. {
  2199. /* Exception? FIXME */
  2200. return false;
  2201. }
  2202. ioctl( fd, TIOCMGET, &result );
  2203. sprintf( message, "nativeStaticRI( ) returns %i\n", result& TIOCM_RI );
  2204. report( message );
  2205. LEAVE( "RXTXPort:nativeStaticIsRI" );
  2206. if( result & TIOCM_RI ) return true;
  2207. else return false;
  2208. }
  2209. /*----------------------------------------------------------
  2210. RXTXPort.nativeStaticGetBaudRate
  2211. accept: filename
  2212. perform: find the baud rate (not all buads are handled yet)
  2213. return: return the baud rate or -1 if not supported yet.
  2214. exceptions:
  2215. comments: simple test for preopened ports
  2216. ----------------------------------------------------------*/
  2217. jint gnu::io::RXTXPort::nativeStaticGetBaudRate(
  2218. jstring jstr
  2219. )
  2220. {
  2221. int i, fd;
  2222. struct termios ttyset;
  2223. int baudrate;
  2224. char filename[80];
  2225. for( i=0;i<jstr->length();i++)
  2226. filename[i] = jstr->charAt(i);
  2227. filename[i] = '\0';
  2228. fd = find_preopened_ports( filename );
  2229. ENTER( "RXTXPort:nativeStaticGetBaudRate" );
  2230. if( !fd )
  2231. {
  2232. /* Exception? FIXME */
  2233. return -1;
  2234. }
  2235. if( tcgetattr( fd, &ttyset ) < 0 )
  2236. {
  2237. report( "nativeStaticGetBaudRate: Cannot Get Serial Port Settings\n" );
  2238. return(-1);
  2239. }
  2240. /*
  2241. dima writes:
  2242. Trent, here is something I found with google:
  2243. (freebsd list freebsd-current@freebsd.org)
  2244. Andrzej Bialecki <abial@korin.warman.org.pl> asked:
  2245. I tried to compile a piece of software, probably for Linux, and I noticed
  2246. that we don't define CBAUD constant. I'm not sure, but I think POSIX
  2247. defines and uses it. Should(n't) we?
  2248. Bruce Evans <bde@zeta.org.au> answered:
  2249. CBAUD is for SYSV compatibility. It is considerably inferior to POSIX's
  2250. cf{get,set}{i,o}speed and shouldn't be provided or used.
  2251. */
  2252. #if defined(CBAUD)/* dima */
  2253. baudrate = ttyset.c_cflag&CBAUD;
  2254. #else
  2255. if(cfgetispeed(&ttyset) != cfgetospeed(&ttyset)) return -1;
  2256. baudrate = cfgetispeed(&ttyset);
  2257. #endif
  2258. return( get_java_baudrate(baudrate) );
  2259. }
  2260. /*----------------------------------------------------------
  2261. RXTXPort.nativeStaticGetDataBits
  2262. accept: filename
  2263. perform: find the data bits (not all buads are handled yet)
  2264. return: return the data bits
  2265. exceptions:
  2266. comments: simple test for preopened ports
  2267. ----------------------------------------------------------*/
  2268. jint gnu::io::RXTXPort::nativeStaticGetDataBits(
  2269. jstring jstr
  2270. )
  2271. {
  2272. int i, fd;
  2273. struct termios ttyset;
  2274. char filename[80];
  2275. for( i=0;i<jstr->length();i++)
  2276. filename[i] = jstr->charAt(i);
  2277. filename[i] = '\0';
  2278. fd = find_preopened_ports( filename );
  2279. ENTER( "RXTXPort:nativeStaticGetDataBits" );
  2280. if( !fd )
  2281. {
  2282. /* Exception? FIXME */
  2283. return -1;
  2284. }
  2285. if( tcgetattr( fd, &ttyset ) < 0 )
  2286. {
  2287. report( "nativeStaticGetDataBits: Cannot Get Serial Port Settings\n" );
  2288. return(-1);
  2289. }
  2290. switch( ttyset.c_cflag&CSIZE ) {
  2291. case CS5: return JDATABITS_5;
  2292. case CS6: return JDATABITS_6;
  2293. case CS7: return JDATABITS_7;
  2294. case CS8: return JDATABITS_8;
  2295. default: return(-1);
  2296. }
  2297. }
  2298. /*----------------------------------------------------------
  2299. RXTXPort.nativeStaticGetParity
  2300. accept: filename
  2301. perform: find the parity
  2302. return: return the parity
  2303. exceptions:
  2304. comments: simple test for preopened ports
  2305. ----------------------------------------------------------*/
  2306. jint gnu::io::RXTXPort::nativeStaticGetParity(
  2307. jstring jstr
  2308. )
  2309. {
  2310. int i, fd;
  2311. struct termios ttyset;
  2312. char filename[80];
  2313. for( i=0;i<jstr->length();i++)
  2314. filename[i] = jstr->charAt(i);
  2315. filename[i] = '\0';
  2316. fd = find_preopened_ports( filename );
  2317. ENTER( "RXTXPort:nativeStaticGetParity" );
  2318. if( !fd )
  2319. {
  2320. /* Exception? FIXME */
  2321. return -1;
  2322. }
  2323. if( tcgetattr( fd, &ttyset ) < 0 )
  2324. {
  2325. report( "nativeStaticGetParity: Cannot Get Serial Port Settings\n" );
  2326. return(-1);
  2327. }
  2328. #ifdef CMSPAR
  2329. switch( ttyset.c_cflag&(PARENB|PARODD|CMSPAR ) ) {
  2330. #else
  2331. switch( ttyset.c_cflag&(PARENB|PARODD) ) {
  2332. #endif /* CMSPAR */
  2333. case 0: return JPARITY_NONE;
  2334. case PARENB: return JPARITY_EVEN;
  2335. case PARENB | PARODD: return JPARITY_ODD;
  2336. #ifdef CMSPAR
  2337. case PARENB | PARODD | CMSPAR: return JPARITY_MARK;
  2338. case PARENB | CMSPAR: return JPARITY_SPACE;
  2339. #endif /* CMSPAR */
  2340. default: return(-1);
  2341. }
  2342. }
  2343. /*----------------------------------------------------------
  2344. RXTXPort.nativeStaticGetStopBits
  2345. accept: filename
  2346. perform: find the stop bits
  2347. return: return the stop bits
  2348. exceptions:
  2349. comments: simple test for preopened ports
  2350. ----------------------------------------------------------*/
  2351. jint gnu::io::RXTXPort::nativeStaticGetStopBits(
  2352. jstring jstr
  2353. )
  2354. {
  2355. int i, fd;
  2356. struct termios ttyset;
  2357. char filename[80];
  2358. fd = find_preopened_ports( filename );
  2359. for( i=0;i<jstr->length();i++)
  2360. filename[i] = jstr->charAt(i);
  2361. filename[i] = '\0';
  2362. ENTER( "RXTXPort:nativeStaticGetStopBits" );
  2363. if( !fd )
  2364. {
  2365. /* Exception? FIXME */
  2366. return -1;
  2367. }
  2368. if( tcgetattr( fd, &ttyset ) < 0 )
  2369. {
  2370. report( "nativeStaticGetStopBits: Cannot Get Serial Port Settings\n" );
  2371. return(-1);
  2372. }
  2373. switch( ttyset.c_cflag&(CSTOPB) ) {
  2374. case 0: return STOPBITS_1;
  2375. case CSTOPB: return STOPBITS_2;
  2376. default: return STOPBITS_1_5;
  2377. }
  2378. }
  2379. /*----------------------------------------------------------
  2380. RXTXPort.nativeGetParityErrorChar
  2381. accept: -
  2382. perform: check the ParityErrorChar
  2383. return: The ParityErrorChar as an jbyte.
  2384. exceptions: UnsupportedCommOperationException if not implemented
  2385. comments: It appears the Parity char is usually \0. The windows
  2386. API allows for this to be changed. I cant find may
  2387. examples of this being done. Maybe for a reason.
  2388. Use a direct call to the termios file until we find a
  2389. solution.
  2390. ----------------------------------------------------------*/
  2391. jbyte gnu::io::RXTXPort::nativeGetParityErrorChar(
  2392. )
  2393. {
  2394. unsigned int result = 0;
  2395. ENTER( "nativeGetParityErrorChar" );
  2396. #ifdef WIN32
  2397. result = ( jbyte ) termiosGetParityErrorChar(
  2398. this->fd );
  2399. #else
  2400. /*
  2401. arg! I cant find a way to change it from \0 in Linux. I think
  2402. the frame and parity error characters are hardcoded.
  2403. */
  2404. result = ( jint ) '\0';
  2405. #endif /* WIN32 */
  2406. LEAVE( "nativeGetParityErrorChar" );
  2407. return( ( jbyte ) result );
  2408. }
  2409. /*----------------------------------------------------------
  2410. RXTXPort.nativeGetEndOfInputChar
  2411. accept: -
  2412. perform: check the EndOf InputChar
  2413. return: the EndOfInputChar as an jbyte. -1 on error
  2414. exceptions: UnsupportedCommOperationException if not implemented
  2415. comments:
  2416. ----------------------------------------------------------*/
  2417. jbyte gnu::io::RXTXPort::nativeGetEndOfInputChar(
  2418. )
  2419. {
  2420. int fd = ( int ) this->fd;
  2421. struct termios ttyset;
  2422. ENTER( "nativeGetEndOfInputChar" );
  2423. if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
  2424. LEAVE( "nativeGetEndOfInputChar" );
  2425. return( (jbyte) ttyset.c_cc[VEOF] );
  2426. fail:
  2427. LEAVE( "nativeGetEndOfInputChar" );
  2428. report( "nativeGetEndOfInputChar failed\n" );
  2429. return( ( jbyte ) -1 );
  2430. }
  2431. /*----------------------------------------------------------
  2432. RXTXPort.nativeSetParityErrorChar
  2433. accept: the ParityArrorCharacter as an int.
  2434. perform: Set the ParityErrorChar
  2435. return: true on success
  2436. exceptions: UnsupportedCommOperationException if not implemented
  2437. comments: It appears the Parity char is usually \0. The windows
  2438. API allows for this to be changed. I cant find may
  2439. examples of this being done. Maybe for a reason.
  2440. Use a direct call to the termios file until we find a
  2441. solution.
  2442. ----------------------------------------------------------*/
  2443. jboolean gnu::io::RXTXPort::nativeSetParityErrorChar(
  2444. jbyte value
  2445. )
  2446. {
  2447. char msg[80];
  2448. #ifdef WIN32
  2449. int fd = ( int ) this->fd;
  2450. ENTER( "nativeSetParityErrorChar" );
  2451. termiosSetParityError( fd, ( char ) value );
  2452. LEAVE( "nativeSetParityErrorChar" );
  2453. return( true );
  2454. #else
  2455. ENTER( "nativeSetParityErrorChar" );
  2456. /*
  2457. arg! I cant find a way to change it from \0 in Linux. I think
  2458. the frame and parity error characters are hardcoded.
  2459. */
  2460. snprintf( msg, 79, "%s%s", strerror( errno ), " in setParityErrorChar()" );
  2461. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  2462. LEAVE( "nativeSetParityErrorChar" );
  2463. return( false );
  2464. #endif /* WIN32 */
  2465. }
  2466. /*----------------------------------------------------------
  2467. RXTXPort.nativeSetEndOfInputChar
  2468. accept: The EndOfInputChar as an int
  2469. perform: set the EndOfInputChar
  2470. return: true on success
  2471. exceptions: UnsupportedCommOperationException if not implemented
  2472. comments: This may cause troubles on Windows.
  2473. Lets give it a shot and see what happens.
  2474. See termios.c for the windows bits.
  2475. EofChar = val;
  2476. fBinary = false; winapi docs say always use true. ?
  2477. ----------------------------------------------------------*/
  2478. jboolean gnu::io::RXTXPort::nativeSetEndOfInputChar(
  2479. jbyte value
  2480. )
  2481. {
  2482. int fd = ( int ) this->fd;
  2483. struct termios ttyset;
  2484. char msg[80];
  2485. ENTER( "nativeSetEndOfInputChar" );
  2486. if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
  2487. ttyset.c_cc[VEOF] = ( char ) value;
  2488. if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 ) goto fail;
  2489. LEAVE( "nativeSetEndOfInputChar" );
  2490. return( true );
  2491. fail:
  2492. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeSetEndOfInputChar" );
  2493. throw new gnu::io::UnsupportedCommOperationException( JvNewStringUTF( msg ) );
  2494. report( "nativeSetEndOfInputChar failed\n" );
  2495. LEAVE( "nativeSetEndOfInputChar" );
  2496. return( false );
  2497. }
  2498. #ifndef WIN32
  2499. long
  2500. GetTickCount()
  2501. {
  2502. /* return milliseconds */
  2503. struct timeval now;
  2504. gettimeofday(&now, NULL);
  2505. report_verbose("gettimeofday\n");
  2506. #ifdef __QNX__
  2507. return ( ( now.tv_sec * 1000 + now.tv_usec / 1000 ) );
  2508. #else
  2509. return ( ( now.tv_sec * 1000) + ( long ) ceil( ( double ) now.tv_usec / 1000 ) );
  2510. #endif /* __QNX__ */
  2511. }
  2512. #endif /* !WIN32 */
  2513. /*----------------------------------------------------------
  2514. read_byte_array
  2515. accept: int fd file descriptor to read from
  2516. unsigned char *buffer buffer to read data into
  2517. int length number of bytes to read
  2518. int timeout milliseconds to wait before returning
  2519. perform: read bytes from the port into a buffer
  2520. return: status of read
  2521. -1 fail (IOException)
  2522. 0 timeout
  2523. >0 number of bytes read
  2524. comments: According to the Communications API spec, a receive threshold
  2525. of 1 is the same as having the threshold disabled.
  2526. The nuts and bolts are documented in
  2527. NativeEnableReceiveTimeoutThreshold()
  2528. ----------------------------------------------------------*/
  2529. int read_byte_array(
  2530. int fd,
  2531. unsigned char *buffer,
  2532. int length,
  2533. int timeout
  2534. )
  2535. {
  2536. int ret, left, bytes = 0;
  2537. long timeLeft, now = 0, start = 0;
  2538. char msg[80];
  2539. struct timeval tv, *tvP;
  2540. fd_set rset;
  2541. /* TRENT */
  2542. int count = 0;
  2543. sigset_t sigpwr_mask;
  2544. // init the sigset for blocking SIGPWR + SIGXCPU
  2545. sigemptyset(&sigpwr_mask);
  2546. sigaddset(&sigpwr_mask, SIGPWR);
  2547. sigaddset(&sigpwr_mask, SIGXCPU);
  2548. report_time_start();
  2549. ENTER( "read_byte_array" );
  2550. sprintf(msg, "read_byte_array requests %i\n", length);
  2551. report( msg );
  2552. left = length;
  2553. if (timeout >= 0)
  2554. start = GetTickCount();
  2555. while( bytes < length && count++ < 20 );
  2556. {
  2557. if (timeout >= 0) {
  2558. now = GetTickCount();
  2559. if ( now-start >= timeout )
  2560. return bytes;
  2561. }
  2562. FD_ZERO(&rset);
  2563. FD_SET(fd, &rset);
  2564. if (timeout >= 0){
  2565. timeLeft = timeout - (now - start);
  2566. tv.tv_sec = timeLeft / 1000;
  2567. tv.tv_usec = 1000 * ( timeLeft % 1000 );
  2568. tvP = &tv;
  2569. }
  2570. else{
  2571. tvP = NULL;
  2572. }
  2573. // ignore SIGPWR + SIGXCPU during SELECT as gcj GC uses these signals
  2574. sigprocmask(SIG_BLOCK, &sigpwr_mask, NULL);
  2575. do {
  2576. ret = SELECT(fd + 1, &rset, NULL, NULL, tvP);
  2577. } while ( ret < 0 && errno == EINTR );
  2578. sigprocmask(SIG_UNBLOCK, &sigpwr_mask, NULL);
  2579. if (ret == -1){
  2580. report( "read_byte_array: select returned -1\n" );
  2581. LEAVE( "read_byte_array" );
  2582. return -1;
  2583. }
  2584. else if (ret > 0){
  2585. if ((ret = READ( fd, buffer + bytes, left )) < 0 ){
  2586. if (errno != EINTR && errno != EAGAIN){
  2587. report( "read_byte_array: read returned -1\n" );
  2588. LEAVE( "read_byte_array" );
  2589. return -1;
  2590. }
  2591. }
  2592. else if ( ret ) {
  2593. bytes += ret;
  2594. left -= ret;
  2595. }
  2596. /*
  2597. The only thing that is bugging me with the new
  2598. version is the CPU usage when reading on the serial port. I
  2599. looked at it today and find a quick fix. It doesn't seems to
  2600. affect the performance for our apps (I mean in a negative way,
  2601. cause the CPU is back to normal, near 0-5%). All I did is add
  2602. a usleep in the reading function.
  2603. Nicolas <ripley@8d.com>
  2604. */
  2605. else {
  2606. //usleep(10);
  2607. usleep(1000);
  2608. }
  2609. }
  2610. }
  2611. /*
  2612. if( count > 19 )
  2613. {
  2614. throw_java_exception( env, IO_EXCEPTION, "read_byte_array",
  2615. "No data available" );
  2616. }
  2617. */
  2618. //*(buffer+bytes) = 0;
  2619. sprintf(msg, "read_byte_array returns %i\n", bytes);
  2620. report( msg );
  2621. LEAVE( "read_byte_array" );
  2622. report_time_end();
  2623. return bytes;
  2624. }
  2625. /*----------------------------------------------------------
  2626. NativeEnableReceiveTimeoutThreshold
  2627. accept: int threshold, int vtime,int buffer
  2628. perform: Set c_cc->VMIN to threshold and c_cc=>VTIME to vtime
  2629. return: void
  2630. exceptions: IOException
  2631. comments: This is actually all handled in read with select in
  2632. canonical input mode.
  2633. ----------------------------------------------------------*/
  2634. void gnu::io::RXTXPort::NativeEnableReceiveTimeoutThreshold(
  2635. jint vtime,
  2636. jint threshold,
  2637. jint buffer
  2638. )
  2639. {
  2640. int fd = ( int ) this->fd;
  2641. struct termios ttyset;
  2642. int timeout;
  2643. char msg[80];
  2644. if (vtime < 0){
  2645. timeout = 0;
  2646. }
  2647. else if (vtime == 0){
  2648. timeout = 1;
  2649. }
  2650. else{
  2651. timeout = vtime;
  2652. }
  2653. ENTER( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
  2654. if( tcgetattr( fd, &ttyset ) < 0 ) goto fail;
  2655. /* TESTING ttyset.c_cc[ VMIN ] = threshold; */
  2656. ttyset.c_cc[ VMIN ] = 0;
  2657. ttyset.c_cc[ VTIME ] = timeout/100;
  2658. if( tcsetattr( fd, TCSANOW, &ttyset ) < 0 ) goto fail;
  2659. LEAVE( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
  2660. return;
  2661. fail:
  2662. LEAVE( "RXTXPort:NativeEnableRecieveTimeoutThreshold" );
  2663. snprintf( msg, 79, "%s%s", strerror( errno ), " in TimeoutThreshold" );
  2664. throw new java::io::IOException( JvNewStringUTF( msg ) );
  2665. return;
  2666. }
  2667. /*----------------------------------------------------------
  2668. RXTXPort.readByte
  2669. accept: none
  2670. perform: Read a single byte from the port. Block unless an exeption
  2671. is thrown, or end of stream.
  2672. return: The byte read
  2673. exceptions: IOException
  2674. comments:
  2675. On Fri, 30 Aug 2002, Bill Smith wrote:
  2676. I agree, the documentation isn't the best. No surprises there.
  2677. I did do a test using the sun/win32 comm driver with read() and retrieve
  2678. timeout enabled. It blocked until the timeout expired, then returned a -1.
  2679. This seems to jive with the way I'm reading it which is the javax.comm
  2680. comments regarding read (in the CommPort.getInputStream stuff)
  2681. extends/overrides
  2682. the documentation for java.io.InputStream.
  2683. This is the same behavior that the Windriver driver for vxworks exhibits.
  2684. On Fri, 30 Aug 2002, Bill Smith wrote:
  2685. > Hi Trent,
  2686. >
  2687. > I have a couple of questions/comments.
  2688. >
  2689. > 1) I noticed in the thread last night and in the code changes this morning that you
  2690. > now have readByte() (which is called from the input stream read(), to block
  2691. > forever. I pulled the following info from the javax.comm doc for the CommPort class in
  2692. > getInputStream().
  2693. >
  2694. > The way I interpret that is that read() just like read(byte[]), and read(byte[], int, int),
  2695. > show only block indefinitely if timeout is disabled. The sun implementation for win32 (as
  2696. > well as the one we have for vxworks) returns a -1 when it times out.
  2697. >
  2698. Doing what Sun does is going to the least hassle. The documentation was a
  2699. little unclear to me. I assume this is the CommPort.getInputStream
  2700. comment that you mention
  2701. The read behaviour of the input stream returned by getInputStream
  2702. depends on combination of the threshold and timeout values. The
  2703. possible behaviours are described in the table below: ...
  2704. But InputStream is where read(byte) is documented
  2705. http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read()
  2706. Reads the next byte of data from the input stream. The value byte
  2707. is returned as an int in the range 0 to 255. If no byte is
  2708. available because the end of the stream has been reached, the value
  2709. -1 is returned. This method blocks until input data is
  2710. available, the end of the stream is detected, or an exception is
  2711. thrown
  2712. If you are sure commapi is doing a timeout and returning -1, I can change
  2713. it back and document the issue.
  2714. Because I often grep my own mailbox for details, I'm going to add
  2715. these two comments also:
  2716. public int read(byte[] b)
  2717. )
  2718. http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read(byte[])
  2719. Reads some number of bytes from the input stream and stores them
  2720. into the buffer array b. The number of bytes actually read is
  2721. returned as an integer. This method blocks until input data is
  2722. available, end of file is detected, or an exception is thrown.
  2723. If b is null, a NullPointerException is thrown. If the length of b
  2724. is zero, then no bytes are read and 0 is returned; otherwise,
  2725. there is an attempt to read at least one byte. If no byte is
  2726. available because the stream is at end of file, the value -1 is
  2727. returned; otherwise, at least one byte is read and stored into b.
  2728. So read(byte[] b) is documented as blocking for the first byte.
  2729. public int read(byte[] b,int off,int len)
  2730. http://java.sun.com/j2se/1.3/docs/api/java/io/InputStream.html#read(byte[],
  2731. int, int)
  2732. Reads up to len bytes of data from the input stream into an array of
  2733. bytes. An attempt is made to read as many as len bytes, but a
  2734. smaller number may be read, possibly zero. The number of bytes
  2735. actually read is returned as an integer.
  2736. Which makes sense with the timeout documentation.
  2737. <snip>threshold comment I'll look at that next. I thought those changes
  2738. where in the ifdefed code. I'll take a second look and reply.
  2739. >
  2740. > Thoughts? Comments?
  2741. >
  2742. > Bill
  2743. >
  2744. > ----------------------
  2745. >
  2746. > public abstract InputStream getInputStream() throws IOException
  2747. >
  2748. >
  2749. > Returns an input stream. This is the only way to receive data from the
  2750. communications
  2751. > port. If the port is unidirectional and doesn't support receiving data, then
  2752. > getInputStream returns null.
  2753. >
  2754. > The read behaviour of the input stream returned by getInputStream depends on
  2755. > combination of the threshold and timeout values. The possible behaviours are
  2756. > described in the table below:
  2757. >
  2758. >
  2759. > Threshold Timeout Read Buffer Read Behaviour
  2760. > State Value State Value Size
  2761. >
  2762. -----------------------------------------------------------------------------------
  2763. > disabled - disabled - n bytes block until any data is available
  2764. >
  2765. > enabled m bytes disabled - n bytes block until min(m,n) bytes are available
  2766. >
  2767. > disabled - enabled x ms n bytes block for x ms or
  2768. until any data is available
  2769. >
  2770. > enabled m bytes enabled x ms n bytes block for x ms or
  2771. until min(m,n) bytes are available
  2772. >
  2773. > Returns: InputStream object that can be used to read from the port
  2774. >
  2775. > Throws: IOException if an I/O error occurred
  2776. ----------------------------------------------------------*/
  2777. jint gnu::io::RXTXPort::readByte(
  2778. )
  2779. {
  2780. int bytes;
  2781. unsigned char buffer[ 1 ];
  2782. int fd = ( int ) this->fd;
  2783. int timeout = ( int ) this->timeout;
  2784. char msg[80];
  2785. ENTER( "RXTXPort:readByte" );
  2786. report_time_start( );
  2787. bytes = read_byte_array( fd, buffer, 1, timeout );
  2788. if( bytes < 0 ) {
  2789. LEAVE( "RXTXPort:readByte" );
  2790. snprintf( msg, 79, "%s%s", strerror( errno ), " in readByte" );
  2791. throw new java::io::IOException( JvNewStringUTF( msg ) );
  2792. return -1;
  2793. }
  2794. LEAVE( "RXTXPort:readByte" );
  2795. sprintf( msg, "readByte return(%i)\n", bytes ? buffer[ 0 ] : -1 );
  2796. report( msg );
  2797. report_time_end( );
  2798. return (bytes ? (jint)buffer[ 0 ] : -1);
  2799. }
  2800. /*----------------------------------------------------------
  2801. RXTXPort.readArray
  2802. accept: offset (offset to start storing data in the jbarray) and
  2803. Length (bytes to read)
  2804. perform: read bytes from the port into a byte array
  2805. return: bytes read on success
  2806. 0 on read timeout
  2807. exceptions: IOException
  2808. comments: throws ArrayIndexOutOfBoundsException if asked to
  2809. read more than SSIZE_MAX bytes
  2810. ----------------------------------------------------------*/
  2811. jint gnu::io::RXTXPort::readArray(
  2812. jbyteArray jbarray,
  2813. jint offset,
  2814. jint length
  2815. )
  2816. {
  2817. int bytes;
  2818. char msg[80];
  2819. int fd = ( int ) this->fd;
  2820. int timeout = ( int ) this->timeout;
  2821. jbyte *in = elements( jbarray ) + offset;
  2822. ENTER( "readArray" );
  2823. report_time_start( );
  2824. if( length > SSIZE_MAX || length < 0 ) {
  2825. report( "RXTXPort:readArray length > SSIZE_MAX" );
  2826. LEAVE( "RXTXPort:readArray" );
  2827. snprintf( msg, 79, "%s%s", "Invalid length", " in readArray" );
  2828. throw new java::lang::ArrayIndexOutOfBoundsException( JvNewStringUTF( msg ) );
  2829. return -1;
  2830. }
  2831. bytes = read_byte_array( fd, (unsigned char *) in, length, timeout );/* dima */
  2832. if( bytes < 0 ) {
  2833. report( "RXTXPort:readArray bytes < 0" );
  2834. LEAVE( "RXTXPort:readArray" );
  2835. snprintf( msg, 79, "%s%s", strerror( errno ), " in readArray" );
  2836. throw new java::io::IOException( JvNewStringUTF( msg ) );
  2837. return -1;
  2838. }
  2839. sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
  2840. report( msg );
  2841. report_time_end( );
  2842. LEAVE( "RXTXPort:readArray" );
  2843. return (bytes);
  2844. }
  2845. /*----------------------------------------------------------
  2846. RXTXPort.nativeavailable
  2847. accept: none
  2848. perform: find out the number of bytes available for reading
  2849. return: available bytes
  2850. -1 on error
  2851. exceptions: none
  2852. ----------------------------------------------------------*/
  2853. jint gnu::io::RXTXPort::nativeavailable(
  2854. )
  2855. {
  2856. int fd = ( int ) this->fd;
  2857. int result;
  2858. char msg[80];
  2859. /*
  2860. ENTER( "RXTXPort:nativeavailable" );
  2861. On SCO OpenServer FIONREAD always fails for serial devices,
  2862. so try ioctl FIORDCHK instead; will only tell us whether
  2863. bytes are available, not how many, but better than nothing.
  2864. This turns out to be true on Solaris also. taj.
  2865. */
  2866. #ifdef FIORDCHK /* __unixware__ __sun__ probably others */
  2867. result = ioctl(fd, FIORDCHK, 0);
  2868. #else
  2869. if( ioctl( fd, FIONREAD, &result ) < 0 )
  2870. {
  2871. goto fail;
  2872. }
  2873. #endif /* FIORDCHK */
  2874. sprintf(msg, " nativeavailable: FIORDCHK result %d, \
  2875. errno %d\n", result , result == -1 ? errno : 0);
  2876. report_verbose( msg );
  2877. if (result == -1) {
  2878. goto fail;
  2879. }
  2880. if( result )
  2881. {
  2882. sprintf(msg, " nativeavailable: FIORDCHK result %d, \
  2883. errno %d\n", result , result == -1 ? errno : 0);
  2884. report( msg );
  2885. }
  2886. /*
  2887. LEAVE( "RXTXPort:nativeavailable" );
  2888. */
  2889. return (jint)result;
  2890. fail:
  2891. report("RXTXPort:nativeavailable: ioctl() failed\n");
  2892. /*
  2893. LEAVE( "RXTXPort:nativeavailable" );
  2894. */
  2895. snprintf( msg, 79, "%s%s", strerror( errno ), " in nativeavailable" );
  2896. throw new java::io::IOException( JvNewStringUTF( msg ) );
  2897. return (jint)result;
  2898. }
  2899. /*----------------------------------------------------------
  2900. RXTXPort.setflowcontrol
  2901. accept: flowmode
  2902. FLOWCONTROL_NONE none
  2903. FLOWCONTROL_RTSCTS_IN hardware flow control
  2904. FLOWCONTROL_RTSCTS_OUT ""
  2905. FLOWCONTROL_XONXOFF_IN input software flow control
  2906. FLOWCONTROL_XONXOFF_OUT output software flow control
  2907. perform: set flow control to flowmode
  2908. return: none
  2909. exceptions: UnsupportedCommOperationException
  2910. comments: there is no differentiation between input and output hardware
  2911. flow control
  2912. ----------------------------------------------------------*/
  2913. void gnu::io::RXTXPort::setflowcontrol(
  2914. jint flowmode
  2915. )
  2916. {
  2917. struct termios ttyset;
  2918. int fd = ( int ) this->fd;
  2919. char msg[80];
  2920. ENTER( "RXTXPort:setflowcontrol" );
  2921. if( tcgetattr( fd, &ttyset ) ) goto fail;
  2922. if ( flowmode & ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT ) )
  2923. {
  2924. ttyset.c_cflag |= HARDWARE_FLOW_CONTROL;
  2925. }
  2926. else ttyset.c_cflag &= ~HARDWARE_FLOW_CONTROL;
  2927. ttyset.c_iflag &= ~IXANY;
  2928. if ( flowmode & FLOWCONTROL_XONXOFF_IN )
  2929. {
  2930. ttyset.c_iflag |= IXOFF;
  2931. }
  2932. else ttyset.c_iflag &= ~IXOFF;
  2933. if ( flowmode & FLOWCONTROL_XONXOFF_OUT )
  2934. {
  2935. ttyset.c_iflag |= IXON;
  2936. }
  2937. else ttyset.c_iflag &= ~IXON;
  2938. /* TRENT */
  2939. if( tcsetattr( fd, TCSANOW, &ttyset ) ) goto fail;
  2940. LEAVE( "RXTXPort:setflowcontrol" );
  2941. return;
  2942. fail:
  2943. LEAVE( "RXTXPort:setflowcontrol" );
  2944. snprintf( msg, 79, "%s%s", "flow control type not supported", " in setflowcontrol" );
  2945. throw new java::io::IOException( JvNewStringUTF( msg ) );
  2946. return;
  2947. }
  2948. /*----------------------------------------------------------
  2949. unlock_monitor_thread
  2950. accept: event_info_struct
  2951. perform: unlock the monitor thread so event notification can start.
  2952. return: none
  2953. exceptions: none
  2954. comments: Events can be missed otherwise.
  2955. ----------------------------------------------------------*/
  2956. void unlock_monitor_thread( gnu::io::RXTXPort *p, struct event_info_struct *eis )
  2957. {
  2958. p->MonitorThreadLock = false;
  2959. }
  2960. /*----------------------------------------------------------
  2961. check_line_status_register
  2962. accept: event_info_struct
  2963. perform: check for changes on the LSR
  2964. return: 0 on success
  2965. exceptions: none
  2966. comments: not supported on all devices/drivers.
  2967. ----------------------------------------------------------*/
  2968. int check_line_status_register( gnu::io::RXTXPort *p, struct event_info_struct *eis )
  2969. {
  2970. #ifdef TIOCSERGETLSR
  2971. struct stat fstatbuf;
  2972. if( ! eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
  2973. {
  2974. report( "check_line_status_registe OUPUT_BUFFER_EMPTY not set\n" );
  2975. return 0;
  2976. }
  2977. if ( fstat( eis->fd, &fstatbuf ) )
  2978. {
  2979. report( "check_line_status_register: fstat\n" );
  2980. return( 1 );
  2981. }
  2982. if( ioctl( eis->fd, TIOCSERGETLSR, &eis->change ) )
  2983. {
  2984. report( "check_line_status_register: TIOCSERGETLSR\n is nonnull\n" );
  2985. return( 1 );
  2986. }
  2987. else if( eis && eis->change )
  2988. {
  2989. report_verbose( "check_line_status_register: sending OUTPUT_BUFFER_EMPTY\n" );
  2990. send_event( p, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
  2991. }
  2992. #else
  2993. /*
  2994. printf("test %i\n", eis->output_buffer_empty_flag );
  2995. */
  2996. if( eis && eis->output_buffer_empty_flag == 1 &&
  2997. eis->eventflags[SPE_OUTPUT_BUFFER_EMPTY] )
  2998. {
  2999. report_verbose("check_line_status_register: sending SPE_OUTPUT_BUFFER_EMPTY\n");
  3000. send_event( p, eis, SPE_OUTPUT_BUFFER_EMPTY, 1 );
  3001. /*
  3002. send_event( this, eis, SPE_DATA_AVAILABLE, 1 );
  3003. */
  3004. eis->output_buffer_empty_flag = 0;
  3005. }
  3006. #endif /* TIOCSERGETLSR */
  3007. return( 0 );
  3008. }
  3009. /*----------------------------------------------------------
  3010. has_line_status_register_access
  3011. accept: fd of interest
  3012. perform: check for access to the LSR
  3013. return: 0 if not available
  3014. exceptions: none
  3015. comments: not supported on all devices/drivers.
  3016. JK00: work around for multiport cards without TIOCSERGETLSR
  3017. Cyclades is one of those :-(
  3018. ----------------------------------------------------------*/
  3019. int has_line_status_register_access( int fd )
  3020. {
  3021. #if defined(TIOCSERGETLSR)
  3022. int change;
  3023. if( !ioctl( fd, TIOCSERGETLSR, &change ) ) {
  3024. return(1);
  3025. }
  3026. #endif /* TIOCSERGETLSR */
  3027. report( "has_line_status_register_acess: Port does not support TIOCSERGETLSR\n" );
  3028. return( 0 );
  3029. }
  3030. /*----------------------------------------------------------
  3031. check_cgi_count
  3032. accept: fd of interest
  3033. perform: check for access to TIOCGICOUNT
  3034. return: 0 if not available
  3035. exceptions: none
  3036. comments: not supported on all devices/drivers.
  3037. * wait for RNG, DSR, CD or CTS but not DataAvailable
  3038. * The drawback here is it never times out so if someone
  3039. * reads there will be no chance to try again.
  3040. * This may make sense if the program does not want to
  3041. * be notified of data available or errors.
  3042. * ret=ioctl(fd,TIOCMIWAIT);
  3043. ----------------------------------------------------------*/
  3044. void check_cgi_count( gnu::io::RXTXPort *p, struct event_info_struct *eis )
  3045. {
  3046. #if defined(TIOCGICOUNT)
  3047. /* JK00: only use it if supported by this port */
  3048. struct serial_icounter_struct sis;
  3049. memcpy( &sis, &eis->osis, sizeof( struct serial_icounter_struct ) );
  3050. if( ioctl( eis->fd, TIOCGICOUNT, &sis ) )
  3051. {
  3052. report( "check_cgi_count: TIOCGICOUNT\n is not 0\n" );
  3053. return;
  3054. }
  3055. while( eis && sis.frame != eis->osis.frame ) {
  3056. send_event( p, eis, SPE_FE, 1);
  3057. eis->osis.frame++;
  3058. }
  3059. while( eis && sis.overrun != eis->osis.overrun ) {
  3060. send_event( p, eis, SPE_OE, 1);
  3061. eis->osis.overrun++;
  3062. }
  3063. while( eis && sis.parity != eis->osis.parity ) {
  3064. send_event( p, eis, SPE_PE, 1);
  3065. eis->osis.parity++;
  3066. }
  3067. while( eis && sis.brk != eis->osis.brk ) {
  3068. send_event( p, eis, SPE_BI, 1);
  3069. eis->osis.brk++;
  3070. }
  3071. if( eis )
  3072. memcpy( &eis->osis, &sis, sizeof( struct serial_icounter_struct ) );
  3073. #endif /* TIOCGICOUNT */
  3074. }
  3075. /*----------------------------------------------------------
  3076. port_has_changed_fionread
  3077. accept: fd of interest
  3078. perform: check if FIONREAD has changed
  3079. return: 0 if no data available
  3080. exceptions: none
  3081. comments:
  3082. ----------------------------------------------------------*/
  3083. int port_has_changed_fionread( struct event_info_struct *eis )
  3084. {
  3085. int change, rc;
  3086. char message[80];
  3087. rc = ioctl( eis->fd, FIONREAD, &change );
  3088. sprintf( message, "port_has_changed_fionread: change is %i ret is %i\n", change, eis->ret );
  3089. #if defined(__unixware__) || defined(__sun__)
  3090. /*
  3091. On SCO OpenServer FIONREAD always fails for serial devices,
  3092. so rely upon select() result to know whether data available.
  3093. This is true for Solaris, also. taj.
  3094. */
  3095. if( (rc != -1 && change) || (rc == -1 && eis->ret > 0) )
  3096. return( 1 );
  3097. #else
  3098. sprintf( message, "port_has_changed_fionread: change is %i\n", change );
  3099. report_verbose( message );
  3100. if( change )
  3101. return( 1 );
  3102. #endif /* __unixware__ || __sun__ */
  3103. return( 0 );
  3104. }
  3105. /*----------------------------------------------------------
  3106. check_tiocmget_changes
  3107. accept: event_info_struct
  3108. perform: use TIOCMGET to report events
  3109. return: none
  3110. exceptions: none
  3111. comments: not supported on all devices/drivers.
  3112. ----------------------------------------------------------*/
  3113. void check_tiocmget_changes( gnu::io::RXTXPort *p, struct event_info_struct * eis )
  3114. {
  3115. unsigned int mflags = 0;
  3116. int change;
  3117. /* DORITO */
  3118. if( !eis ) return;
  3119. change = eis->change;
  3120. report_verbose("entering check_tiocmget_changes\n");
  3121. if( ioctl( eis->fd, TIOCMGET, &mflags ) )
  3122. {
  3123. report( "=======================================\n");
  3124. report( "check_tiocmget_changes: ioctl(TIOCMGET)\n" );
  3125. return;
  3126. }
  3127. change = (mflags&TIOCM_CTS) - (eis->omflags&TIOCM_CTS);
  3128. if( eis && change ) send_event( p, eis, SPE_CTS, change );
  3129. change = (mflags&TIOCM_DSR) - (eis->omflags&TIOCM_DSR);
  3130. if( eis && change )
  3131. {
  3132. report( "sending DSR ===========================\n");
  3133. send_event( p, eis, SPE_DSR, change );
  3134. }
  3135. change = (mflags&TIOCM_RNG) - (eis->omflags&TIOCM_RNG);
  3136. if( eis && change ) send_event( p, eis, SPE_RI, change );
  3137. change = (mflags&TIOCM_CD) - (eis->omflags&TIOCM_CD);
  3138. if( eis && change ) send_event( p, eis, SPE_CD, change );
  3139. if( eis )
  3140. eis->omflags = mflags;
  3141. report_verbose("leaving check_tiocmget_changes\n");
  3142. }
  3143. /*----------------------------------------------------------
  3144. system_wait
  3145. accept:
  3146. perform:
  3147. return:
  3148. exceptions: none
  3149. comments:
  3150. ----------------------------------------------------------*/
  3151. void system_wait()
  3152. {
  3153. #if defined (__sun__ )
  3154. struct timespec retspec, tspec;
  3155. retspec.tv_sec = 0;
  3156. retspec.tv_nsec = 100000000;
  3157. do {
  3158. tspec = retspec;
  3159. nanosleep( &tspec, &retspec );
  3160. } while( tspec.tv_nsec != 0 );
  3161. /* Trent
  3162. */
  3163. #else
  3164. #ifdef TRENT_IS_HERE_DEBUGGING_THREADS
  3165. /* On NT4 The following was observed in a intense test:
  3166. 50000 95% 179 sec
  3167. 200000 95% 193 sec
  3168. 1000000 95% 203 sec some callback failures sometimes.
  3169. 2000000 0-95% callback failures.
  3170. */
  3171. #endif /* TRENT_IS_HERE_DEBUGGING_THREADS */
  3172. #endif /* __sun__ */
  3173. }
  3174. /*----------------------------------------------------------
  3175. driver_has_tiocgicount
  3176. accept: fd of interest
  3177. perform: check for access to TIOCGICOUNT
  3178. return: 0 if not available
  3179. exceptions: none
  3180. comments: not supported on all devices/drivers.
  3181. Some multiport serial cards do not implement TIOCGICOUNT ...
  3182. So use the 'dumb' mode to enable using them after all! JK00
  3183. ----------------------------------------------------------*/
  3184. int driver_has_tiocgicount( struct event_info_struct * eis )
  3185. {
  3186. #if defined(TIOCGICOUNT)
  3187. /* Some multiport serial cards do not implement TIOCGICOUNT ... */
  3188. /* So use the 'dumb' mode to enable using them after all! JK00 */
  3189. if( ioctl( eis->fd, TIOCGICOUNT, &eis->osis ) < 0 ) {
  3190. report_verbose( " driver_has_tiocgicount: Port does not support TIOCGICOUNT events\n" );
  3191. return(0);
  3192. }
  3193. else
  3194. return(1);
  3195. #endif /* TIOCGICOUNT */
  3196. return(0);
  3197. }
  3198. /*----------------------------------------------------------
  3199. report_serial_events
  3200. accept: event_info_struct
  3201. perform: send events if they occured
  3202. return: 0 if not available
  3203. exceptions: none
  3204. comments: not supported on all devices/drivers.
  3205. ----------------------------------------------------------*/
  3206. void report_serial_events( gnu::io::RXTXPort *p, struct event_info_struct *eis )
  3207. {
  3208. /* JK00: work around for Multi IO cards without TIOCSERGETLSR */
  3209. /* if( eis->has_tiocsergetlsr ) we have a fix for output empty */
  3210. if( check_line_status_register( p, eis ) )
  3211. return;
  3212. #ifndef WIN32 /* something is wrong here */
  3213. if ( eis && eis->has_tiocgicount )
  3214. check_cgi_count( p, eis );
  3215. #endif /* WIN32 */
  3216. check_tiocmget_changes( p, eis );
  3217. if( eis && port_has_changed_fionread( eis ) )
  3218. {
  3219. if(!eis->eventflags[SPE_DATA_AVAILABLE] )
  3220. {
  3221. report_verbose("report_serial_events: ignoring DATA_AVAILABLE\n");
  3222. /*
  3223. report(".");
  3224. */
  3225. #if !defined(__sun__)
  3226. /* FIXME: No time to test on all OS's for production */
  3227. usleep(20000);
  3228. #endif /* !__sun__ */
  3229. return;
  3230. }
  3231. report("report_serial_events: sending DATA_AVAILABLE\n");
  3232. if(!send_event( p, eis, SPE_DATA_AVAILABLE, 1 ))
  3233. {
  3234. /* select wont block */
  3235. #if !defined(__sun__)
  3236. /* FIXME: No time to test on all OS's for production */
  3237. usleep(20000);
  3238. #endif /* !__sun__ */
  3239. /*
  3240. system_wait();
  3241. */
  3242. }
  3243. }
  3244. }
  3245. /*----------------------------------------------------------
  3246. initialise_event_info_struct
  3247. accept: event_info_struct for this thread.
  3248. perform: initialise or reset the event_info_struct
  3249. return: 1 on success
  3250. exceptions: none
  3251. comments:
  3252. ----------------------------------------------------------*/
  3253. int initialise_event_info_struct( gnu::io::RXTXPort *p, struct event_info_struct *eis )
  3254. {
  3255. int i;
  3256. struct event_info_struct *index = master_index;
  3257. if ( eis->initialised == 1 )
  3258. goto end;
  3259. #ifdef TIOCGICOUNT
  3260. memset(&eis->osis,0,sizeof(eis->osis));
  3261. #endif /* TIOCGICOUNT */
  3262. if( index )
  3263. {
  3264. while( index->next )
  3265. {
  3266. index = index->next;
  3267. }
  3268. index->next = eis;
  3269. eis->prev = index;
  3270. eis->next = NULL;
  3271. }
  3272. else
  3273. {
  3274. master_index = eis;
  3275. master_index->next = NULL;
  3276. master_index->prev = NULL;
  3277. }
  3278. for( i = 0; i < 11; i++ ) eis->eventflags[i] = 0;
  3279. #if !defined(TIOCSERGETLSR) && !defined(WIN32)
  3280. eis->output_buffer_empty_flag = 0;
  3281. eis->writing = 0;
  3282. #endif /* TIOCSERGETLSR */
  3283. eis->eventloop_interrupted = 0;
  3284. eis->closing = 0;
  3285. eis->fd = ( int ) p->fd;
  3286. eis->has_tiocsergetlsr = has_line_status_register_access( eis->fd );
  3287. eis->has_tiocgicount = driver_has_tiocgicount( eis );
  3288. if( ioctl( eis->fd, TIOCMGET, &eis->omflags) < 0 ) {
  3289. report( "initialise_event_info_struct: Port does not support events\n" );
  3290. }
  3291. end:
  3292. FD_ZERO( &eis->rfds );
  3293. FD_SET( eis->fd, &eis->rfds );
  3294. eis->tv_sleep.tv_sec = 0;
  3295. eis->tv_sleep.tv_usec = 1000;
  3296. eis->initialised = 1;
  3297. return( 1 );
  3298. }
  3299. /*----------------------------------------------------------
  3300. finalize_event_info_struct
  3301. accept: event_info_struct for this thread.
  3302. perform: free resources
  3303. return: none
  3304. exceptions: none
  3305. comments:
  3306. ----------------------------------------------------------*/
  3307. void finalize_event_info_struct( struct event_info_struct *eis )
  3308. {
  3309. if( eis->next && eis->prev )
  3310. {
  3311. eis->prev->next = eis->next;
  3312. eis->next->prev = eis->prev;
  3313. }
  3314. else if( eis->next )
  3315. {
  3316. eis->next->prev = NULL;
  3317. master_index = eis->next;
  3318. }
  3319. else if( eis->prev )
  3320. eis->prev->next = NULL;
  3321. else master_index = NULL;
  3322. }
  3323. /*----------------------------------------------------------
  3324. RXTXPort.eventLoop
  3325. accept: none
  3326. perform: periodically check for SerialPortEvents
  3327. return: none
  3328. exceptions: none
  3329. comments: please keep this function clean.
  3330. ----------------------------------------------------------*/
  3331. void gnu::io::RXTXPort::eventLoop(
  3332. )
  3333. {
  3334. struct event_info_struct eis;
  3335. eis.initialised = 0;
  3336. ENTER( "eventLoop\n" );
  3337. if ( !initialise_event_info_struct( this, &eis ) ) goto end;
  3338. if ( !init_threads( this, &eis ) ) goto end;
  3339. unlock_monitor_thread( this, &eis );
  3340. do{
  3341. report_time_eventLoop( );
  3342. do {
  3343. /* report( "." ); */
  3344. eis.ret = SELECT( eis.fd + 1, &eis.rfds, NULL, NULL,
  3345. &eis.tv_sleep );
  3346. /* nothing goes between this call and select */
  3347. if( eis.closing )
  3348. {
  3349. report("eventLoop: got interrupt\n");
  3350. finalize_threads( &eis );
  3351. finalize_event_info_struct( &eis );
  3352. this->MonitorThreadCloseLock = false;
  3353. LEAVE("eventLoop");
  3354. return;
  3355. }
  3356. usleep(20000);
  3357. /*
  3358. Trent system_wait();
  3359. */
  3360. } while ( eis.ret < 0 && errno == EINTR );
  3361. if( eis.ret >= 0 )
  3362. {
  3363. report_serial_events( this, &eis );
  3364. }
  3365. initialise_event_info_struct( this, &eis );
  3366. } while( 1 );
  3367. end:
  3368. LEAVE( "eventLoop: Bailing!\n" );
  3369. }
  3370. /*----------------------------------------------------------
  3371. RXTXCommDriver.nativeGetVersion
  3372. accept: none
  3373. perform: return the current version
  3374. return: version
  3375. exceptions: none
  3376. comments: This is used to avoid mixing versions of the .jar and
  3377. native library.
  3378. First introduced in rxtx-1.5-9
  3379. ----------------------------------------------------------*/
  3380. jstring gnu::io::RXTXCommDriver::nativeGetVersion (
  3381. )
  3382. {
  3383. return JvNewStringUTF( "RXTX-2.1-7" );
  3384. }
  3385. /*----------------------------------------------------------
  3386. RXTXCommDriver.testRead
  3387. accept: jstr The device to be tested
  3388. perform: test if the device can be read from
  3389. return: true if the device can be read from
  3390. exceptions: none
  3391. comments: From Wayne Roberts wroberts1@home.com
  3392. check tcget/setattr returns.
  3393. support for non serial ports Trent
  3394. ----------------------------------------------------------*/
  3395. jboolean gnu::io::RXTXCommDriver::testRead(
  3396. jstring jstr,
  3397. jint port_type
  3398. )
  3399. {
  3400. struct termios ttyset;
  3401. char c;
  3402. int i, fd, ret = true, pid = -1;
  3403. //char filename[80];
  3404. char filename[80];
  3405. #ifdef TRENT_IS_HERE_DEBUGGING_ENUMERATION
  3406. char message[80];
  3407. #endif /* TRENT_IS_HERE_DEBUGGING_ENUMERATION */
  3408. for( i=0;i<jstr->length();i++)
  3409. filename[i] = jstr->charAt(i);
  3410. filename[i] = '\0';
  3411. //java::lang::System::out->println( filename );
  3412. //const char *filename = (const char *) jstr->toCharArray();
  3413. /* We opened the file in this thread, use this pid to unlock */
  3414. //java::lang::System::out->println( jstr );
  3415. #ifndef WIN32
  3416. pid = getpid();
  3417. #else
  3418. char full_windows_name[80];
  3419. #endif /* WIN32 */
  3420. ENTER( "RXTXPort:testRead" );
  3421. //printf( "RXTXCommDriver::testRead( %s )\n", filename );
  3422. #ifdef TRENT_IS_HERE_DEBUGGING_ENUMERATION
  3423. /* vmware lies about which ports are there causing irq conflicts */
  3424. /* this is for testing only */
  3425. if( !strcmp( filename, "COM1" ) || !strcmp( filename, "COM2") )
  3426. {
  3427. printf("%s is good\n",filename);
  3428. sprintf( message, "testRead: %s is good!\n", filename );
  3429. report( message );
  3430. return( true );
  3431. }
  3432. return( false );
  3433. #endif /* TRENT_IS_HERE_DEBUGGING_ENUMERATION */
  3434. #ifdef WIN32
  3435. strcpy( full_windows_name, DEVICEDIR );
  3436. strcat( full_windows_name, filename );
  3437. ret = serial_test((char *) full_windows_name );
  3438. return(ret);
  3439. #endif /* WIN32 */
  3440. /*
  3441. LOCK is one of three functions defined in SerialImp.h
  3442. uucp_lock Solaris
  3443. fhs_lock Linux
  3444. system_does_not_lock Win32
  3445. */
  3446. //printf( "RXTXCommDriver::testRead( %s )\n", filename );
  3447. if ( LOCK( filename, pid ) )
  3448. {
  3449. LEAVE( "RXTXPort:testRead no lock" );
  3450. return false;
  3451. }
  3452. /*
  3453. CLOCAL eliminates open blocking on modem status lines
  3454. -- changed to O_NONBLOCK
  3455. */
  3456. do {
  3457. fd=::OPEN ( filename, O_RDWR | O_NOCTTY | O_NONBLOCK );
  3458. } while ( fd < 0 && errno==EINTR );
  3459. if( fd < 0 )
  3460. {
  3461. report_verbose( "testRead() open failed\n" );
  3462. ret = false;
  3463. goto END;
  3464. }
  3465. if ( port_type == PORT_SERIAL )
  3466. {
  3467. int saved_flags;
  3468. struct termios saved_termios;
  3469. if (tcgetattr(fd, &ttyset) < 0) {
  3470. ret = false;
  3471. goto END;
  3472. }
  3473. /* save, restore later */
  3474. if ( ( saved_flags = fcntl(fd, F_GETFL ) ) < 0 )
  3475. {
  3476. report( "testRead() fcntl(F_GETFL) failed\n" );
  3477. ret = false;
  3478. goto END;
  3479. }
  3480. memcpy( &saved_termios, &ttyset, sizeof( struct termios ) );
  3481. if ( fcntl( fd, F_SETFL, O_NONBLOCK ) < 0 )
  3482. {
  3483. report( "testRead() fcntl(F_SETFL) failed\n" );
  3484. ret = false;
  3485. goto END;
  3486. }
  3487. cfmakeraw(&ttyset);
  3488. ttyset.c_cc[VMIN] = ttyset.c_cc[VTIME] = 0;
  3489. if ( tcsetattr( fd, TCSANOW, &ttyset) < 0 )
  3490. {
  3491. report( "testRead() tcsetattr failed\n" );
  3492. ret = false;
  3493. tcsetattr( fd, TCSANOW, &saved_termios );
  3494. goto END;
  3495. }
  3496. /*
  3497. The following may mess up if both EAGAIN and EWOULDBLOCK
  3498. are defined but only EWOULDBLOCK is used
  3499. Linux:
  3500. man 2 open
  3501. O_NONBLOCK or O_NDELAY
  3502. When possible, the file is opened in non-blocking
  3503. mode. Neither the open nor any subsequent opera
  3504. tions on the file descriptor which is returned will
  3505. cause the calling process to wait. For the han
  3506. dling of FIFOs (named pipes), see also fifo(4).
  3507. This mode need not have any effect on files other
  3508. than FIFOs.
  3509. man 2 read
  3510. EAGAIN
  3511. Non-blocking I/O has been selected using O_NONBLOCK
  3512. and no data was immediately available for reading.
  3513. /usr/include/asm/error.h:
  3514. #define EAGAIN 11 / Try again /
  3515. #define EWOULDBLOCK EAGAIN / Operation would block /
  3516. looks like the kernel is using EAGAIN
  3517. -- should be OK
  3518. Solaris:
  3519. man 2 open
  3520. EAGAIN The path argument names the slave side of a
  3521. pseudo-terminal device that is locked.
  3522. man 2 read
  3523. If O_NONBLOCK is set, read() returns -1 and sets errno
  3524. to EAGAIN.
  3525. -- should be OK.
  3526. HP-UX
  3527. both are defined but EAGAIN is used.
  3528. -- should be OK.
  3529. Win32
  3530. neither errno is currently set. Comment added to termios.c
  3531. serial_open().
  3532. -- should be OK
  3533. Steven's book. Advanced programming in the Unix Environment pg 364
  3534. "A common use for nonblocking I/O is for dealing with a terminal device
  3535. for a network connection and these devices are normally used by one process
  3536. at a time. This means that the change in the BSD semantics normally does 't
  3537. effect us. The different error return, EWOULDBLOCK, instead of POSIX.1
  3538. EAGAIN, continues to be a portability difference that we must deal with."
  3539. */
  3540. if ( READ( fd, &c, 1 ) < 0 )
  3541. {
  3542. #ifdef EAGAIN
  3543. if ( errno != EAGAIN ) {
  3544. report( "testRead() read failed\n" );
  3545. ret = false;
  3546. }
  3547. #else
  3548. #ifdef EWOULDBLOCK
  3549. if ( errno != EWOULDBLOCK )
  3550. {
  3551. report( "testRead() read failed\n" );
  3552. ret = false;
  3553. }
  3554. #else
  3555. ret = false;
  3556. #endif /* EWOULDBLOCK */
  3557. #endif /* EAGAIN */
  3558. }
  3559. /* dont walk over unlocked open devices */
  3560. tcsetattr( fd, TCSANOW, &saved_termios );
  3561. fcntl( fd, F_SETFL, saved_flags );
  3562. }
  3563. /*
  3564. UNLOCK is one of three functions defined in SerialImp.h
  3565. uucp_unlock Solaris
  3566. fhs_unlock Linux
  3567. system_does_not_unlock Win32
  3568. */
  3569. END:
  3570. UNLOCK(filename, pid );
  3571. ::CLOSE( fd );
  3572. LEAVE( "RXTXPort:testRead" );
  3573. return ret;
  3574. }
  3575. #if defined(__APPLE__)
  3576. /*----------------------------------------------------------
  3577. createSerialIterator()
  3578. accept:
  3579. perform:
  3580. return:
  3581. exceptions:
  3582. comments:
  3583. Code courtesy of Eric Welch at Keyspan, except for the bugs
  3584. which are courtesy of Joseph Goldstone (joseph@lp.com)
  3585. ----------------------------------------------------------*/
  3586. kern_return_t
  3587. createSerialIterator(io_iterator_t *serialIterator)
  3588. {
  3589. kern_return_t kernResult;
  3590. mach_port_t masterPort;
  3591. CFMutableDictionaryRef classesToMatch;
  3592. if ((kernResult=IOMasterPort(NULL, &masterPort)) != KERN_SUCCESS)
  3593. {
  3594. printf( "IOMasterPort returned %d\n", kernResult);
  3595. return kernResult;
  3596. }
  3597. if ((classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue)) == NULL)
  3598. {
  3599. printf( "IOServiceMatching returned NULL\n" );
  3600. return kernResult;
  3601. }
  3602. CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
  3603. kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, serialIterator);
  3604. if (kernResult != KERN_SUCCESS)
  3605. {
  3606. printf( "IOServiceGetMatchingServices returned %d\n", kernResult);
  3607. }
  3608. return kernResult;
  3609. }
  3610. /*----------------------------------------------------------
  3611. getRegistryString()
  3612. accept:
  3613. perform:
  3614. return:
  3615. exceptions:
  3616. comments:
  3617. Code courtesy of Eric Welch at Keyspan, except for the bugs
  3618. which are courtesy of Joseph Goldstone (joseph@lp.com)
  3619. ----------------------------------------------------------*/
  3620. char *
  3621. getRegistryString(io_object_t sObj, char *propName)
  3622. {
  3623. static char resultStr[256];
  3624. CFTypeRef nameCFstring;
  3625. resultStr[0] = 0;
  3626. nameCFstring = IORegistryEntryCreateCFProperty(sObj,
  3627. CFStringCreateWithCString(kCFAllocatorDefault, propName, kCFStringEncodingASCII),
  3628. kCFAllocatorDefault, 0);
  3629. if (nameCFstring)
  3630. {
  3631. CFStringGetCString(nameCFstring, resultStr, sizeof(resultStr), kCFStringEncodingASCII);
  3632. CFRelease(nameCFstring);
  3633. }
  3634. return resultStr;
  3635. }
  3636. /*----------------------------------------------------------
  3637. registerKnownSerialPorts()
  3638. accept:
  3639. perform:
  3640. return:
  3641. exceptions:
  3642. comments:
  3643. ----------------------------------------------------------*/
  3644. int
  3645. registerKnownSerialPorts(
  3646. jint portType
  3647. ) /* dima */
  3648. {
  3649. io_iterator_t theSerialIterator;
  3650. io_object_t theObject;
  3651. int numPorts = 0;/* dima it should initiated */
  3652. if (createSerialIterator(&theSerialIterator) != KERN_SUCCESS)
  3653. {
  3654. printf( "createSerialIterator failed\n" );
  3655. } else {
  3656. while (theObject = IOIteratorNext(theSerialIterator))
  3657. {
  3658. /* begin dima taj got this close for gcj */
  3659. jstring tempJstring;
  3660. tempJstring = JvNewStringUTF(getRegistryString(theObject, kIODialinDeviceKey));
  3661. gnu::io::ComPortIdentifier->addPortName(tempJstring,portType,this);/* dima */
  3662. numPorts++;
  3663. tempJstring = JvNewStringUTF(getRegistryString(theObject, kIOCalloutDeviceKey));
  3664. gnu::io::ComPortIdentifier->addPortName(tempJstring,portType,this);/* dima */
  3665. numPorts++;
  3666. /* end dima taj got this close for gcj */
  3667. }
  3668. }
  3669. }
  3670. return numPorts;
  3671. }
  3672. #endif /* __APPLE__ */
  3673. /*----------------------------------------------------------
  3674. registerKnownPorts
  3675. accept: the type of port
  3676. perform: register any ports of the desired type a priori known to this OS
  3677. return: true if any such ports were registered otherwise false
  3678. exceptions: none
  3679. comments:
  3680. ----------------------------------------------------------*/
  3681. jboolean gnu::io::RXTXCommDriver::registerKnownPorts(
  3682. jint portType
  3683. )
  3684. {
  3685. enum {PORT_TYPE_SERIAL = 1,
  3686. PORT_TYPE_PARALLEL,
  3687. PORT_TYPE_I2C,
  3688. PORT_TYPE_RS485,
  3689. PORT_TYPE_RAW};
  3690. jboolean result = false;
  3691. char message[80];
  3692. switch(portType) {
  3693. case PORT_TYPE_SERIAL:
  3694. #if defined(__APPLE__)
  3695. if (registerKnownSerialPorts( PORT_TYPE_SERIAL) > 0)
  3696. {/* dima */
  3697. result = true;
  3698. }
  3699. #endif
  3700. break;
  3701. case PORT_TYPE_PARALLEL: break;
  3702. case PORT_TYPE_I2C: break;
  3703. case PORT_TYPE_RS485: break;
  3704. case PORT_TYPE_RAW: break;
  3705. default:
  3706. sprintf( message, "unknown portType %d handed to \
  3707. native RXTXCommDriver.registerKnownPorts() \
  3708. method.\n",
  3709. (int) portType
  3710. );
  3711. report( message );
  3712. }
  3713. return result;
  3714. }
  3715. /*----------------------------------------------------------
  3716. isPortPrefixValid
  3717. accept: a port prefix
  3718. perform: see if the port prefix matches a port that is valid on this OS.
  3719. return: true if it exists otherwise false
  3720. exceptions: none
  3721. comments:
  3722. ----------------------------------------------------------*/
  3723. jboolean gnu::io::RXTXCommDriver::isPortPrefixValid(
  3724. jstring jstr
  3725. )
  3726. {
  3727. jboolean result;
  3728. static struct stat mystat;
  3729. char teststring[256];
  3730. int fd,i;
  3731. char filename[80];
  3732. for( i=0;i<jstr->length();i++)
  3733. filename[i] = jstr->charAt(i);
  3734. filename[i] = '\0';
  3735. ENTER( "RXTXCommDriver:isPortPrefixValid" );
  3736. for(i=0;i<64;i++){
  3737. #if defined(__sun__)
  3738. /* Solaris uses /dev/cua/a instead of /dev/cua0 */
  3739. if( i > 25 ) break;
  3740. sprintf(teststring,"%s%s%c",DEVICEDIR, name, i + 97 );
  3741. fprintf(stderr, "testing: %s\n", teststring);
  3742. #else
  3743. #if defined(_GNU_SOURCE)
  3744. snprintf(teststring, 256, "%s%s%i",DEVICEDIR,filename, i);
  3745. #else
  3746. sprintf(teststring,"%s%s%i",DEVICEDIR,filename, i);
  3747. #endif /* _GNU_SOURCE */
  3748. stat(teststring,&mystat);
  3749. #endif /* __sun__ */
  3750. /* XXX the following hoses freebsd when it tries to open the port later on */
  3751. #ifndef __FreeBSD__
  3752. if(S_ISCHR(mystat.st_mode)){
  3753. fd=::OPEN(teststring,O_RDONLY|O_NONBLOCK);
  3754. if (fd>0){
  3755. ::CLOSE(fd);
  3756. result=true;
  3757. break;
  3758. }
  3759. else
  3760. result=false;
  3761. }
  3762. else
  3763. result=false;
  3764. #else
  3765. result=true;
  3766. #endif /* __FreeBSD __ */
  3767. }
  3768. #if defined(_GNU_SOURCE)
  3769. snprintf(teststring, 256, "%s%s",DEVICEDIR,filename);
  3770. #else
  3771. sprintf(teststring,"%s%s",DEVICEDIR,filename);
  3772. #endif /* _GNU_SOURCE */
  3773. stat(teststring,&mystat);
  3774. if(S_ISCHR(mystat.st_mode)){
  3775. fd=::OPEN(teststring,O_RDONLY|O_NONBLOCK);
  3776. if (fd>0){
  3777. ::CLOSE(fd);
  3778. result=true;
  3779. }
  3780. }
  3781. LEAVE( "RXTXCommDriver:isPortPrefixValid" );
  3782. return(result);
  3783. }
  3784. /*----------------------------------------------------------
  3785. getDeviceDirectory
  3786. accept:
  3787. perform:
  3788. return: the directory containing the device files
  3789. exceptions:
  3790. comments: use this to avoid hard coded "/dev/"
  3791. values are in SerialImp.h
  3792. ----------------------------------------------------------*/
  3793. jstring gnu::io::RXTXCommDriver::getDeviceDirectory(
  3794. )
  3795. {
  3796. ENTER( "RXTXCommDriver:getDeviceDirectory" );
  3797. return JvNewStringUTF(DEVICEDIR);
  3798. LEAVE( "RXTXCommDriver:getDeviceDirectory" );
  3799. }
  3800. #ifdef GOING_TO_MESS_WITH_BUFFERS
  3801. /*----------------------------------------------------------
  3802. setInputBufferSize
  3803. accept:
  3804. perform:
  3805. return: none
  3806. exceptions: none
  3807. comments: see fopen/fclose/fwrite/fread man pages.
  3808. ----------------------------------------------------------*/
  3809. void gnu::io::RXTXPort::setInputBufferSize(
  3810. jint size
  3811. )
  3812. {
  3813. report( "setInputBufferSize is not implemented\n" );
  3814. }
  3815. /*----------------------------------------------------------
  3816. getIputBufferSize
  3817. accept:
  3818. perform:
  3819. return: none
  3820. exceptions: none
  3821. comments: see fopen/fclose/fwrite/fread man pages.
  3822. ----------------------------------------------------------*/
  3823. jint gnu::io::RXTXPort::getInputBufferSize(
  3824. )
  3825. {
  3826. report( "getInputBufferSize is not implemented\n" );
  3827. return(1);
  3828. }
  3829. /*----------------------------------------------------------
  3830. setOutputBufferSize
  3831. accept:
  3832. perform:
  3833. return: none
  3834. exceptions: none
  3835. comments: see fopen/fclose/fwrite/fread man pages.
  3836. ----------------------------------------------------------*/
  3837. void gnu::io::RXTXPort::setOutputBufferSize(
  3838. jint size
  3839. )
  3840. {
  3841. report( "setOutputBufferSize is not implemented\n" );
  3842. }
  3843. /*----------------------------------------------------------
  3844. getOutputBufferSize
  3845. accept:
  3846. perform:
  3847. return: none
  3848. exceptions: none
  3849. comments: see fopen/fclose/fwrite/fread man pages.
  3850. ----------------------------------------------------------*/
  3851. jint gnu::io::RXTXPort::getOutputBufferSize()
  3852. {
  3853. report( "getOutputBufferSize is not implemented\n" );
  3854. return(1);
  3855. }
  3856. #endif /* GOING_TO_MESS_WITH_BUFFERS */
  3857. /*----------------------------------------------------------
  3858. interruptEventLoop
  3859. accept: nothing
  3860. perform: increment eventloop_interrupted
  3861. return: nothing
  3862. exceptions: none
  3863. comments: all eventloops in this PID will check if their thread
  3864. is interrupted. When all the interrupted threads exit
  3865. they will decrement the var leaving it 0.
  3866. the remaining threads will continue.
  3867. ----------------------------------------------------------*/
  3868. void gnu::io::RXTXPort::interruptEventLoop(
  3869. )
  3870. {
  3871. struct event_info_struct *index = master_index;
  3872. int fd = ( int ) this->fd;
  3873. int searching = 1;
  3874. while( searching )
  3875. {
  3876. index = master_index;
  3877. if( index )
  3878. {
  3879. while( index->fd != fd &&
  3880. index->next ) index = index->next;
  3881. if ( index->fd == fd ) searching = 0;
  3882. }
  3883. else
  3884. report("x");
  3885. if( searching )
  3886. {
  3887. report("@");
  3888. usleep(1000);
  3889. }
  3890. }
  3891. index->eventloop_interrupted = 1;
  3892. /*
  3893. Many OS's need a thread running to determine if output buffer is
  3894. empty. For Linux and Win32 it is not needed. So closing is used to
  3895. shut down the thread in the write order on OS's that don't have
  3896. kernel support for output buffer empty.
  3897. In rxtx TIOCSERGETLSR is defined for win32 and Linux
  3898. */
  3899. #ifdef TIOCSERGETLSR
  3900. index->closing=1;
  3901. #endif /* TIOCSERGETLSR */
  3902. #ifdef WIN32
  3903. termios_interrupt_event_loop( index->fd, 1 );
  3904. #endif /* WIN32 */
  3905. report("interruptEventLoop: interrupted\n");
  3906. }
  3907. /*----------------------------------------------------------
  3908. is_interrupted
  3909. accept: event_info_struct
  3910. perform: see if the port is being closed.
  3911. return: a positive value if the port is being closed.
  3912. exceptions: none
  3913. comments:
  3914. ----------------------------------------------------------*/
  3915. jboolean is_interrupted( gnu::io::RXTXPort *p, struct event_info_struct *eis )
  3916. {
  3917. int result;
  3918. ENTER( "is_interrupted" );
  3919. result = p->checkMonitorThread( );
  3920. #ifdef DEBUG
  3921. if((*env)->ExceptionOccurred(env)) {
  3922. report ( "is_interrupted: an error occured calling sendEvent()\n" );
  3923. (*env)->ExceptionDescribe(env);
  3924. (*env)->ExceptionClear(env);
  3925. }
  3926. #endif /* DEBUG */
  3927. LEAVE( "RXTXCommDriver:is_interrupted" );
  3928. return(result);
  3929. }
  3930. /*----------------------------------------------------------
  3931. nativeSetEventFlag
  3932. accept: fd for finding the struct, event to flag, flag.
  3933. perform: toggle the flag
  3934. return: none
  3935. exceptions: none
  3936. comments: all the logic used to be done in Java but its too noisy
  3937. ----------------------------------------------------------*/
  3938. void gnu::io::RXTXPort::nativeSetEventFlag(
  3939. jint fd,
  3940. jint event,
  3941. jboolean flag
  3942. )
  3943. {
  3944. struct event_info_struct *index = master_index;
  3945. if( !index )
  3946. {
  3947. report_error("nativeSetEventFlag !index\n");
  3948. return;
  3949. }
  3950. while( index->fd != fd && index->next )
  3951. {
  3952. index = index->next;
  3953. }
  3954. if( index->fd != fd )
  3955. {
  3956. report_error("nativeSetEventFlag !fd\n");
  3957. return;
  3958. }
  3959. index->eventflags[event] = (int) flag;
  3960. #ifdef WIN32
  3961. termios_setflags( fd, index->eventflags );
  3962. #endif /* win32 */
  3963. }
  3964. /*----------------------------------------------------------
  3965. send_event
  3966. accept: event_info_structure, event type and true/false
  3967. perform: if state is > 0 send a true event otherwise send false
  3968. return: a positive value if the port is being closed.
  3969. exceptions: none
  3970. comments:
  3971. ----------------------------------------------------------*/
  3972. int send_event( gnu::io::RXTXPort *p, struct event_info_struct *eis, jint type, int flag )
  3973. {
  3974. int result;
  3975. ENTER( "send_event" );
  3976. if( !eis || eis->eventloop_interrupted > 1 )
  3977. {
  3978. report("event loop interrupted\n");
  3979. return true;
  3980. }
  3981. report_verbose("send_event: !eventloop_interupted\n");
  3982. #ifdef TODO /* FIXME jcj hack */
  3983. (*env)->ExceptionClear(env);
  3984. #endif /* FIXME jcj hack */
  3985. report_verbose("send_event: calling\n");
  3986. result = p->sendEvent( type, flag > 0 ? true : false );
  3987. report_verbose("send_event: called\n");
  3988. #ifdef asdf
  3989. if(!eis || (*eis->env)->ExceptionOccurred(eis->env)) {
  3990. report ( "send_event: an error occured calling sendEvent()\n" );
  3991. (*eis->env)->ExceptionDescribe(eis->env);
  3992. (*eis->env)->ExceptionClear(eis->env);
  3993. }
  3994. #endif /* asdf */
  3995. /* report("e"); */
  3996. LEAVE( "send_event" );
  3997. return(result);
  3998. }
  3999. /*----------------------------------------------------------
  4000. report_warning
  4001. accept: string to send to report as an message
  4002. perform: send the string to stderr or however it needs to be reported.
  4003. return: none
  4004. exceptions: none
  4005. comments:
  4006. ----------------------------------------------------------*/
  4007. void report_warning(char *msg)
  4008. {
  4009. #ifndef DEBUG_MW
  4010. fprintf(stderr, msg);
  4011. #else
  4012. mexWarnMsgTxt( (const char *) msg );
  4013. #endif /* DEBUG_MW */
  4014. }
  4015. /*----------------------------------------------------------
  4016. report_verbose
  4017. accept: string to send to report as an verbose message
  4018. perform: send the string to stderr or however it needs to be reported.
  4019. return: none
  4020. exceptions: none
  4021. comments:
  4022. ----------------------------------------------------------*/
  4023. void report_verbose(char *msg)
  4024. {
  4025. #ifdef DEBUG_VERBOSE
  4026. #ifdef DEBUG_MW
  4027. mexErrMsgTxt( msg );
  4028. #else
  4029. fprintf(stderr, msg);
  4030. #endif /* DEBUG_MW */
  4031. #endif /* DEBUG_VERBOSE */
  4032. }
  4033. /*----------------------------------------------------------
  4034. report_error
  4035. accept: string to send to report as an error
  4036. perform: send the string to stderr or however it needs to be reported.
  4037. return: none
  4038. exceptions: none
  4039. comments:
  4040. ----------------------------------------------------------*/
  4041. void report_error(char *msg)
  4042. {
  4043. #ifndef DEBUG_MW
  4044. fprintf(stderr, msg);
  4045. #else
  4046. mexWarnMsgTxt( msg );
  4047. #endif /* DEBUG_MW */
  4048. }
  4049. /*----------------------------------------------------------
  4050. report
  4051. accept: string to send to stderr
  4052. perform: if DEBUG is defined send the string to stderr.
  4053. return: none
  4054. exceptions: none
  4055. comments:
  4056. ----------------------------------------------------------*/
  4057. void report(char *msg)
  4058. {
  4059. #ifdef DEBUG
  4060. # ifndef DEBUG_MW
  4061. fprintf(stderr, msg);
  4062. # else
  4063. mexPrintf( msg );
  4064. # endif /* DEBUG_MW */
  4065. #endif /* DEBUG */
  4066. }
  4067. #ifndef WIN32
  4068. #ifdef LFS
  4069. /*----------------------------------------------------------
  4070. lfs_lock
  4071. accept: The name of the device to try to lock
  4072. perform: Create a lock file if there is not one already using a
  4073. lock file server.
  4074. return: 1 on failure 0 on success
  4075. exceptions: none
  4076. comments:
  4077. ----------------------------------------------------------*/
  4078. int lfs_lock( const char *filename, int pid )
  4079. {
  4080. int s;
  4081. int ret;
  4082. int size = 1024;
  4083. char *buffer = malloc(size);
  4084. struct sockaddr_in addr;
  4085. if ( !( s = socket( AF_INET, SOCK_STREAM, 0 ) ) > 0 )
  4086. return 1;
  4087. addr.sin_family = AF_INET;
  4088. addr.sin_port = htons( 50001 );
  4089. addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
  4090. if ( !connect( s, ( struct sockaddr * ) &addr, sizeof( addr ) ) == 0 )
  4091. return 1;
  4092. ret=recv( s, buffer, size, 0 );
  4093. sprintf( buffer, "lock %s %i\n", filename, pid );
  4094. /* printf( "%s", buffer ); */
  4095. send( s, buffer, strlen(buffer), 0 );
  4096. ret=recv( s, buffer, size, 0 );
  4097. if ( ret > 0 )
  4098. {
  4099. buffer[ret] = '\0';
  4100. /* printf( "Message recieved: %s", buffer ); */
  4101. }
  4102. send( s, "quit\n", strlen( "quit\n" ), 0 );
  4103. close(s);
  4104. /* printf("%s\n", buffer); */
  4105. if( buffer[0] == '2' ) return 0;
  4106. return 1;
  4107. }
  4108. /*----------------------------------------------------------
  4109. lfs_unlock
  4110. accept: The name of the device to try to unlock
  4111. perform: Remove a lock file if there is one using a
  4112. lock file server.
  4113. return: 1 on failure 0 on success
  4114. exceptions: none
  4115. comments:
  4116. ----------------------------------------------------------*/
  4117. int lfs_unlock( const char *filename, int pid )
  4118. {
  4119. int s;
  4120. int ret;
  4121. int size = 1024;
  4122. char *buffer = malloc(size);
  4123. struct sockaddr_in addr;
  4124. if ( !( s = socket( AF_INET, SOCK_STREAM, 0 ) ) > 0 )
  4125. return 1;
  4126. addr.sin_family = AF_INET;
  4127. addr.sin_port = htons( 50001 );
  4128. addr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
  4129. if ( !connect( s, ( struct sockaddr * ) &addr, sizeof( addr ) ) == 0 )
  4130. return 1;
  4131. sprintf( buffer, "unlock %s %i\n", filename, pid );
  4132. /* printf( "%s", buffer ); */
  4133. send( s, buffer, strlen(buffer), 0 );
  4134. ret = recv( s, buffer, size, 0 );
  4135. if ( ret > 0 )
  4136. {
  4137. buffer[ret] = '\0';
  4138. /* printf( "Message recieved: %s", buffer ); */
  4139. }
  4140. send( s, "quit\n", strlen( "quit\n" ), 0 );
  4141. close(s);
  4142. if( buffer[0] == '2' ) return 0;
  4143. return 1;
  4144. }
  4145. #endif /* LFS */
  4146. /*----------------------------------------------------------
  4147. fhs_lock
  4148. accept: The name of the device to try to lock
  4149. termios struct
  4150. perform: Create a lock file if there is not one already.
  4151. return: 1 on failure 0 on success
  4152. exceptions: none
  4153. comments: This is for linux and freebsd only currently. I see SVR4 does
  4154. this differently and there are other proposed changes to the
  4155. Filesystem Hierachy Standard
  4156. more reading:
  4157. ----------------------------------------------------------*/
  4158. int fhs_lock( const char *filename, int pid )
  4159. {
  4160. /*
  4161. * There is a zoo of lockdir possibilities
  4162. * Its possible to check for stale processes with most of them.
  4163. * for now we will just check for the lockfile on most
  4164. * Problem lockfiles will be dealt with. Some may not even be in use.
  4165. *
  4166. */
  4167. int fd,j;
  4168. char lockinfo[12], message[80];
  4169. char file[80], *p;
  4170. j = strlen( filename );
  4171. p = ( char * ) filename + j;
  4172. /* FIXME need to handle subdirectories /dev/cua/...
  4173. SCO Unix use lowercase all the time
  4174. taj
  4175. */
  4176. //printf("lock file is %s\n",filename);
  4177. while( *( p - 1 ) != '/' && j-- != 1 )
  4178. {
  4179. #if defined ( __unixware__ )
  4180. *p = tolower( *p );
  4181. #endif /* __unixware__ */
  4182. p--;
  4183. }
  4184. sprintf( file, "%s/LCK..%s", LOCKDIR, p );
  4185. if ( check_lock_status( filename ) )
  4186. {
  4187. report( "fhs_lock() lockstatus fail\n" );
  4188. return 1;
  4189. }
  4190. fd = open( file, O_CREAT | O_WRONLY | O_EXCL, 0444 );
  4191. if( fd < 0 )
  4192. {
  4193. sprintf( message,
  4194. "RXTX fhs_lock() Error: creating lock file: %s: %s\n",
  4195. file, strerror(errno) );
  4196. report_error( message );
  4197. return 1;
  4198. }
  4199. sprintf( lockinfo, "%10d\n",(int) getpid() );
  4200. sprintf( message, "fhs_lock: creating lockfile: %s\n", lockinfo );
  4201. report( message );
  4202. write( fd, lockinfo, 11 );
  4203. close( fd );
  4204. return 0;
  4205. }
  4206. /*----------------------------------------------------------
  4207. uucp_lock
  4208. accept: char * filename. Device to be locked
  4209. perform: Try to get a uucp_lock
  4210. return: int 0 on success
  4211. exceptions: none
  4212. comments:
  4213. The File System Hierarchy Standard
  4214. http://www.pathname.com/fhs/
  4215. UUCP Lock Files
  4216. http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html
  4217. FSSTND
  4218. ftp://tsx-11.mit.edu/pub/linux/docs/linux-standards/fsstnd/
  4219. Proposed Changes to the File System Hierarchy Standard
  4220. ftp://scicom.alphacdc.com/pub/linux/devlock-0.X.tgz
  4221. "UNIX Network Programming", W. Richard Stevens,
  4222. Prentice-Hall, 1990, pages 96-101.
  4223. There is much to do here.
  4224. 1) UUCP style locks (done)
  4225. /var/spool/uucp
  4226. 2) SVR4 locks
  4227. /var/spool/locks
  4228. 3) FSSTND locks (done)
  4229. /var/lock
  4230. 4) handle stale locks (done except kermit locks)
  4231. 5) handle minicom lockfile contents (FSSTND?)
  4232. " 16929 minicom root\n" (done)
  4233. 6) there are other Lock conventions that use Major and Minor
  4234. numbers...
  4235. 7) Stevens recommends LCK..<pid>
  4236. most are caught above. If they turn out to be problematic
  4237. rather than an exercise, we will handle them.
  4238. ----------------------------------------------------------*/
  4239. int uucp_lock( const char *filename, int pid )
  4240. {
  4241. char lockfilename[80], lockinfo[12], message[80];
  4242. char name[80];
  4243. int fd;
  4244. struct stat buf;
  4245. sprintf( message, "uucp_lock( %s );\n", filename );
  4246. report( message );
  4247. if ( check_lock_status( filename ) )
  4248. {
  4249. report( "RXTX uucp check_lock_status true\n" );
  4250. return 1;
  4251. }
  4252. if ( stat( LOCKDIR, &buf ) != 0 )
  4253. {
  4254. report( "RXTX uucp_lock() could not find lock directory.\n" );
  4255. return 1;
  4256. }
  4257. if ( stat( filename, &buf ) != 0 )
  4258. {
  4259. report( "RXTX uucp_lock() could not find device.\n" );
  4260. sprintf( message, "uucp_lock: device was %s\n", name );
  4261. report( message );
  4262. return 1;
  4263. }
  4264. sprintf( lockfilename, "%s/LK.%03d.%03d.%03d",
  4265. LOCKDIR,
  4266. (int) major( buf.st_dev ),
  4267. (int) major( buf.st_rdev ),
  4268. (int) minor( buf.st_rdev )
  4269. );
  4270. sprintf( lockinfo, "%10d\n", (int) getpid() );
  4271. if ( stat( lockfilename, &buf ) == 0 )
  4272. {
  4273. sprintf( message, "RXTX uucp_lock() %s is there\n",
  4274. lockfilename );
  4275. report( message );
  4276. report_error( message );
  4277. return 1;
  4278. }
  4279. fd = open( lockfilename, O_CREAT | O_WRONLY | O_EXCL, 0444 );
  4280. if( fd < 0 )
  4281. {
  4282. sprintf( message,
  4283. "RXTX uucp_lock() Error: creating lock file: %s\n",
  4284. lockfilename );
  4285. report_error( message );
  4286. return 1;
  4287. }
  4288. write( fd, lockinfo,11 );
  4289. close( fd );
  4290. return 0;
  4291. }
  4292. /*----------------------------------------------------------
  4293. check_lock_status
  4294. accept: the lock name in question
  4295. perform: Make sure everything is sane
  4296. return: 0 on success
  4297. exceptions: none
  4298. comments:
  4299. ----------------------------------------------------------*/
  4300. int check_lock_status( const char *filename )
  4301. {
  4302. struct stat buf;
  4303. /* First, can we find the directory? */
  4304. if ( stat( LOCKDIR, &buf ) != 0 )
  4305. {
  4306. report( "check_lock_status: could not find lock directory.\n" );
  4307. return 1;
  4308. }
  4309. /* OK. Are we able to write to it? If not lets bail */
  4310. if ( check_group_uucp() )
  4311. {
  4312. report_error( "check_lock_status: No permission to create lock file.\nplease see: How can I use Lock Files with rxtx? in INSTALL\n" );
  4313. return(1);
  4314. }
  4315. /* is the device alread locked */
  4316. if ( is_device_locked( filename ) )
  4317. {
  4318. report( "check_lock_status: device is locked by another application\n" );
  4319. return 1;
  4320. }
  4321. return 0;
  4322. }
  4323. /*----------------------------------------------------------
  4324. fhs_unlock
  4325. accept: The name of the device to unlock
  4326. perform: delete the lock file
  4327. return: none
  4328. exceptions: none
  4329. comments: This is for linux only currently. I see SVR4 does this
  4330. differently and there are other proposed changes to the
  4331. Filesystem Hierachy Standard
  4332. ----------------------------------------------------------*/
  4333. void fhs_unlock( const char *filename, int openpid )
  4334. {
  4335. char file[80],*p;
  4336. int i;
  4337. i = strlen( filename );
  4338. p = ( char * ) filename + i;
  4339. /* FIXME need to handle subdirectories /dev/cua/... */
  4340. while( *( p - 1 ) != '/' && i-- != 1 ) p--;
  4341. sprintf( file, "%s/LCK..%s", LOCKDIR, p );
  4342. if( !check_lock_pid( file, openpid ) )
  4343. {
  4344. unlink(file);
  4345. report("fhs_unlock: Removing LockFile\n");
  4346. }
  4347. else
  4348. {
  4349. report("fhs_unlock: Unable to remove LockFile\n");
  4350. }
  4351. }
  4352. /*----------------------------------------------------------
  4353. uucp_unlock
  4354. accept: char *filename the device that is locked
  4355. perform: remove the uucp lockfile if it exists
  4356. return: none
  4357. exceptions: none
  4358. comments: http://docs.freebsd.org/info/uucp/uucp.info.UUCP_Lock_Files.html
  4359. ----------------------------------------------------------*/
  4360. void uucp_unlock( const char *filename, int openpid )
  4361. {
  4362. struct stat buf;
  4363. char file[80], message[80];
  4364. /* FIXME */
  4365. sprintf( message, "uucp_unlock( %s );\n", filename );
  4366. report( message );
  4367. if ( stat( filename, &buf ) != 0 )
  4368. {
  4369. /* hmm the file is not there? */
  4370. report( "uucp_unlock() no such device\n" );
  4371. return;
  4372. }
  4373. sprintf( file, LOCKDIR"/LK.%03d.%03d.%03d",
  4374. (int) major( buf.st_dev ),
  4375. (int) major( buf.st_rdev ),
  4376. (int) minor( buf.st_rdev )
  4377. );
  4378. if ( stat( file, &buf ) != 0 )
  4379. {
  4380. /* hmm the file is not there? */
  4381. report( "uucp_unlock no such lockfile\n" );
  4382. return;
  4383. }
  4384. if( !check_lock_pid( file, openpid ) )
  4385. {
  4386. sprintf( message, "uucp_unlock: unlinking %s\n", file );
  4387. report( message );
  4388. unlink(file);
  4389. }
  4390. else
  4391. {
  4392. sprintf( message, "uucp_unlock: unlinking failed %s\n", file );
  4393. report( message );
  4394. }
  4395. }
  4396. /*----------------------------------------------------------
  4397. check_lock_pid
  4398. accept: the name of the lockfile
  4399. perform: make sure the lock file is ours.
  4400. return: 0 on success
  4401. exceptions: none
  4402. comments:
  4403. ----------------------------------------------------------*/
  4404. int check_lock_pid( const char *file, int openpid )
  4405. {
  4406. int fd, lockpid;
  4407. char pid_buffer[12];
  4408. char message[80];
  4409. fd=open( file, O_RDONLY );
  4410. if ( fd < 0 )
  4411. {
  4412. return( 1 );
  4413. }
  4414. if ( read( fd, pid_buffer, 11 ) < 0 )
  4415. {
  4416. close( fd );
  4417. return( 1 );
  4418. }
  4419. close( fd );
  4420. pid_buffer[11] = '\0';
  4421. lockpid = atol( pid_buffer );
  4422. /* Native threads JVM's have multiple pids */
  4423. if ( lockpid != getpid() && lockpid != getppid() && lockpid != openpid )
  4424. {
  4425. sprintf(message, "check_lock_pid: lock = %s pid = %i gpid=%i openpid=%i\n",
  4426. pid_buffer, (int) getpid(), (int) getppid(), openpid );
  4427. report( message );
  4428. return( 1 );
  4429. }
  4430. return( 0 );
  4431. }
  4432. /*----------------------------------------------------------
  4433. check_group_uucp
  4434. accept: none
  4435. perform: check if the user is root or in group uucp
  4436. return: 0 on success
  4437. exceptions: none
  4438. comments:
  4439. This checks if the effective user is in group uucp so we can
  4440. create lock files. If not we give them a warning and bail.
  4441. If its root we just skip the test.
  4442. if someone really wants to override this they can use the USER_LOCK_DIRECTORY --not recommended.
  4443. In a recent change RedHat 7.2 decided to use group lock.
  4444. In order to get around this we just check the group id
  4445. of the lock directory.
  4446. * Modified to support Debian *
  4447. The problem was that checking the ownership of the lock file
  4448. dir is not enough, in the sense that even if the current user
  4449. is not in the group of the lock directory if the lock
  4450. directory has 777 permissions the lock file can be anyway
  4451. created. My solution is simply to try to create a tmp file
  4452. there and if it works then we can go on. Here is my code that
  4453. I tried and seems to work.
  4454. Villa Valerio <valerio.villa@siemens.com>
  4455. ----------------------------------------------------------*/
  4456. int check_group_uucp()
  4457. {
  4458. #ifndef USER_LOCK_DIRECTORY
  4459. FILE *testLockFile ;
  4460. char testLockFileDirName[] = LOCKDIR;
  4461. char testLockFileName[] = "tmpXXXXXX";
  4462. char *testLockAbsFileName;
  4463. testLockAbsFileName = ( char * ) calloc(strlen(testLockFileDirName)
  4464. + strlen(testLockFileName) + 2, sizeof(char));
  4465. if ( NULL == testLockAbsFileName )
  4466. {
  4467. report_error("check_group_uucp(): Insufficient memory");
  4468. return 1;
  4469. }
  4470. strcat(testLockAbsFileName, testLockFileDirName);
  4471. strcat(testLockAbsFileName, "/");
  4472. strcat(testLockAbsFileName, testLockFileName);
  4473. if ( NULL == mkstemp(testLockAbsFileName) )
  4474. {
  4475. free(testLockAbsFileName);
  4476. report_error("check_group_uucp(): mktemp malformed string - \
  4477. should not happen");
  4478. return 1;
  4479. }
  4480. testLockFile = fopen (testLockAbsFileName, "w+");
  4481. if (NULL == testLockFile)
  4482. {
  4483. report_error("check_group_uucp(): error testing lock file \
  4484. creation Error details: ");
  4485. report_error(strerror(errno));
  4486. free(testLockAbsFileName);
  4487. return 1;
  4488. }
  4489. fclose (testLockFile);
  4490. unlink (testLockAbsFileName);
  4491. free(testLockAbsFileName);
  4492. #endif /* USER_LOCK_DIRECTORY */
  4493. return 0;
  4494. #ifdef USE_OLD_CHECK_GROUP_UUCP
  4495. int check_group_uucp()
  4496. {
  4497. #ifndef USER_LOCK_DIRECTORY
  4498. int group_count;
  4499. struct passwd *user = getpwuid( geteuid() );
  4500. struct stat buf;
  4501. char msg[80];
  4502. gid_t list[ NGROUPS_MAX ];
  4503. if( stat( LOCKDIR, &buf) )
  4504. {
  4505. sprintf( msg, "check_group_uucp: Can not find Lock Directory: %s\n", LOCKDIR );
  4506. report_error( msg );
  4507. return( 1 );
  4508. }
  4509. group_count = getgroups( NGROUPS_MAX, list );
  4510. list[ group_count ] = geteuid();
  4511. /* JJO changes start */
  4512. if( user == NULL )
  4513. {
  4514. report_error( "Not able to get user groups.\n" );
  4515. return 1;
  4516. } else
  4517. /* JJO changes stop */
  4518. if( user->pw_gid )
  4519. {
  4520. while( group_count >= 0 && buf.st_gid != list[ group_count ] )
  4521. {
  4522. group_count--;
  4523. }
  4524. if( buf.st_gid == list[ group_count ] )
  4525. return 0;
  4526. sprintf( msg, "%i %i\n", buf.st_gid, list[ group_count ] );
  4527. report_error( msg );
  4528. report_error( UUCP_ERROR );
  4529. return 1;
  4530. }
  4531. return 0;
  4532. /*
  4533. if( strcmp( user->pw_name, "root" ) )
  4534. {
  4535. while( *g->gr_mem )
  4536. {
  4537. if( !strcmp( *g->gr_mem, user->pw_name ) )
  4538. {
  4539. break;
  4540. }
  4541. (void) *g->gr_mem++;
  4542. }
  4543. if( !*g->gr_mem )
  4544. {
  4545. report( UUCP_ERROR );
  4546. return 1;
  4547. }
  4548. }
  4549. */
  4550. #endif /* USER_LOCK_DIRECTORY */
  4551. return 0;
  4552. #endif /* USE_OLD_CHECK_GROUP_UUCP */
  4553. }
  4554. /*----------------------------------------------------------
  4555. The following should be able to follow symbolic links. I think the stat
  4556. method used below will work on more systems. This was found while looking
  4557. for information.
  4558. * realpath() doesn't exist on all of the systems my code has to run
  4559. on (HP-UX 9.x, specifically)
  4560. ----------------------------------------------------------
  4561. int different_from_LOCKDIR(const char* ld)
  4562. {
  4563. char real_ld[MAXPATHLEN];
  4564. char real_LOCKDIR[MAXPATHLEN];
  4565. if (strncmp(ld, LOCKDIR, strlen(ld)) == 0)
  4566. return 0;
  4567. if (realpath(ld, real_ld) == NULL)
  4568. return 1;
  4569. if (realpath(LOCKDIR, real_LOCKDIR) == NULL)
  4570. return 1;
  4571. if (strncmp(real_ld, real_LOCKDIR, strlen(real_ld)) == 0)
  4572. return 0;
  4573. else
  4574. return 1;
  4575. }
  4576. */
  4577. /*----------------------------------------------------------
  4578. is_device_locked
  4579. accept: char * filename. The device in question including the path.
  4580. perform: see if one of the many possible lock files is aready there
  4581. if there is a stale lock, remove it.
  4582. return: 1 if the device is locked or somethings wrong.
  4583. 0 if its possible to create our own lock file.
  4584. exceptions: none
  4585. comments: check if the device is already locked
  4586. ----------------------------------------------------------*/
  4587. int is_device_locked( const char *port_filename )
  4588. {
  4589. const char *lockdirs[] = { "/etc/locks", "/usr/spool/kermit",
  4590. "/usr/spool/locks", "/usr/spool/uucp", "/usr/spool/uucp/",
  4591. "/usr/spool/uucp/LCK", "/var/lock", "/var/lock/modem",
  4592. "/var/spool/lock", "/var/spool/locks", "/var/spool/uucp",
  4593. LOCKDIR, NULL
  4594. };
  4595. const char *lockprefixes[] = { "LCK..", "lk..", "LK.", NULL };
  4596. char *p, file[80], pid_buffer[20], message[80];
  4597. int i = 0, j, k, fd , pid;
  4598. struct stat buf;
  4599. struct stat buf2;
  4600. j = strlen( port_filename );
  4601. p = ( char * ) port_filename+j;
  4602. while( *( p-1 ) != '/' && j-- !=1 ) p--;
  4603. while( lockdirs[i] )
  4604. {
  4605. /*
  4606. Look for lockfiles in all known places other than the
  4607. defined lock directory for this system
  4608. report any unexpected lockfiles.
  4609. Is the suspect lockdir there?
  4610. if it is there is it not the expected lock dir?
  4611. */
  4612. if( !stat( lockdirs[i], &buf2 ) &&
  4613. strncmp( lockdirs[i], LOCKDIR, strlen( lockdirs[i] ) ) )
  4614. {
  4615. j = strlen( port_filename );
  4616. p = ( char * ) port_filename + j;
  4617. /*
  4618. SCO Unix use lowercase all the time
  4619. taj
  4620. */
  4621. while( *( p - 1 ) != '/' && j-- != 1 )
  4622. {
  4623. #if defined ( __unixware__ )
  4624. *p = tolower( *p );
  4625. #endif /* __unixware__ */
  4626. p--;
  4627. }
  4628. k=0;
  4629. while ( lockprefixes[k] )
  4630. {
  4631. /* FHS style */
  4632. sprintf( file, "%s/%s%s", lockdirs[i],
  4633. lockprefixes[k], p );
  4634. if( stat( file, &buf ) == 0 )
  4635. {
  4636. sprintf( message, UNEXPECTED_LOCK_FILE,
  4637. file );
  4638. report_warning( message );
  4639. return 1;
  4640. }
  4641. /* UUCP style */
  4642. stat(port_filename , &buf );
  4643. sprintf( file, "%s/%s%03d.%03d.%03d",
  4644. lockdirs[i],
  4645. lockprefixes[k],
  4646. (int) major( buf.st_dev ),
  4647. (int) major( buf.st_rdev ),
  4648. (int) minor( buf.st_rdev )
  4649. );
  4650. if( stat( file, &buf ) == 0 )
  4651. {
  4652. sprintf( message, UNEXPECTED_LOCK_FILE,
  4653. file );
  4654. report_warning( message );
  4655. return 1;
  4656. }
  4657. k++;
  4658. }
  4659. }
  4660. i++;
  4661. }
  4662. /*
  4663. OK. We think there are no unexpect lock files for this device
  4664. Lets see if there any stale lock files that need to be
  4665. removed.
  4666. */
  4667. #ifdef FHS
  4668. /* FHS standard locks */
  4669. i = strlen( port_filename );
  4670. p = ( char * ) port_filename + i;
  4671. while( *(p-1) != '/' && i-- != 1)
  4672. {
  4673. #if defined ( __unixware__ )
  4674. *p = tolower( *p );
  4675. #endif /* __unixware__ */
  4676. p--;
  4677. }
  4678. sprintf( file, "%s/%s%s", LOCKDIR, LOCKFILEPREFIX, p );
  4679. #else
  4680. /* UUCP standard locks */
  4681. if ( stat( port_filename, &buf ) != 0 )
  4682. {
  4683. report( "RXTX is_device_locked() could not find device.\n" );
  4684. return 1;
  4685. }
  4686. sprintf( file, "%s/LK.%03d.%03d.%03d",
  4687. LOCKDIR,
  4688. (int) major( buf.st_dev ),
  4689. (int) major( buf.st_rdev ),
  4690. (int) minor( buf.st_rdev )
  4691. );
  4692. #endif /* FHS */
  4693. if( stat( file, &buf ) == 0 )
  4694. {
  4695. /* check if its a stale lock */
  4696. fd=open( file, O_RDONLY );
  4697. read( fd, pid_buffer, 11 );
  4698. /* FIXME null terminiate pid_buffer? need to check in Solaris */
  4699. close( fd );
  4700. sscanf( pid_buffer, "%d", &pid );
  4701. if( kill( (pid_t) pid, 0 ) && errno==ESRCH )
  4702. {
  4703. sprintf( message,
  4704. "RXTX Warning: Removing stale lock file. %s\n",
  4705. file );
  4706. report_warning( message );
  4707. if( unlink( file ) != 0 )
  4708. {
  4709. snprintf( message, 80, "RXTX Error: Unable to \
  4710. remove stale lock file: %s\n",
  4711. file
  4712. );
  4713. report_warning( message );
  4714. return 1;
  4715. }
  4716. }
  4717. }
  4718. return 0;
  4719. }
  4720. #endif /* WIN32 */
  4721. /*----------------------------------------------------------
  4722. system_does_not_lock
  4723. accept: the filename the system thinks should be locked.
  4724. perform: avoid trying to create lock files on systems that dont use them
  4725. return: 0 for success ;)
  4726. exceptions: none
  4727. comments: OS's like Win32 may not have lock files.
  4728. ----------------------------------------------------------*/
  4729. int system_does_not_lock( const char * filename, int pid )
  4730. {
  4731. return 0;
  4732. }
  4733. /*----------------------------------------------------------
  4734. system_does_not_unlock
  4735. accept: the filename the system thinks should be locked.
  4736. perform: avoid trying to create lock files on systems that dont use them
  4737. return: none
  4738. exceptions: none
  4739. comments: OS's like Win32 may not have lock files.
  4740. ----------------------------------------------------------*/
  4741. void system_does_not_unlock( const char * filename, int openpid )
  4742. {
  4743. return;
  4744. }
  4745. /*----------------------------------------------------------
  4746. dump_termios
  4747. accept: string to indicate where this was called.
  4748. termios struct
  4749. perform: print the termios struct to stderr.
  4750. return: none
  4751. exceptions: none
  4752. comments: used to debug the termios struct.
  4753. ----------------------------------------------------------*/
  4754. void dump_termios(char *foo,struct termios *ttyset)
  4755. {
  4756. #ifdef DEBUG
  4757. int i;
  4758. fprintf(stderr, "%s c_iflag=%#x\n", foo, ttyset->c_iflag);
  4759. fprintf(stderr, "%s c_lflag=%#x\n", foo, ttyset->c_lflag);
  4760. fprintf(stderr, "%s c_oflag=%#x\n", foo, ttyset->c_oflag);
  4761. fprintf(stderr, "%s c_cflag=%#x\n", foo, ttyset->c_cflag);
  4762. fprintf(stderr, "%s c_cc[]: ", foo);
  4763. for(i=0; i<NCCS; i++)
  4764. {
  4765. fprintf(stderr,"%d=%x ", i, ttyset->c_cc[i]);
  4766. }
  4767. fprintf(stderr,"\n" );
  4768. #endif /* DEBUG */
  4769. }
  4770. /*----------------------------------------------------------
  4771. printj
  4772. accept: like vwprintf()
  4773. return: number of jchars written or -1
  4774. exceptions: none
  4775. comments: prints data using System.out.print()
  4776. for gcj + CNI
  4777. Just use java::lang::System::out->println(s);
  4778. ----------------------------------------------------------*/
  4779. int printj(
  4780. wchar_t *fmt,
  4781. ...
  4782. )
  4783. {
  4784. return(0);
  4785. }
  4786. /* for gcj compiles */
  4787. jboolean gnu::io::RXTXPort::nativeSetCallOutHangup( jboolean NoHup )
  4788. {
  4789. return( true );
  4790. }
  4791. jboolean gnu::io::RXTXPort::nativeGetCallOutHangup( )
  4792. {
  4793. return( true );
  4794. }
  4795. jboolean gnu::io::RXTXPort::nativeSetLowLatency( )
  4796. {
  4797. return( true );
  4798. }
  4799. jboolean gnu::io::RXTXPort::nativeGetLowLatency( )
  4800. {
  4801. return( true );
  4802. }
  4803. jboolean gnu::io::RXTXPort::nativeSetUartType( jstring ty, jboolean te )
  4804. {
  4805. return( true );
  4806. }
  4807. jstring gnu::io::RXTXPort::nativeGetUartType( )
  4808. {
  4809. return JvNewStringUTF( "RXTX-2.1-7pre13 SAM I AM" );
  4810. }