/*
/////////////////////////////////////////////////////////////////////////////
// $Header: $
//
// Copyright (c) 2000 - Rosimildo da Silva
//  
// MODULE DESCRIPTION: 
// This module implements the input devices interface used by MicroWindows
// in an embedded system environment.
//
// MODIFICATION/HISTORY:
//
// $Log: $
//
/////////////////////////////////////////////////////////////////////////////
*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <mqueue.h>   /* POSIX message queue  */

#include <rtems/mw_uid.h>

static mqd_t           mq;
static int open_count = 0;

/* open a message queue with the kernel */
int uid_open_queue( const char *q_name, int flags, size_t max_msgs )
{
   if( !open_count )
   {
      struct mq_attr  attr;
      attr.mq_maxmsg  = max_msgs;
      attr.mq_msgsize = sizeof( struct MW_UID_MESSAGE );
      attr.mq_flags = flags;
      mq = mq_open( q_name, flags , 0x777, &attr );
      if( mq == -1 ) 
      {
         return -1;
      }
   }
   open_count++;
   return 0;
}


/* close message queue */
int uid_close_queue( void )
{
  if( open_count == 1 )
  {
     mq_close( mq );
     mq = -1;
  }
  open_count--;
  return 0;
}

/* reads for a message from the device */
int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout )
{
  unsigned int priority = 0;
  struct   timespec tm;
  tm.tv_sec  = timeout/1000;
  tm.tv_nsec = 100000*( timeout % 1000 );
  return mq_timedreceive( mq, ( void *)m, sizeof( struct MW_UID_MESSAGE ), &priority, &tm );
}


/* 
 * add a message to the queue of events. This method cna be used to
 * simulate hardware events, and it can be very handy during development
 * a new interface.
 */
int uid_send_message( struct MW_UID_MESSAGE *m )
{
   return mq_send( mq, ( void * )m, sizeof( struct MW_UID_MESSAGE ), 0 );
}

/* 
 * register the device to insert events to the message
 * queue named as the value passed in q_name 
 */
int uid_register_device( int fd, const char *q_name )
{
  return ioctl( fd, MW_UID_REGISTER_DEVICE, q_name );
}

/* tell this device to stop adding events to the queue */
int uid_unregister_device( int fd )
{
  return ioctl( fd, MW_UID_UNREGISTER_DEVICE, NULL );
}
