Serial Port + Console Access on RtP vs QNX4

Hi everyone,

We had the following working code on QNX4 using qnx_proxy* and dev_*
functions
and I try to get a working equivalent example for QNX RtP,
since we have many apps using console keyboard and serial port
that we have to develop and to support our customer.

It’s basically a skeleton for writing any Keyboard/Console application
and also a skeleton for writing serial port access application.

It basically take any byte from the keyboard of a serial port dumb terminal
and print it on the console, while any byte from the keyboard is print on
a serial port dumb terminal.

Pretty simple and straight forward.

Here’s the QNX4 SerialChat program:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <sys/dev.h>
#include <sys/proxy.h>
#include <sys/kernel.h>
#include <conio.h>
#include <i86.h>


#define LOCAL_KEYBOARD “/dev/con1”
#define ELAN104_SERIAL “//2/dev/ser1”

int main()
{
// This is a bidirectionnal CHAT program
// between the ELAN104, the HP Dump Terminal and the Switchboard
printf("\n\rBasic QNX Serial Port CHAT program: \n\r\n\n");

// Serial Port Stuff
unsigned state;
pid_t kb_proxy;
pid_t mdm_proxy;
pid_t pid;
int kb_fd;
int mdm_fd;
int n;
char buf[80];

// Initialize and setup the Serial Port
kb_fd = open( LOCAL_KEYBOARD, O_RDWR );// Local Keyboard
mdm_fd = open( ELAN104_SERIAL, O_RDWR );// QNX-2 Elan104 Board

kb_proxy = qnx_proxy_attach( 0, 0, 0, -1 );
mdm_proxy = qnx_proxy_attach( 0, 0, 0, -1 );


dev_mode( kb_fd, 0, _DEV_MODES );
dev_mode( mdm_fd, 0, _DEV_MODES );

// Clear, then arm the proxies for future events

dev_state( kb_fd, 0, _DEV_EVENT_INPUT );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );

dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );


for(;:wink: // Infinite Loop, until CTRL-BREAK
{

// Wait for either keyboard or modem to send an input.
pid = Receive( 0, 0, 0 );

// Waiting for an event, then check the Process ID,
// Read the message and send it back to the other machine.

if ( pid == kb_proxy ) {
state = dev_state( kb_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Keyboard Console
// then Read it and Send it Back to the Modem

if ( state & _DEV_EVENT_INPUT ) {
n = read( kb_fd, &buf, sizeof( buf ) );
write( mdm_fd, &buf, n );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );
}
}
else if ( pid == mdm_proxy )
{
state = dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Modem
// then Read it and Send it Back to the Keyboard Console

if ( state & _DEV_EVENT_INPUT )
{
n = read( mdm_fd, &buf, sizeof( buf ) );
write( kb_fd, &buf, n );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );
}
}
}


printf("\nDone!\n");
return 0;
}


The only sort of QNX RtP non-working equivalent,
I could come up with from the select() documentation was:

/*

  • This example opens a console and a serial port for
  • read mode, and calls select() with a 5 second timeout.
  • It waits for data to be available on either descriptor.
    */

#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/time.h>

int max( int x, int y )
{
return ( (x)>(y) ? (x) : (y) );
}

