summaryrefslogtreecommitdiff
path: root/cpukit/libmisc/fb/mw_uid.c
blob: c3933d6e9917595e1bb9d6be9d53be3dee8d7b84 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/**
 * @file
 *
 * @ingroup libmisc_fb_mw Input Devices for MicroWindows
 *
 * @brief MicroWindows UID
 *
 * This module implements the input devices interface used by MicroWindows
 * in an embedded system environment.  It uses the RTEMS message queue as
 * the repository for the messages posted by the devices registered.
 */

/*
 * Copyright (c) 2000 - Rosimildo da Silva
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <rtems.h>

#include <rtems/mw_uid.h>
#include <rtems/seterr.h>

static rtems_id  queue_id = 0;
static int       open_count = 0;

/*
#define MW_DEBUG_ON     1
*/

/* open a message queue with the kernel */
int uid_open_queue(
  const char *q_name,
  int         flags RTEMS_UNUSED,
  size_t      max_msgs
)
{
  rtems_status_code status;

  /*
   * For the first device calling this function we would create the queue.
   * It is assumed that this call is done at initialization, and no concerns
   * regarding multi-threading is taken in consideration here.
   */
  if ( open_count ) {
    open_count++;
    return 0;
  }

  status = rtems_message_queue_create(
    rtems_build_name( q_name[0], q_name[1], q_name[2], q_name[3] ),
    max_msgs,
    sizeof( struct MW_UID_MESSAGE ),
    RTEMS_FIFO | RTEMS_LOCAL,
    &queue_id
  );
  if ( status != RTEMS_SUCCESSFUL ) {
    #ifdef MW_DEBUG_ON
      printk( "UID_Queue: error creating queue: %d\n", status );
     #endif
    return -1;
  }
  #ifdef MW_DEBUG_ON
    printk( "UID_Queue: id=%X\n", queue_id );
  #endif
  open_count++;
  return 0;
}


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

/* reads for a message from the device */
int uid_read_message( struct MW_UID_MESSAGE *m, unsigned long timeout )
{
  rtems_status_code status;
  size_t            size = 0;
  int               wait = (timeout != 0);
  int ticks = RTEMS_MICROSECONDS_TO_TICKS(timeout * 1000);

  if (timeout == (unsigned long) -1) {
    ticks = RTEMS_NO_TIMEOUT;
  } else if (timeout && ticks == 0) {
    /* if timeout greater than 0 and smaller than a tick, round up to avoid
     * unintentionally RTEMS_NO_TIMEOUT
     */
    ticks = 1;
  }

  status = rtems_message_queue_receive(
   queue_id,
   (void*)m,
   &size,
   wait ? RTEMS_WAIT : RTEMS_NO_WAIT,
   ticks
  );

  if( status == RTEMS_SUCCESSFUL ) {
     return size;
  } else if( ( status == RTEMS_UNSATISFIED ) || ( status == RTEMS_TIMEOUT ) ) {
     rtems_set_errno_and_return_minus_one( ETIMEDOUT );
  }
  /* Here we have one error condition */
  #ifdef MW_DEBUG_ON
    printk( "UID_Queue: error reading queue: %d\n", status );
  #endif
  return -1;
}

/*
 * add a message to the queue of events. This method can 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 )
{
  rtems_status_code status;
  status = rtems_message_queue_send(
    queue_id, ( void * )m, sizeof( struct MW_UID_MESSAGE ) );
  return (status == RTEMS_SUCCESSFUL) ? 0 : -1;
}

/*
 * 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 );
}

/* set the keyboard */
int uid_set_kbd_mode( int fd, int mode, int *old_mode )
{
  if (ioctl( fd, MV_KDGKBMODE, old_mode) < 0) {
     return -1;
  }
  if (ioctl(fd, MV_KDSKBMODE, mode ) < 0 ) {
     return -1;
  }
  return 0;
}