summaryrefslogtreecommitdiffstats
path: root/cpukit/include/rtems/termiostypes.h
blob: b3cac66e9278c76f78b2d47cebf1e49e43428b83 (plain) (blame)
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
/**
 * @file rtems/termiostypes.h
 *
 * RTEMS termios device support internal data structures
 */

/*
 *  COPYRIGHT (c) 1989-2011.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#ifndef  __TERMIOSTYPES_H
#define  __TERMIOSTYPES_H

#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/assoc.h>
#include <rtems/chain.h>
#include <sys/ioccom.h>
#include <stdint.h>
#include <termios.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 *  @defgroup TermiostypesSupport RTEMS Termios Device Support
 *
 *  @ingroup libcsupport
 *
 *  @brief RTEMS Termios Device Support Internal Data Structures
 */

/*
 * Wakeup callback data structure
 */
struct ttywakeup {
  void      (*sw_pfn)(struct termios *tty, void *arg);
  void      *sw_arg;
};

/*
 * Variables associated with the character buffer
 */
struct rtems_termios_rawbuf {
  char *theBuf;
  volatile unsigned int  Head;
  volatile unsigned int  Tail;
  volatile unsigned int  Size;
  rtems_id    Semaphore;
};

typedef enum {
  TERMIOS_POLLED,
  TERMIOS_IRQ_DRIVEN,
  TERMIOS_TASK_DRIVEN,
  TERMIOS_IRQ_SERVER_DRIVEN
} rtems_termios_device_mode;

struct rtems_termios_tty;

/**
 * @brief Termios device context.
 *
 * @see RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER(),
 * rtems_termios_device_context_initialize() and
 * rtems_termios_device_install().
 */
typedef struct rtems_termios_device_context {
  union {
    /* Used for TERMIOS_POLLED and TERMIOS_IRQ_DRIVEN */
    rtems_interrupt_lock interrupt;

    /* Used for TERMIOS_IRQ_SERVER_DRIVEN or TERMIOS_TASK_DRIVEN */
    rtems_id mutex;
  } lock;

  void ( *lock_acquire )(
    struct rtems_termios_device_context *,
    rtems_interrupt_lock_context *
  );

  void ( *lock_release )(
    struct rtems_termios_device_context *,
    rtems_interrupt_lock_context *
  );
} rtems_termios_device_context;

void rtems_termios_device_lock_acquire_default(
  rtems_termios_device_context *ctx,
  rtems_interrupt_lock_context *lock_context
);

void rtems_termios_device_lock_release_default(
  rtems_termios_device_context *ctx,
  rtems_interrupt_lock_context *lock_context
);

/**
 * @brief Initializes a device context.
 *
 * @param[in] context The Termios device context.
 * @param[in] name The name for the interrupt lock.  This name must be a
 *   string persistent throughout the life time of this lock.  The name is only
 *   used if profiling is enabled.
 */
RTEMS_INLINE_ROUTINE void rtems_termios_device_context_initialize(
  rtems_termios_device_context *context,
  const char                   *name
)
{
  rtems_interrupt_lock_initialize( &context->lock.interrupt, name );
  context->lock_acquire = rtems_termios_device_lock_acquire_default;
  context->lock_release = rtems_termios_device_lock_release_default;
}

/**
 * @brief Initializer for static initialization of Termios device contexts.
 *
 * @param name The name for the interrupt lock.  It must be a string.  The name
 *   is only used if profiling is enabled.
 */
#define RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( name ) \
  { \
    { RTEMS_INTERRUPT_LOCK_INITIALIZER( name ) }, \
    rtems_termios_device_lock_acquire_default, \
    rtems_termios_device_lock_release_default \
  }

/**
 * @brief Termios device handler.
 *
 * @see rtems_termios_device_install().
 */