int main( void )
{
int console, serial;
struct timeval tv;
fd_set rfd;
int n;
char buf[80];

if( ( console = open( “/dev/con1”, O_RDWR ) ) == -1
|| ( serial = open( “/dev/ser1”, O_RDWR ) ) == -1 )
{
perror( “open” );
return EXIT_FAILURE;
}

/*

  • Clear the set of read file descriptors, and
  • add the two we just got from the open calls.
    */
    FD_ZERO( &rfd );
    FD_SET( console, &rfd );
    FD_SET( serial, &rfd );

/*

  • Set a 5 second timeout.
    */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

for(;:wink: {

switch ( n = select( 1 + max( console, serial ),
&rfd, 0, 0, &tv ) ) {
case -1:
perror( “select” );
return EXIT_FAILURE;
case 0:
puts( “select timed out” );
break;
default:
printf( “%d descriptors ready …\n”, n );
if( FD_ISSET( console, &rfd ) ) {
puts( " – console descriptor has data pending" );
n = read( console, &buf, sizeof( buf ) );
write( serial, &buf, n );
}

if( FD_ISSET( serial, &rfd ) ) {
puts( " – serial descriptor has data pending" );
n = read( serial, &buf, sizeof( buf ) );
write( console, &buf, n );
}
}


}
return EXIT_SUCCESS;
}

But that code doesn’t work, the keyboard states that bytes has to be
written,
but nothing show up on the dumb terminal, and nothing from the dumb terminal
show up on the Local Console. =(

Anybody could give us a basic working example ?

That would be just great.

Sincerly yours,
Fred.

Hello Fred,

my proposal is to say goodbye to the QNX4 like server concepts,
because QNX6 allows multithreaded applications. Please see my
comments at comp.os.qnx …

Armin

( sorry, I’m just in a hurry …)


Fred wrote:

Hi everyone,

We had the following working code on QNX4 using qnx_proxy* and dev_*
functions
and I try to get a working equivalent example for QNX RtP,
since we have many apps using console keyboard and serial port
that we have to develop and to support our customer.

It’s basically a skeleton for writing any Keyboard/Console application
and also a skeleton for writing serial port access application.

It basically take any byte from the keyboard of a serial port dumb terminal
and print it on the console, while any byte from the keyboard is print on
a serial port dumb terminal.

Pretty simple and straight forward.

Here’s the QNX4 SerialChat program:

#include <stdio.h
#include <stdlib.h
#include <fcntl.h
#include <unistd.h
#include <termios.h
#include <sys/types.h
#include <sys/stat.h

#include <sys/dev.h
#include <sys/proxy.h
#include <sys/kernel.h
#include <conio.h
#include <i86.h

#define LOCAL_KEYBOARD “/dev/con1”
#define ELAN104_SERIAL “//2/dev/ser1”

int main()
{
// This is a bidirectionnal CHAT program
// between the ELAN104, the HP Dump Terminal and the Switchboard
printf("\n\rBasic QNX Serial Port CHAT program: \n\r\n\n");

// Serial Port Stuff
unsigned state;
pid_t kb_proxy;
pid_t mdm_proxy;
pid_t pid;
int kb_fd;
int mdm_fd;
int n;
char buf[80];

// Initialize and setup the Serial Port
kb_fd = open( LOCAL_KEYBOARD, O_RDWR );// Local Keyboard
mdm_fd = open( ELAN104_SERIAL, O_RDWR );// QNX-2 Elan104 Board

kb_proxy = qnx_proxy_attach( 0, 0, 0, -1 );
mdm_proxy = qnx_proxy_attach( 0, 0, 0, -1 );

dev_mode( kb_fd, 0, _DEV_MODES );
dev_mode( mdm_fd, 0, _DEV_MODES );

// Clear, then arm the proxies for future events

dev_state( kb_fd, 0, _DEV_EVENT_INPUT );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );

dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );

for(;:wink: // Infinite Loop, until CTRL-BREAK
{

// Wait for either keyboard or modem to send an input.
pid = Receive( 0, 0, 0 );

// Waiting for an event, then check the Process ID,
// Read the message and send it back to the other machine.

if ( pid == kb_proxy ) {
state = dev_state( kb_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Keyboard Console
// then Read it and Send it Back to the Modem

if ( state & _DEV_EVENT_INPUT ) {
n = read( kb_fd, &buf, sizeof( buf ) );
write( mdm_fd, &buf, n );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );
}
}
else if ( pid == mdm_proxy )
{
state = dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Modem
// then Read it and Send it Back to the Keyboard Console

if ( state & _DEV_EVENT_INPUT )
{
n = read( mdm_fd, &buf, sizeof( buf ) );
write( kb_fd, &buf, n );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );
}
}
}

printf("\nDone!\n");
return 0;
}

The only sort of QNX RtP non-working equivalent,
I could come up with from the select() documentation was:

/*

  • This example opens a console and a serial port for
  • read mode, and calls select() with a 5 second timeout.
  • It waits for data to be available on either descriptor.
    */

#include <stdio.h
#include <string.h
#include <errno.h

#include <unistd.h
#include <stdlib.h
#include <fcntl.h
#include <sys/time.h

int max( int x, int y )
{
return ( (x)>(y) ? (x) : (y) );
}

int main( void )
{
int console, serial;
struct timeval tv;
fd_set rfd;
int n;
char buf[80];

if( ( console = open( “/dev/con1”, O_RDWR ) ) == -1
|| ( serial = open( “/dev/ser1”, O_RDWR ) ) == -1 )
{
perror( “open” );
return EXIT_FAILURE;
}

/*

  • Clear the set of read file descriptors, and
  • add the two we just got from the open calls.
    */
    FD_ZERO( &rfd );
    FD_SET( console, &rfd );
    FD_SET( serial, &rfd );

/*

  • Set a 5 second timeout.
    */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

for(;:wink: {

switch ( n = select( 1 + max( console, serial ),
&rfd, 0, 0, &tv ) ) {
case -1:
perror( “select” );
return EXIT_FAILURE;
case 0:
puts( “select timed out” );
break;
default:
printf( “%d descriptors ready …\n”, n );
if( FD_ISSET( console, &rfd ) ) {
puts( " – console descriptor has data pending" );
n = read( console, &buf, sizeof( buf ) );
write( serial, &buf, n );
}

if( FD_ISSET( serial, &rfd ) ) {
puts( " – serial descriptor has data pending" );
n = read( serial, &buf, sizeof( buf ) );
write( console, &buf, n );
}
}

}
return EXIT_SUCCESS;
}

But that code doesn’t work, the keyboard states that bytes has to be
written,
but nothing show up on the dumb terminal, and nothing from the dumb terminal
show up on the Local Console. =(

Anybody could give us a basic working example ?

That would be just great.

Sincerly yours,
Fred.

Armin Steinhoff wrote in message <3A8668D3.E7B53DB7@web_.de>…

Hello Fred,

my proposal is to say goodbye to the QNX4 like server concepts,
because QNX6 allows multithreaded applications. Please see my
comments at comp.os.qnx …

Armin



Hi everyone,

We had the following working code on QNX4 using qnx_proxy* and dev_*
functions
and I try to get a working equivalent example for QNX RtP,
since we have many apps using console keyboard and serial port
that we have to develop and to support our customer.

It’s basically a skeleton for writing any Keyboard/Console application
and also a skeleton for writing serial port access application.

It basically take any byte from the keyboard of a serial port dumb
terminal
and print it on the console, while any byte from the keyboard is print on
a serial port dumb terminal.

Pretty simple and straight forward.

Here’s the QNX4 SerialChat program:

#include <stdio.h
#include <stdlib.h
#include <fcntl.h
#include <unistd.h
#include <termios.h
#include <sys/types.h
#include <sys/stat.h

#include <sys/dev.h
#include <sys/proxy.h
#include <sys/kernel.h
#include <conio.h
#include <i86.h

#define LOCAL_KEYBOARD “/dev/con1”
#define ELAN104_SERIAL “//2/dev/ser1”

int main()
{
// This is a bidirectionnal CHAT program
// between the ELAN104, the HP Dump Terminal and the Switchboard
printf("\n\rBasic QNX Serial Port CHAT program: \n\r\n\n");

// Serial Port Stuff
unsigned state;
pid_t kb_proxy;
pid_t mdm_proxy;
pid_t pid;
int kb_fd;
int mdm_fd;
int n;
char buf[80];

// Initialize and setup the Serial Port
kb_fd = open( LOCAL_KEYBOARD, O_RDWR );// Local Keyboard
mdm_fd = open( ELAN104_SERIAL, O_RDWR );// QNX-2 Elan104 Board

kb_proxy = qnx_proxy_attach( 0, 0, 0, -1 );
mdm_proxy = qnx_proxy_attach( 0, 0, 0, -1 );

dev_mode( kb_fd, 0, _DEV_MODES );
dev_mode( mdm_fd, 0, _DEV_MODES );

// Clear, then arm the proxies for future events

dev_state( kb_fd, 0, _DEV_EVENT_INPUT );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );

dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );

for(;:wink: // Infinite Loop, until CTRL-BREAK
{

// Wait for either keyboard or modem to send an input.
pid = Receive( 0, 0, 0 );

// Waiting for an event, then check the Process ID,
// Read the message and send it back to the other machine.

if ( pid == kb_proxy ) {
state = dev_state( kb_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Keyboard Console
// then Read it and Send it Back to the Modem

if ( state & _DEV_EVENT_INPUT ) {
n = read( kb_fd, &buf, sizeof( buf ) );
write( mdm_fd, &buf, n );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );
}
}
else if ( pid == mdm_proxy )
{
state = dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Modem
// then Read it and Send it Back to the Keyboard Console

if ( state & _DEV_EVENT_INPUT )
{
n = read( mdm_fd, &buf, sizeof( buf ) );
write( kb_fd, &buf, n );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );
}
}
}

printf("\nDone!\n");
return 0;
}