typedef struct {
  /**
   * @brief First open of this device.
   *
   * @param[in] tty The Termios control.  This parameter may be passed to
   *   interrupt service routines since it must be provided for the
   *   rtems_termios_enqueue_raw_characters() and
   *   rtems_termios_dequeue_characters() functions.
   * @param[in] context The Termios device context.
   * @param[in] term The current Termios attributes.
   * @param[in] args The open/close arguments.  This is parameter provided to
   *   support legacy drivers.  It must not be used by new drivers.
   *
   * @retval true Successful operation.
   * @retval false Cannot open device.
   *
   * @see rtems_termios_get_device_context() and rtems_termios_set_best_baud().
   */
  bool (*first_open)(
    struct rtems_termios_tty      *tty,
    rtems_termios_device_context  *context,
    struct termios                *term,
    rtems_libio_open_close_args_t *args
  );

  /**
   * @brief Last close of this device.
   *
   * @param[in] tty The Termios control.
   * @param[in] context The Termios device context.
   * @param[in] args The open/close arguments.  This is parameter provided to
   *   support legacy drivers.  It must not be used by new drivers.
   */
  void (*last_close)(
    struct rtems_termios_tty      *tty,
    rtems_termios_device_context  *context,
    rtems_libio_open_close_args_t *args
  );

  /**
   * @brief Polled read.
   *
   * In case mode is TERMIOS_IRQ_DRIVEN, TERMIOS_IRQ_SERVER_DRIVEN or
   * TERMIOS_TASK_DRIVEN, then data is received via
   * rtems_termios_enqueue_raw_characters().
   *
   * @param[in] context The Termios device context.
   *
   * @retval char The received data encoded as unsigned char.
   * @retval -1 No data currently available.
   */
  int (*poll_read)(rtems_termios_device_context *context);

  /**
   * @brief Polled write in case mode is TERMIOS_POLLED or write support
   * otherwise.
   *
   * @param[in] context The Termios device context.
   * @param[in] buf The output buffer.
   * @param[in] len The output buffer length in characters.
   */
  void (*write)(
    rtems_termios_device_context *context,
    const char *buf,
    size_t len
  );

  /**
   * @brief Set attributes after a Termios settings change.
   *
   * @param[in] context The Termios device context.
   * @param[in] term The new Termios attributes.
   *
   * @retval true Successful operation.
   * @retval false Invalid attributes.
   */
  bool (*set_attributes)(
    rtems_termios_device_context *context,
    const struct termios         *term
  );

  /**
   * @brief IO control handler.
   *
   * Invoked in case the Termios layer cannot deal with the IO request.
   *
   * @param[in] context The Termios device context.
   * @param[in] request The IO control request.
   * @param[in] buffer The IO control buffer.
   */
  int (*ioctl)(
    rtems_termios_device_context *context,
    ioctl_command_t               request,
    void                         *buffer
  );

  /**
   * @brief Termios device mode.
   */
  rtems_termios_device_mode mode;
} rtems_termios_device_handler;

/**
 * @brief Termios device flow control handler.
 *
 * @see rtems_termios_device_install().
 */
typedef struct {
  /**
   * @brief Indicate to stop remote transmitter.
   *
   * @param[in] context The Termios device context.
   */
  void (*stop_remote_tx)(rtems_termios_device_context *context);

  /**
   * @brief Indicate to start remote transmitter.
   *
   * @param[in] context The Termios device context.
   */
  void (*start_remote_tx)(rtems_termios_device_context *context);
} rtems_termios_device_flow;

/**
 * @brief Termios device node for installed devices.
 *
 * @see rtems_termios_device_install().
 */
typedef struct rtems_termios_device_node {
  rtems_chain_node                    node;
  rtems_device_major_number           major;
  rtems_device_minor_number           minor;
  const rtems_termios_device_handler *handler;
  const rtems_termios_device_flow    *flow;
  rtems_termios_device_context       *context;
  struct rtems_termios_tty           *tty;
} rtems_termios_device_node;

/*
 * Variables associated with each termios instance.
 * One structure for each hardware I/O device.
 */