The only sort of QNX RtP non-working equivalent,
I could come up with from the select() documentation was:

/*

  • This example opens a console and a serial port for
  • read mode, and calls select() with a 5 second timeout.
  • It waits for data to be available on either descriptor.
    */

#include <stdio.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/time.h>

#include <sys/types.h>
#include <sys/uio.h>

#include “Basic_PThread.hpp”


int max( int x, int y )
{
return ( (x)>(y) ? (x) : (y) );
}


int dev_raw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_cc[VMIN] = 1;
termios_p.c_cc[VTIME] = 0;
termios_p.c_lflag &= ~(ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag &= ~(OPOST);
return (tcsetattr (fd, TCSANOW, &termios_p));
}

int dev_unraw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_lflag |= (ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag |= (OPOST);
return (tcsetattr (fd, TCSAFLUSH, &termios_p));
}

//
http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_hpp-source.h
tml
//
http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_cpp-source.h
tml

class Device : public Basic_PThread
{
protected:
int fd;
int size_read;
char buffer[80];

struct timeval tv;
fd_set rfd;
int n;
char name[80];

public:

Device( const char* device = “/dev/ser1” )
: fd( 0 ), size_read( 0 ), n( 0 )
{
memset( buffer, 0, sizeof( buffer ) );
memset( name, 0, sizeof( name ) );
memset( &tv, 0, sizeof( tv ) );
strcpy( name, device );

// Open a file for input
if( ( fd = open( device, O_RDWR ) ) == -1 )
{
printf( “Error while opening [%s].\n”, device );
exit( 1 );
}

/*

  • Clear the set of read file descriptors, and
  • add the two we just got from the open calls.
    */
    FD_ZERO( &rfd );
    FD_SET( fd, &rfd );

/*

  • Set a 5 second timeout.
    */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

dev_raw( fd );

// http://qdn.qnx.com/support/docs/neutrino_qrp/lib_ref/t/tcgetattr.html
// http://qdn.qnx.com/support/docs/neutrino_qrp/audio/wavec.html

}

virtual void run()
{
for(;:wink:
{
// Read the text
size_read = read( fd, buffer, 1 );

// Test for error
if( size_read == -1 ) {
printf( “Error reading %s”, name );
exit( 1 );
}

handler();
}
}

virtual void handler() = 0;

virtual ~Device()
{
// Close the file
close( fd );
}

private:
// Prohibited:
Device( const Device& src );
const Device& operator=( const Device& src );
};

class Chat : public Device
{
Chat* chat;
public:

Chat( const char* device = “/dev/ser1”, Chat* c = NULL )
: Device( device ), chat( c ) { }

void setup( Chat* c ) { chat = c; }

virtual void ~Console() { }

virtual void handler()
{
if ( !c ) return;
c->print( buffer, size_read );
}

void print( const void* buf, size_t sz )
{
write( fd, buf, sz );
}
};

int main()
{
Chat* serial = new Chat( “/dev/ser1” );
Chat* console = new Chat( “/dev/con1”, serial );
serial->setup( console );

serial->start( 11 );
console->start(11 );

serial->join();
console->join();

for( int k = 0; k < 2000; k++ ) { printf("."); }

return 0;
}

/*********** END *****/


Something like that ?
Fred.

for(;:wink: {

switch ( n = select( 1 + max( console, serial ),
&rfd, 0, 0, &tv ) ) {
case -1:
perror( “select” );
return EXIT_FAILURE;
case 0:
puts( “select timed out” );
break;
default:
printf( “%d descriptors ready …\n”, n );
if( FD_ISSET( console, &rfd ) ) {
puts( " – console descriptor has data pending" );
n = read( console, &buf, sizeof( buf ) );
write( serial, &buf, n );
}

if( FD_ISSET( serial, &rfd ) ) {
puts( " – serial descriptor has data pending" );
n = read( serial, &buf, sizeof( buf ) );
write( console, &buf, n );
}
}

}
return EXIT_SUCCESS;
}

But that code doesn’t work, the keyboard states that bytes has to be
written,
but nothing show up on the dumb terminal, and nothing from the dumb
terminal
show up on the Local Console. =(

Anybody could give us a basic working example ?

That would be just great.

Sincerly yours,
Fred.

Hi Fred,

yes … I believe your coding example goes into the right direction
as long as the method ‘start’ starts a new thread.

Armin

Fred wrote:

Armin Steinhoff wrote in message <3A8668D3.E7B53DB7@web_.de>…

Hello Fred,

my proposal is to say goodbye to the QNX4 like server concepts,
because QNX6 allows multithreaded applications. Please see my
comments at comp.os.qnx …

Armin



Hi everyone,

We had the following working code on QNX4 using qnx_proxy* and dev_*
functions
and I try to get a working equivalent example for QNX RtP,
since we have many apps using console keyboard and serial port
that we have to develop and to support our customer.

It’s basically a skeleton for writing any Keyboard/Console application
and also a skeleton for writing serial port access application.

It basically take any byte from the keyboard of a serial port dumb
terminal
and print it on the console, while any byte from the keyboard is print on
a serial port dumb terminal.

Pretty simple and straight forward.

Here’s the QNX4 SerialChat program:

#include <stdio.h
#include <stdlib.h
#include <fcntl.h
#include <unistd.h
#include <termios.h
#include <sys/types.h
#include <sys/stat.h

#include <sys/dev.h
#include <sys/proxy.h
#include <sys/kernel.h
#include <conio.h
#include <i86.h

#define LOCAL_KEYBOARD “/dev/con1”
#define ELAN104_SERIAL “//2/dev/ser1”

int main()
{
// This is a bidirectionnal CHAT program
// between the ELAN104, the HP Dump Terminal and the Switchboard
printf("\n\rBasic QNX Serial Port CHAT program: \n\r\n\n");

// Serial Port Stuff
unsigned state;
pid_t kb_proxy;
pid_t mdm_proxy;
pid_t pid;
int kb_fd;
int mdm_fd;
int n;
char buf[80];

// Initialize and setup the Serial Port
kb_fd = open( LOCAL_KEYBOARD, O_RDWR );// Local Keyboard
mdm_fd = open( ELAN104_SERIAL, O_RDWR );// QNX-2 Elan104 Board

kb_proxy = qnx_proxy_attach( 0, 0, 0, -1 );
mdm_proxy = qnx_proxy_attach( 0, 0, 0, -1 );

dev_mode( kb_fd, 0, _DEV_MODES );
dev_mode( mdm_fd, 0, _DEV_MODES );

// Clear, then arm the proxies for future events

dev_state( kb_fd, 0, _DEV_EVENT_INPUT );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );

dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );

for(;:wink: // Infinite Loop, until CTRL-BREAK
{

// Wait for either keyboard or modem to send an input.
pid = Receive( 0, 0, 0 );

// Waiting for an event, then check the Process ID,
// Read the message and send it back to the other machine.

if ( pid == kb_proxy ) {
state = dev_state( kb_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Keyboard Console
// then Read it and Send it Back to the Modem

if ( state & _DEV_EVENT_INPUT ) {
n = read( kb_fd, &buf, sizeof( buf ) );
write( mdm_fd, &buf, n );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );
}
}
else if ( pid == mdm_proxy )
{
state = dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Modem
// then Read it and Send it Back to the Keyboard Console

if ( state & _DEV_EVENT_INPUT )
{
n = read( mdm_fd, &buf, sizeof( buf ) );
write( kb_fd, &buf, n );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );
}
}
}

printf("\nDone!\n");
return 0;
}