typedef struct rtems_termios_tty {
  /*
   * Linked-list of active TERMIOS devices
   */
  struct rtems_termios_tty  *forw;
  struct rtems_termios_tty  *back;

  /*
   * How many times has this device been opened
   */
  int    refcount;

  /*
   * This device
   */
  rtems_device_major_number  major;
  rtems_device_minor_number  minor;

  /*
   * Mutual-exclusion semaphores
   */
  rtems_id  isem;
  rtems_id  osem;

  /*
   * The canonical (cooked) character buffer
   */
  char    *cbuf;
  int    ccount;
  int    cindex;

  /*
   * Keep track of cursor (printhead) position
   */
  int    column;
  int    read_start_column;

  /*
   * The ioctl settings
   */
  struct termios  termios;
  rtems_interval  vtimeTicks;

  /*
   * Raw input character buffer
   */
  struct rtems_termios_rawbuf rawInBuf;
  uint32_t                    rawInBufSemaphoreOptions;
  rtems_interval              rawInBufSemaphoreTimeout;
  rtems_interval              rawInBufSemaphoreFirstTimeout;
  unsigned int                rawInBufDropped;  /* Statistics */

  /*
   * Raw output character buffer
   */
  struct rtems_termios_rawbuf rawOutBuf;
  int  t_dqlen; /* count of characters dequeued from device */
  enum {rob_idle, rob_busy, rob_wait }  rawOutBufState;

  /*
   * Callbacks to device-specific routines
   */
  rtems_termios_callbacks  device;

  /**
   * @brief Context for legacy devices using the callbacks.
   */
  rtems_termios_device_context legacy_device_context;

  /**
   * @brief The device handler.
   */
  rtems_termios_device_handler handler;

  /**
   * @brief The device flow control handler.
   */
  rtems_termios_device_flow flow;

  volatile unsigned int    flow_ctrl;
  unsigned int             lowwater,highwater;

  /*
   * I/O task IDs (for task-driven drivers)
   */
  rtems_id                rxTaskId;
  rtems_id                txTaskId;

  /*
   * line discipline related stuff
   */
  int t_line;   /* id of line discipline                       */
  void *t_sc;   /* hook for discipline-specific data structure */

  /*
   * Wakeup callback variables
   */
  struct ttywakeup tty_snd;
  struct ttywakeup tty_rcv;
  bool             tty_rcvwakeup;

  /**
   * @brief Corresponding device node.
   */
  rtems_termios_device_node *device_node;

  /**
   * @brief Context for device driver.
   */
  rtems_termios_device_context *device_context;
} rtems_termios_tty;

/**
 * @brief Installs a Termios device.
 *
 * The installed Termios device may be removed via unlink().
 *
 * @param[in] device_file The device file path.
 * @param[in] handler The device handler.  It must be persistent throughout the
 *   installed time of the device.
 * @param[in] flow The device flow control handler.  The device flow control
 *   handler are optional and may be @c NULL.  If present must be persistent
 *   throughout the installed time of the device.
 * @param[in] context The device context.  It must be persistent throughout the
 *   installed time of the device.
 *
 * @retval RTEMS_SUCCESSFUL Successful operation.
 * @retval RTEMS_NO_MEMORY Not enough memory to create a device node.
 * @retval RTEMS_UNSATISFIED Creation of the device file failed.
 * @retval RTEMS_INCORRECT_STATE Termios is not initialized.
 *
 * @see rtems_termios_get_device_context().
 */
rtems_status_code rtems_termios_device_install(
  const char                         *device_file,
  const rtems_termios_device_handler *handler,
  const rtems_termios_device_flow    *flow,
  rtems_termios_device_context       *context
);

/**
 * @brief Returns the device context of an installed Termios device.
 *
 * @param[in] tty The Termios control.
 */
RTEMS_INLINE_ROUTINE void *rtems_termios_get_device_context(
  const rtems_termios_tty *tty
)
{
  return tty->device_context;
}

/**
 * @brief Acquires the device lock.
 *
 * @param[in] context The device context.
 * @param[in] lock_context The local interrupt lock context for an acquire and
 *   release pair.
 */
RTEMS_INLINE_ROUTINE void rtems_termios_device_lock_acquire(
  rtems_termios_device_context *context,
  rtems_interrupt_lock_context *lock_context
)
{
  ( *context->lock_acquire )( context, lock_context );
}

/**
 * @brief Releases the device lock.
 *
 * @param[in] context The device context.
 * @param[in] lock_context The local interrupt lock context for an acquire and
 *   release pair.
 */
RTEMS_INLINE_ROUTINE void rtems_termios_device_lock_release(
  rtems_termios_device_context *context,
  rtems_interrupt_lock_context *lock_context
)
{
  ( *context->lock_release )( context, lock_context );
}

/**
 * @brief Sets the best baud value in the Termios control.
 *
 * The valid Termios baud values are between 0 and 460800.  The Termios baud
 * value is chosen which minimizes the difference to the value specified.
 *
 * @param[in] term The Termios attributes.
 * @param[in] baud The current baud setting of the device.
 */
void rtems_termios_set_best_baud(
  struct termios *term,
  uint32_t        baud
);

struct rtems_termios_linesw {
  int (*l_open) (struct rtems_termios_tty *tp);
  int (*l_close)(struct rtems_termios_tty *tp);
  int (*l_read )(struct rtems_termios_tty *tp,rtems_libio_rw_args_t *args);
  int (*l_write)(struct rtems_termios_tty *tp,rtems_libio_rw_args_t *args);
  int (*l_rint )(int c,struct rtems_termios_tty *tp);
  int (*l_start)(struct rtems_termios_tty *tp);
  int (*l_ioctl)(struct rtems_termios_tty *tp,rtems_libio_ioctl_args_t *args);
  int (*l_modem)(struct rtems_termios_tty *tp,int flags);
};

/*
 * FIXME: this should move to termios.h!
 */
void rtems_termios_rxirq_occured(struct rtems_termios_tty *tty);

/*
 * FIXME: this should move to termios.h!
 * put a string to output ring buffer
 */
void rtems_termios_puts (
  const void               *buf,
  size_t                    len,
  struct rtems_termios_tty *tty
);

/*
 * global hooks for line disciplines
 */
extern struct rtems_termios_linesw rtems_termios_linesw[];
extern int   rtems_termios_nlinesw;

#define TTYDISC   0    /* termios tty line discipline */
#define TABLDISC  3    /* tablet discipline */
#define SLIPDISC  4    /* serial IP discipline */
#define PPPDISC   5    /* PPP discipline */
#define MAXLDISC  8

/* baudrate xxx integer type */
typedef uint32_t rtems_termios_baud_t;

/**
 *  @brief RTEMS Termios Baud Table
 */
extern const rtems_assoc_t rtems_termios_baud_table [];

/**
 *  @brief Converts the Integral Baud value @a baud to the Termios Control Flag
 *  Representation
 *
 *  @retval B0 Invalid baud value or a baud value of 0.
 *  @retval other Baud constant according to @a baud.
 */
speed_t rtems_termios_number_to_baud(rtems_termios_baud_t baud);

/**
 *  @brief Converts the baud flags to an integral baud value.
 *
 *  @retval 0 Invalid baud value or a baud value of @c B0.
 *  @retval other Integral baud value.
 */
rtems_termios_baud_t rtems_termios_baud_to_number(speed_t baud);

/**
 *  @brief Convert Bxxx Constant to Index
 */
int  rtems_termios_baud_to_index(rtems_termios_baud_t termios_baud);

/**
 * @brief Sets the initial @a baud in the Termios context @a tty.
 *
 * @retval 0 Successful operation.
 * @retval -1 Invalid baud value.
 */
int rtems_termios_set_initial_baud(
  struct rtems_termios_tty *tty,
  rtems_termios_baud_t baud
);

/**
 * @brief Termios kqueue() filter filesystem node handler
 *
 * Real implementation is provided by libbsd.
 */
int rtems_termios_kqfilter(
  rtems_libio_t *iop,
  struct knote  *kn
);

/**
 * @brief Termios mmap() filter filesystem node handler
 *
 * Real implementation is provided by libbsd.
 */
int rtems_termios_mmap(
  rtems_libio_t *iop,
  void         **addr,
  size_t         len,
  int            prot,
  off_t          off
);

/**
 * @brief Termios poll() filesystem node handler.
 *
 * Real implementation is provided by libbsd.
 */
int rtems_termios_poll(
  rtems_libio_t *iop,
  int            events
);

#define RTEMS_IO_SNDWAKEUP _IOW('t', 11, struct ttywakeup ) /* send tty wakeup */
#define RTEMS_IO_RCVWAKEUP _IOW('t', 12, struct ttywakeup ) /* recv tty wakeup */

#define	OLCUC		0x00000100	/* map lower case to upper case on output */
#define	IUCLC		0x00004000	/* map upper case to lower case on input */

#define RTEMS_TERMIOS_NUMBER_BAUD_RATES 25

#ifdef __cplusplus
}
#endif

#endif  /* TERMIOSTYPES_H */