The only sort of QNX RtP non-working equivalent,
I could come up with from the select() documentation was:

/*

  • This example opens a console and a serial port for
  • read mode, and calls select() with a 5 second timeout.
  • It waits for data to be available on either descriptor.
    */

#include <stdio.h
#include <string.h
#include <errno.h

#include <unistd.h
#include <stdlib.h
#include <fcntl.h
#include <sys/time.h

#include <sys/types.h
#include <sys/uio.h

#include “Basic_PThread.hpp”

int max( int x, int y )
{
return ( (x)>(y) ? (x) : (y) );
}

int dev_raw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_cc[VMIN] = 1;
termios_p.c_cc[VTIME] = 0;
termios_p.c_lflag &= ~(ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag &= ~(OPOST);
return (tcsetattr (fd, TCSANOW, &termios_p));
}

int dev_unraw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_lflag |= (ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag |= (OPOST);
return (tcsetattr (fd, TCSAFLUSH, &termios_p));
}

//
http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_hpp-source.h
tml
//
http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_cpp-source.h
tml

class Device : public Basic_PThread
{
protected:
int fd;
int size_read;
char buffer[80];

struct timeval tv;
fd_set rfd;
int n;
char name[80];

public:

Device( const char* device = “/dev/ser1” )
: fd( 0 ), size_read( 0 ), n( 0 )
{
memset( buffer, 0, sizeof( buffer ) );
memset( name, 0, sizeof( name ) );
memset( &tv, 0, sizeof( tv ) );
strcpy( name, device );

// Open a file for input
if( ( fd = open( device, O_RDWR ) ) == -1 )
{
printf( “Error while opening [%s].\n”, device );
exit( 1 );
}

/*

  • Clear the set of read file descriptors, and
  • add the two we just got from the open calls.
    */
    FD_ZERO( &rfd );
    FD_SET( fd, &rfd );

/*

  • Set a 5 second timeout.
    */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

dev_raw( fd );

// > http://qdn.qnx.com/support/docs/neutrino_qrp/lib_ref/t/tcgetattr.html
// > http://qdn.qnx.com/support/docs/neutrino_qrp/audio/wavec.html

}

virtual void run()
{
for(;:wink:
{
// Read the text
size_read = read( fd, buffer, 1 );

// Test for error
if( size_read == -1 ) {
printf( “Error reading %s”, name );
exit( 1 );
}

handler();
}
}

virtual void handler() = 0;

virtual ~Device()
{
// Close the file
close( fd );
}

private:
// Prohibited:
Device( const Device& src );
const Device& operator=( const Device& src );
};

class Chat : public Device
{
Chat* chat;
public:

Chat( const char* device = “/dev/ser1”, Chat* c = NULL )
: Device( device ), chat( c ) { }

void setup( Chat* c ) { chat = c; }

virtual void ~Console() { }

virtual void handler()
{
if ( !c ) return;
c->print( buffer, size_read );
}

void print( const void* buf, size_t sz )
{
write( fd, buf, sz );
}
};

int main()
{
Chat* serial = new Chat( “/dev/ser1” );
Chat* console = new Chat( “/dev/con1”, serial );
serial->setup( console );

serial->start( 11 );
console->start(11 );

serial->join();
console->join();

for( int k = 0; k < 2000; k++ ) { printf("."); }

return 0;
}

/*********** END *****/

Something like that ?
Fred.

for(;:wink: {

switch ( n = select( 1 + max( console, serial ),
&rfd, 0, 0, &tv ) ) {
case -1:
perror( “select” );
return EXIT_FAILURE;
case 0:
puts( “select timed out” );
break;
default:
printf( “%d descriptors ready …\n”, n );
if( FD_ISSET( console, &rfd ) ) {
puts( " – console descriptor has data pending" );
n = read( console, &buf, sizeof( buf ) );
write( serial, &buf, n );
}

if( FD_ISSET( serial, &rfd ) ) {
puts( " – serial descriptor has data pending" );
n = read( serial, &buf, sizeof( buf ) );
write( console, &buf, n );
}
}

}
return EXIT_SUCCESS;
}

But that code doesn’t work, the keyboard states that bytes has to be
written,
but nothing show up on the dumb terminal, and nothing from the dumb
terminal
show up on the Local Console. =(

Anybody could give us a basic working example ?

That would be just great.

Sincerly yours,
Fred.

Hi Fred,

yes … I believe your coding example goes into the right direction
as long as the method ‘start’ starts a new thread.

Do I need to use select() or simply read() will block until data is
available ?

Wouldn’t it be better to use Interrupts like for the Parallel port example ?

If I write() onto the console will it do the same as a printf(…); ?

Why do I need a RAW terminal ?

The hardware technician here, told me that I must use XON/XOFF
access to the hardware, for the second step of the development stage,
and that data must not be sent at rate bigger than 512 bytes,
in order to not exceed the SerialPort target Controller internal buffer.

Where can I get more info on how to use the Serial Port with RTP ?
Is there any tutorial anywhere or documentation available online ?

I’m in a kind of rush and I’m trying to get everything up and running,
so your help is REALLY REALLY APPRECIATED ! =)

Yes, start create a pthread of Wrapper(), a stub,
which call the child version of run(),
like in Java.

void Basic_PThread::start()
{
//…
int err = pthread_create( &pid, &attr, Wrapper, (void*)this );
// …
}

static void* Basic_PThread::Wrapper( void* pthis )
{
Basic_PThread* me = (Basic_PThread*)pthis;
me->run;
return NULL;
}

Sincerly yours,
Fred.

P.S. Thanks again for your help!

Hello Fred,

my proposal is to say goodbye to the QNX4 like server concepts,
because QNX6 allows multithreaded applications. Please see my
comments at comp.os.qnx …

Armin



Hi everyone,

We had the following working code on QNX4 using qnx_proxy* and dev_*
functions
and I try to get a working equivalent example for QNX RtP,
since we have many apps using console keyboard and serial port
that we have to develop and to support our customer.

It’s basically a skeleton for writing any Keyboard/Console application
and also a skeleton for writing serial port access application.

It basically take any byte from the keyboard of a serial port dumb
terminal
and print it on the console, while any byte from the keyboard is print
on
a serial port dumb terminal.

Pretty simple and straight forward.

Here’s the QNX4 SerialChat program:

#include <stdio.h
#include <stdlib.h
#include <fcntl.h
#include <unistd.h
#include <termios.h
#include <sys/types.h
#include <sys/stat.h

#include <sys/dev.h
#include <sys/proxy.h
#include <sys/kernel.h
#include <conio.h
#include <i86.h

#define LOCAL_KEYBOARD “/dev/con1”
#define ELAN104_SERIAL “//2/dev/ser1”

int main()
{
// This is a bidirectionnal CHAT program
// between the ELAN104, the HP Dump Terminal and the Switchboard
printf("\n\rBasic QNX Serial Port CHAT program: \n\r\n\n");

// Serial Port Stuff
unsigned state;
pid_t kb_proxy;
pid_t mdm_proxy;
pid_t pid;
int kb_fd;
int mdm_fd;
int n;
char buf[80];

// Initialize and setup the Serial Port
kb_fd = open( LOCAL_KEYBOARD, O_RDWR );// Local Keyboard
mdm_fd = open( ELAN104_SERIAL, O_RDWR );// QNX-2 Elan104 Board

kb_proxy = qnx_proxy_attach( 0, 0, 0, -1 );
mdm_proxy = qnx_proxy_attach( 0, 0, 0, -1 );

dev_mode( kb_fd, 0, _DEV_MODES );
dev_mode( mdm_fd, 0, _DEV_MODES );

// Clear, then arm the proxies for future events

dev_state( kb_fd, 0, _DEV_EVENT_INPUT );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );

dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );

for(;:wink: // Infinite Loop, until CTRL-BREAK
{

// Wait for either keyboard or modem to send an input.
pid = Receive( 0, 0, 0 );

// Waiting for an event, then check the Process ID,
// Read the message and send it back to the other machine.

if ( pid == kb_proxy ) {
state = dev_state( kb_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Keyboard Console
// then Read it and Send it Back to the Modem

if ( state & _DEV_EVENT_INPUT ) {
n = read( kb_fd, &buf, sizeof( buf ) );
write( mdm_fd, &buf, n );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );
}
}
else if ( pid == mdm_proxy )
{
state = dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Modem
// then Read it and Send it Back to the Keyboard Console

if ( state & _DEV_EVENT_INPUT )
{
n = read( mdm_fd, &buf, sizeof( buf ) );
write( kb_fd, &buf, n );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );
}
}
}

printf("\nDone!\n");
return 0;
}

The only sort of QNX RtP non-working equivalent,
I could come up with from the select() documentation was:

/*

  • This example opens a console and a serial port for
  • read mode, and calls select() with a 5 second timeout.
  • It waits for data to be available on either descriptor.
    */

#include <stdio.h
#include <string.h
#include <errno.h

#include <unistd.h
#include <stdlib.h
#include <fcntl.h
#include <sys/time.h

#include <sys/types.h
#include <sys/uio.h

#include “Basic_PThread.hpp”

int max( int x, int y )
{
return ( (x)>(y) ? (x) : (y) );
}

int dev_raw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_cc[VMIN] = 1;
termios_p.c_cc[VTIME] = 0;
termios_p.c_lflag &= ~(ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag &= ~(OPOST);
return (tcsetattr (fd, TCSANOW, &termios_p));
}

int dev_unraw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_lflag |= (ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag |= (OPOST);
return (tcsetattr (fd, TCSAFLUSH, &termios_p));
}

//

http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_hpp-source.h
tml
//

http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_cpp-source.h
tml

class Device : public Basic_PThread
{
protected:
int fd;
int size_read;
char buffer[80];

struct timeval tv;
fd_set rfd;
int n;
char name[80];

public:

Device( const char* device = “/dev/ser1” )
: fd( 0 ), size_read( 0 ), n( 0 )
{
memset( buffer, 0, sizeof( buffer ) );
memset( name, 0, sizeof( name ) );
memset( &tv, 0, sizeof( tv ) );
strcpy( name, device );

// Open a file for input
if( ( fd = open( device, O_RDWR ) ) == -1 )
{
printf( “Error while opening [%s].\n”, device );
exit( 1 );
}

/*

  • Clear the set of read file descriptors, and
  • add the two we just got from the open calls.
    */
    FD_ZERO( &rfd );
    FD_SET( fd, &rfd );

/*

  • Set a 5 second timeout.
    */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

dev_raw( fd );

// > http://qdn.qnx.com/support/docs/neutrino_qrp/lib_ref/t/tcgetattr.html
// > http://qdn.qnx.com/support/docs/neutrino_qrp/audio/wavec.html

}

virtual void run()
{
for(;:wink:
{
// Read the text
size_read = read( fd, buffer, 1 );

// Test for error
if( size_read == -1 ) {
printf( “Error reading %s”, name );
exit( 1 );
}

handler();
}
}

virtual void handler() = 0;

virtual ~Device()
{
// Close the file
close( fd );
}

private:
// Prohibited:
Device( const Device& src );
const Device& operator=( const Device& src );
};

class Chat : public Device
{
Chat* chat;
public:

Chat( const char* device = “/dev/ser1”, Chat* c = NULL )
: Device( device ), chat( c ) { }

void setup( Chat* c ) { chat = c; }

virtual void ~Console() { }

virtual void handler()
{
if ( !c ) return;
c->print( buffer, size_read );
}

void print( const void* buf, size_t sz )
{
write( fd, buf, sz );
}
};

int main()
{
Chat* serial = new Chat( “/dev/ser1” );
Chat* console = new Chat( “/dev/con1”, serial );
serial->setup( console );

serial->start( 11 );
console->start(11 );

serial->join();
console->join();

for( int k = 0; k < 2000; k++ ) { printf("."); }

return 0;
}

/*********** END *****/

Something like that ?
Fred.

for(;:wink: {

switch ( n = select( 1 + max( console, serial ),
&rfd, 0, 0, &tv ) ) {
case -1:
perror( “select” );
return EXIT_FAILURE;
case 0:
puts( “select timed out” );
break;
default:
printf( “%d descriptors ready …\n”, n );
if( FD_ISSET( console, &rfd ) ) {
puts( " – console descriptor has data pending" );
n = read( console, &buf, sizeof( buf ) );
write( serial, &buf, n );
}

if( FD_ISSET( serial, &rfd ) ) {
puts( " – serial descriptor has data pending" );
n = read( serial, &buf, sizeof( buf ) );
write( console, &buf, n );
}
}

}
return EXIT_SUCCESS;
}

But that code doesn’t work, the keyboard states that bytes has to be
written,
but nothing show up on the dumb terminal, and nothing from the dumb
terminal
show up on the Local Console. =(

Anybody could give us a basic working example ?

That would be just great.

Sincerly yours,
Fred.

Fred wrote:

Hi Fred,

yes … I believe your coding example goes into the right direction
as long as the method ‘start’ starts a new thread.

Do I need to use select() or simply read() will block until data is
available ?

I would use read() if a thread has only to care about a single file
descriptor.

Wouldn’t it be better to use Interrupts like for the Parallel port example ?

Interrupt should be handled at resource manager level …

If I write() onto the console will it do the same as a printf(…); ?

Why do I need a RAW terminal ?

You can also use the serial ports in edited mode … if it make
sense.

The hardware technician here, told me that I must use XON/XOFF
access to the hardware, for the second step of the development stage,
and that data must not be sent at rate bigger than 512 bytes,
in order to not exceed the SerialPort target Controller internal buffer.

The internal buffer of e.g. /dev/ser1 is by default 2048 bytes …
you can also increase its size by a command line switch … buffer
overflows can be avoided by reading bigger amount of data from the
serial ports.

Where can I get more info on how to use the Serial Port with RTP ?
Is there any tutorial anywhere or documentation available online ?

There is an article about the usage of device controls … please
see the arcticle section of QDN.

Armin

I’m in a kind of rush and I’m trying to get everything up and running,
so your help is REALLY REALLY APPRECIATED ! =)

Yes, start create a pthread of Wrapper(), a stub,
which call the child version of run(),
like in Java.

void Basic_PThread::start()
{
//…
int err = pthread_create( &pid, &attr, Wrapper, (void*)this );
// …
}

static void* Basic_PThread::Wrapper( void* pthis )
{
Basic_PThread* me = (Basic_PThread*)pthis;
me->run;
return NULL;
}

Sincerly yours,
Fred.

P.S. Thanks again for your help!

Hello Fred,

my proposal is to say goodbye to the QNX4 like server concepts,
because QNX6 allows multithreaded applications. Please see my
comments at comp.os.qnx …

Armin



Hi everyone,

We had the following working code on QNX4 using qnx_proxy* and dev_*
functions
and I try to get a working equivalent example for QNX RtP,
since we have many apps using console keyboard and serial port
that we have to develop and to support our customer.

It’s basically a skeleton for writing any Keyboard/Console application
and also a skeleton for writing serial port access application.

It basically take any byte from the keyboard of a serial port dumb
terminal
and print it on the console, while any byte from the keyboard is print
on
a serial port dumb terminal.

Pretty simple and straight forward.

Here’s the QNX4 SerialChat program:

#include <stdio.h
#include <stdlib.h
#include <fcntl.h
#include <unistd.h
#include <termios.h
#include <sys/types.h
#include <sys/stat.h

#include <sys/dev.h
#include <sys/proxy.h
#include <sys/kernel.h
#include <conio.h
#include <i86.h

#define LOCAL_KEYBOARD “/dev/con1”
#define ELAN104_SERIAL “//2/dev/ser1”

int main()
{
// This is a bidirectionnal CHAT program
// between the ELAN104, the HP Dump Terminal and the Switchboard
printf("\n\rBasic QNX Serial Port CHAT program: \n\r\n\n");

// Serial Port Stuff
unsigned state;
pid_t kb_proxy;
pid_t mdm_proxy;
pid_t pid;
int kb_fd;
int mdm_fd;
int n;
char buf[80];

// Initialize and setup the Serial Port
kb_fd = open( LOCAL_KEYBOARD, O_RDWR );// Local Keyboard
mdm_fd = open( ELAN104_SERIAL, O_RDWR );// QNX-2 Elan104 Board

kb_proxy = qnx_proxy_attach( 0, 0, 0, -1 );
mdm_proxy = qnx_proxy_attach( 0, 0, 0, -1 );

dev_mode( kb_fd, 0, _DEV_MODES );
dev_mode( mdm_fd, 0, _DEV_MODES );

// Clear, then arm the proxies for future events

dev_state( kb_fd, 0, _DEV_EVENT_INPUT );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );

dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );

for(;:wink: // Infinite Loop, until CTRL-BREAK
{

// Wait for either keyboard or modem to send an input.
pid = Receive( 0, 0, 0 );

// Waiting for an event, then check the Process ID,
// Read the message and send it back to the other machine.

if ( pid == kb_proxy ) {
state = dev_state( kb_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Keyboard Console
// then Read it and Send it Back to the Modem

if ( state & _DEV_EVENT_INPUT ) {
n = read( kb_fd, &buf, sizeof( buf ) );
write( mdm_fd, &buf, n );
dev_arm( kb_fd, kb_proxy, _DEV_EVENT_INPUT );
}
}
else if ( pid == mdm_proxy )
{
state = dev_state( mdm_fd, 0, _DEV_EVENT_INPUT );

// If there is an Input from Modem
// then Read it and Send it Back to the Keyboard Console

if ( state & _DEV_EVENT_INPUT )
{
n = read( mdm_fd, &buf, sizeof( buf ) );
write( kb_fd, &buf, n );
dev_arm( mdm_fd, mdm_proxy, _DEV_EVENT_INPUT );
}
}
}

printf("\nDone!\n");
return 0;
}

The only sort of QNX RtP non-working equivalent,
I could come up with from the select() documentation was:

/*

  • This example opens a console and a serial port for
  • read mode, and calls select() with a 5 second timeout.
  • It waits for data to be available on either descriptor.
    */

#include <stdio.h
#include <string.h
#include <errno.h

#include <unistd.h
#include <stdlib.h
#include <fcntl.h
#include <sys/time.h

#include <sys/types.h
#include <sys/uio.h

#include “Basic_PThread.hpp”

int max( int x, int y )
{
return ( (x)>(y) ? (x) : (y) );
}

int dev_raw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_cc[VMIN] = 1;
termios_p.c_cc[VTIME] = 0;
termios_p.c_lflag &= ~(ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag &= ~(OPOST);
return (tcsetattr (fd, TCSANOW, &termios_p));
}

int dev_unraw (int fd)
{
struct termios termios_p;

if (tcgetattr (fd, &termios_p))
return (-1);

termios_p.c_lflag |= (ECHO | ICANON | ISIG |
ECHOE | ECHOK | ECHONL);
termios_p.c_oflag |= (OPOST);
return (tcsetattr (fd, TCSAFLUSH, &termios_p));
}

//

http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_hpp-source.h
tml
//

http://j2k.sourceforge.net/docs/en/html/445_Posix_Basic_PThread_cpp-source.h
tml

class Device : public Basic_PThread
{
protected:
int fd;
int size_read;
char buffer[80];

struct timeval tv;
fd_set rfd;
int n;
char name[80];

public:

Device( const char* device = “/dev/ser1” )
: fd( 0 ), size_read( 0 ), n( 0 )
{
memset( buffer, 0, sizeof( buffer ) );
memset( name, 0, sizeof( name ) );
memset( &tv, 0, sizeof( tv ) );
strcpy( name, device );

// Open a file for input
if( ( fd = open( device, O_RDWR ) ) == -1 )
{
printf( “Error while opening [%s].\n”, device );
exit( 1 );
}

/*

  • Clear the set of read file descriptors, and
  • add the two we just got from the open calls.
    */
    FD_ZERO( &rfd );
    FD_SET( fd, &rfd );

/*

  • Set a 5 second timeout.
    */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

dev_raw( fd );

// > http://qdn.qnx.com/support/docs/neutrino_qrp/lib_ref/t/tcgetattr.html
// > http://qdn.qnx.com/support/docs/neutrino_qrp/audio/wavec.html

}

virtual void run()
{
for(;:wink:
{
// Read the text
size_read = read( fd, buffer, 1 );

// Test for error
if( size_read == -1 ) {
printf( “Error reading %s”, name );
exit( 1 );
}

handler();
}
}

virtual void handler() = 0;

virtual ~Device()
{
// Close the file
close( fd );
}

private:
// Prohibited:
Device( const Device& src );
const Device& operator=( const Device& src );
};

class Chat : public Device
{
Chat* chat;
public:

Chat( const char* device = “/dev/ser1”, Chat* c = NULL )
: Device( device ), chat( c ) { }

void setup( Chat* c ) { chat = c; }

virtual void ~Console() { }

virtual void handler()
{
if ( !c ) return;
c->print( buffer, size_read );
}

void print( const void* buf, size_t sz )
{
write( fd, buf, sz );
}
};

int main()
{
Chat* serial = new Chat( “/dev/ser1” );
Chat* console = new Chat( “/dev/con1”, serial );
serial->setup( console );

serial->start( 11 );
console->start(11 );

serial->join();
console->join();

for( int k = 0; k < 2000; k++ ) { printf("."); }

return 0;
}

/*********** END *****/

Something like that ?
Fred.

for(;:wink: {

switch ( n = select( 1 + max( console, serial ),
&rfd, 0, 0, &tv ) ) {
case -1:
perror( “select” );
return EXIT_FAILURE;
case 0:
puts( “select timed out” );
break;
default:
printf( “%d descriptors ready …\n”, n );
if( FD_ISSET( console, &rfd ) ) {
puts( " – console descriptor has data pending" );
n = read( console, &buf, sizeof( buf ) );
write( serial, &buf, n );
}

if( FD_ISSET( serial, &rfd ) ) {
puts( " – serial descriptor has data pending" );
n = read( serial, &buf, sizeof( buf ) );
write( console, &buf, n );
}
}

}
return EXIT_SUCCESS;
}

But that code doesn’t work, the keyboard states that bytes has to be
written,
but nothing show up on the dumb terminal, and nothing from the dumb
terminal
show up on the Local Console. =(

Anybody could give us a basic working example ?

That would be just great.

Sincerly yours,
Fred.