/ addons / rtdm / rtdm.h
rtdm.h
  1  /**
  2   * @file
  3   * Real-Time Driver Model for RTAI, user API header
  4   *
  5   * @note Copyright (C) 2005, 2006 Jan Kiszka <jan.kiszka@web.de>
  6   * @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
  7   * @note Copyright (C) 2005-2010 Paolo Mantegazza <mantegazza@aero.polimi.it>
  8   *
  9   * RTAI is free software; you can redistribute it and/or modify it
 10   * under the terms of the GNU General Public License as published by
 11   * the Free Software Foundation; either version 2 of the License, or
 12   * (at your option) any later version.
 13   *
 14   * RTAI is distributed in the hope that it will be useful, but
 15   * WITHOUT ANY WARRANTY; without even the implied warranty of
 16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17   * General Public License for more details.
 18   *
 19   * You should have received a copy of the GNU General Public License
 20   * along with RTAI; if not, write to the Free Software Foundation,
 21   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 22   *
 23   * @ingroup userapi
 24   */
 25  
 26  /*!
 27   * @defgroup rtdm Real-Time Driver Model
 28   *
 29   * The Real-Time Driver Model (RTDM) provides a unified interface to
 30   * both users and developers of real-time device
 31   * drivers. Specifically, it addresses the constraints of mixed
 32   * RT/non-RT systems like RTAI. RTDM conforms to POSIX
 33   * semantics (IEEE Std 1003.1) where available and applicable.
 34   *
 35   * @b API @b Revision: 8
 36   */
 37  
 38  /*!
 39   * @ingroup rtdm
 40   * @defgroup userapi User API
 41   *
 42   * This is the upper interface of RTDM provided to application programs both
 43   * in kernel and user space. Note that certain functions may not be
 44   * implemented by every device. Refer to the @ref profiles "Device Profiles"
 45   * for precise information.
 46   */
 47  
 48  #ifndef _RTDM_H
 49  #define _RTDM_H
 50  
 51  #define RTDM_INDX  15
 52  
 53  #define __rtdm_fdcount          0
 54  #define __rtdm_open             1
 55  #define __rtdm_socket           2
 56  #define __rtdm_close            3
 57  #define __rtdm_ioctl            4
 58  #define __rtdm_read             5
 59  #define __rtdm_write            6
 60  #define __rtdm_recvmsg          7
 61  #define __rtdm_sendmsg          8
 62  #define __rtdm_select           9
 63  
 64  #ifdef __KERNEL__
 65  
 66  #include <linux/fcntl.h>
 67  #include <linux/ioctl.h>
 68  #include <linux/sched.h>
 69  #include <linux/socket.h>
 70  
 71  typedef u32 socklen_t;
 72  typedef struct task_struct rtdm_user_info_t;
 73  
 74  #else /* !__KERNEL__ */
 75  
 76  #include <fcntl.h>
 77  #include <stdint.h>
 78  #include <sys/ioctl.h>
 79  #include <sys/socket.h>
 80  
 81  #endif /* !__KERNEL__ */
 82  
 83  /*!
 84   * @addtogroup rtdm
 85   * @{
 86   */
 87  
 88  /*!
 89   * @anchor api_versioning @name API Versioning
 90   * @{ */
 91  /** Common user and driver API version */
 92  #define RTDM_API_VER			8
 93  
 94  /** Minimum API revision compatible with the current release */
 95  #define RTDM_API_MIN_COMPAT_VER		6
 96  /** @} API Versioning */
 97  
 98  /** RTDM type for representing absolute dates. Its base type is a 64 bit
 99   *  unsigned integer. The unit is 1 nanosecond. */
100  typedef int64_t nanosecs_abs_t;
101  
102  /** RTDM type for representing relative intervals. Its base type is a 64 bit
103   *  signed integer. The unit is 1 nanosecond. Relative intervals can also
104   *  encode the special timeouts "infinite" and "non-blocking", see
105   *  @ref RTDM_TIMEOUT_xxx. */
106  typedef int64_t nanosecs_rel_t;
107  
108  /*!
109   * @anchor RTDM_TIMEOUT_xxx @name RTDM_TIMEOUT_xxx
110   * Special timeout values
111   * @{ */
112  /** Block forever. */
113  #define RTDM_TIMEOUT_INFINITE		0
114  
115  /** Any negative timeout means non-blocking. */
116  #define RTDM_TIMEOUT_NONE		(-1)
117  /** @} RTDM_TIMEOUT_xxx */
118  /** @} rtdm */
119  
120  /*!
121   * @addtogroup profiles
122   * @{
123   */
124  
125  /*!
126   * @anchor RTDM_CLASS_xxx   @name RTDM_CLASS_xxx
127   * Device classes
128   * @{ */
129  #define RTDM_CLASS_PARPORT		1
130  #define RTDM_CLASS_SERIAL		2
131  #define RTDM_CLASS_CAN			3
132  #define RTDM_CLASS_NETWORK		4
133  #define RTDM_CLASS_RTMAC		5
134  #define RTDM_CLASS_TESTING		6
135  #define RTDM_CLASS_RTIPC                7
136  /*
137  #define RTDM_CLASS_USB			?
138  #define RTDM_CLASS_FIREWIRE		?
139  #define RTDM_CLASS_INTERBUS		?
140  #define RTDM_CLASS_PROFIBUS		?
141  #define ...
142  */
143  #define RTDM_CLASS_EXPERIMENTAL		224
144  #define RTDM_CLASS_MAX			255
145  /** @} RTDM_CLASS_xxx */
146  
147  #define RTDM_SUBCLASS_GENERIC		(-1)
148  
149  #define RTIOC_TYPE_COMMON		0
150  
151  /*!
152   * @anchor device_naming    @name Device Naming
153   * Maximum length of device names (excluding the final null character)
154   * @{
155   */
156  #define RTDM_MAX_DEVNAME_LEN		31
157  /** @} Device Naming */
158  
159  /**
160   * Device information
161   */
162  typedef struct rtdm_device_info {
163  	/** Device flags, see @ref dev_flags "Device Flags" for details */
164  	int device_flags;
165  
166  	/** Device class ID, see @ref RTDM_CLASS_xxx */
167  	int device_class;
168  
169  	/** Device sub-class, either RTDM_SUBCLASS_GENERIC or a
170  	 *  RTDM_SUBCLASS_xxx definition of the related @ref profiles
171  	 *  "Device Profile" */
172  	int device_sub_class;
173  
174  	/** Supported device profile version */
175  	int profile_version;
176  } rtdm_device_info_t;
177  
178  /*!
179   * @anchor RTDM_PURGE_xxx_BUFFER    @name RTDM_PURGE_xxx_BUFFER
180   * Flags selecting buffers to be purged
181   * @{ */
182  #define RTDM_PURGE_RX_BUFFER		0x0001
183  #define RTDM_PURGE_TX_BUFFER		0x0002
184  /** @} RTDM_PURGE_xxx_BUFFER*/
185  
186  /*!
187   * @anchor common_IOCTLs    @name Common IOCTLs
188   * The following IOCTLs are common to all device profiles.
189   * @{
190   */
191  
192  /**
193   * Retrieve information about a device or socket.
194   * @param[out] arg Pointer to information buffer (struct rtdm_device_info)
195   */
196  #define RTIOC_DEVICE_INFO \
197  	_IOR(RTIOC_TYPE_COMMON, 0x00, struct rtdm_device_info)
198  
199  /**
200   * Purge internal device or socket buffers.
201   * @param[in] arg Purge mask, see @ref RTDM_PURGE_xxx_BUFFER
202   */
203  #define RTIOC_PURGE		_IOW(RTIOC_TYPE_COMMON, 0x10, int)
204  /** @} Common IOCTLs */
205  /** @} rtdm */
206  
207  /* Internally used for mapping socket functions on IOCTLs */
208  struct _rtdm_getsockopt_args {
209  	int level;
210  	int optname;
211  	void *optval;
212  	socklen_t *optlen;
213  };
214  
215  struct _rtdm_setsockopt_args {
216  	int level;
217  	int optname;
218  	const void *optval;
219  	socklen_t optlen;
220  };
221  
222  struct _rtdm_getsockaddr_args {
223  	struct sockaddr *addr;
224  	socklen_t *addrlen;
225  };
226  
227  struct _rtdm_setsockaddr_args {
228  	const struct sockaddr *addr;
229  	socklen_t addrlen;
230  };
231  
232  #define _RTIOC_GETSOCKOPT	_IOW(RTIOC_TYPE_COMMON, 0x20,		\
233  				     struct _rtdm_getsockopt_args)
234  #define _RTIOC_SETSOCKOPT	_IOW(RTIOC_TYPE_COMMON, 0x21,		\
235  				     struct _rtdm_setsockopt_args)
236  #define _RTIOC_BIND		_IOW(RTIOC_TYPE_COMMON, 0x22,		\
237  				     struct _rtdm_setsockaddr_args)
238  #define _RTIOC_CONNECT		_IOW(RTIOC_TYPE_COMMON, 0x23,		\
239  				     struct _rtdm_setsockaddr_args)
240  #define _RTIOC_LISTEN		_IOW(RTIOC_TYPE_COMMON, 0x24,		\
241  				     int)
242  #define _RTIOC_ACCEPT		_IOW(RTIOC_TYPE_COMMON, 0x25,		\
243  				     struct _rtdm_getsockaddr_args)
244  #define _RTIOC_GETSOCKNAME	_IOW(RTIOC_TYPE_COMMON, 0x26,		\
245  				     struct _rtdm_getsockaddr_args)
246  #define _RTIOC_GETPEERNAME	_IOW(RTIOC_TYPE_COMMON, 0x27,		\
247  				     struct _rtdm_getsockaddr_args)
248  #define _RTIOC_SHUTDOWN		_IOW(RTIOC_TYPE_COMMON, 0x28,		\
249  				     int)
250  
251  #ifdef __KERNEL__
252  int __rt_dev_open(rtdm_user_info_t *user_info, const char *path, int oflag);
253  int __rt_dev_socket(rtdm_user_info_t *user_info, int protocol_family,
254  		    int socket_type, int protocol);
255  int __rt_dev_close(rtdm_user_info_t *user_info, int fd);
256  int __rt_dev_ioctl(rtdm_user_info_t *user_info, int fd, int request, ...);
257  ssize_t __rt_dev_read(rtdm_user_info_t *user_info, int fd, void *buf,
258  		      size_t nbyte);
259  ssize_t __rt_dev_write(rtdm_user_info_t *user_info, int fd, const void *buf,
260  		       size_t nbyte);
261  ssize_t __rt_dev_recvmsg(rtdm_user_info_t *user_info, int fd,
262  			 struct msghdr *msg, int flags);
263  ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info, int fd,
264  			 const struct msghdr *msg, int flags);
265  #include "select.h"
266  int __rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout, struct xnselector *selector, int space);
267  #endif /* __KERNEL__ */
268  
269  /* Define RTDM_NO_DEFAULT_USER_API to switch off the default rt_dev_xxx
270   * interface when providing a customised user API */
271  #ifndef RTDM_NO_DEFAULT_USER_API
272  
273  #ifdef __KERNEL__
274  
275  #define rt_dev_open(path, oflag, ...)				\
276  	__rt_dev_open(NULL, path, oflag)
277  
278  #define rt_dev_socket(protocol_family, socket_type, protocol)	\
279  	__rt_dev_socket(NULL, protocol_family, socket_type, protocol)
280  
281  #define rt_dev_close(fd)					\
282  	__rt_dev_close(NULL, fd)
283  
284  #define rt_dev_ioctl(fd, request, ...)				\
285  	__rt_dev_ioctl(NULL, fd, request, __VA_ARGS__)
286  
287  #define rt_dev_read(fd, buf, nbyte)				\
288  	__rt_dev_read(NULL, fd, buf, nbyte)
289  
290  #define rt_dev_write(fd, buf, nbyte)				\
291  	__rt_dev_write(NULL, fd, buf, nbyte)
292  
293  #define rt_dev_recvmsg(fd, msg, flags)				\
294  	__rt_dev_recvmsg(NULL, fd, msg, flags)
295  
296  #define rt_dev_sendmsg(fd, msg, flags)				\
297  	__rt_dev_sendmsg(NULL, fd, msg, flags)
298  
299  static inline ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags,
300  				      struct sockaddr *from,
301  				      socklen_t *fromlen)
302  {
303  	struct iovec iov;
304  	struct msghdr msg;
305  	int ret;
306  
307  	iov.iov_base = buf;
308  	iov.iov_len = len;
309  
310  	msg.msg_name = from;
311  	msg.msg_namelen = from ? *fromlen : 0;
312  	msg.msg_iov = &iov;
313  	msg.msg_iovlen = 1;
314  	msg.msg_control = NULL;
315  	msg.msg_controllen = 0;
316  
317  	ret = rt_dev_recvmsg(fd, &msg, flags);
318  	if (ret >= 0 && from)
319  		*fromlen = msg.msg_namelen;
320  	return ret;
321  }
322  
323  
324  static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
325  {
326  #ifdef CONFIG_RTAI_RTDM_SELECT
327  	struct xnselector *selector;
328  	int ret;
329  	selector = rt_malloc(sizeof(struct xnselector));
330  	xnselector_init(selector);
331          ret = __rt_dev_select(nfds, rfds, wfds, efds, timeout, selector, 1);
332  	xnselector_destroy(selector);
333  	return ret;
334  #else
335  	return -ENOSYS;
336  #endif
337  }
338  
339  #else /* !__KERNEL__ */
340  
341  #ifdef __cplusplus
342  extern "C" {
343  #endif
344  
345  #ifndef _RTAI_FUSION_LXRT_H
346  #include <rtai_lxrt.h>
347  #endif
348  #include <stdarg.h>
349  
350  //#define RTAI_LXRT(ext, lsize, srq, arg) rtai_lxrt(ext, lsize, srq, arg).i[LOW]
351  
352  #ifndef RTDM_RTAI_LXRT
353  static inline int RTDM_RTAI_LXRT(int ext, int lsize, int srq, void *arg)
354  {
355  	int r;
356  	if ((r = rtai_lxrt(ext, lsize, srq, arg).i[LOW]) == -ENOSYS && rt_is_hard_real_time(NULL)) {
357  		rt_make_soft_real_time();
358  		r = rtai_lxrt(ext, lsize, srq, arg).i[LOW];
359  		rt_make_hard_real_time();
360  	}
361  	return r;
362  }
363  #endif
364  
365  static inline int rt_dev_fdcount(void)
366  {
367          struct { long dummy; } arg = { 0 };
368          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_fdcount, &arg);
369  }
370  
371  static inline int rt_dev_open(const char *path, int oflag, ...)
372  {
373          struct { const char *path; long oflag; } arg = { path, oflag };
374          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_open, &arg);
375  }
376  
377  static inline int rt_dev_socket(int protocol_family, int socket_type, int protocol)
378  {
379          struct { long protocol_family; long socket_type; long protocol; } arg = { protocol_family, socket_type, protocol };
380          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_socket, &arg);
381  }
382  
383  static inline int rt_dev_close(int fd)
384  {
385          struct { long fd; } arg = { fd };
386          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_close, &arg);
387  }
388  
389  static inline int rt_dev_ioctl(int fd, int request, ...)
390  {
391  	struct { long fd; long request; void *arg; } arg = { fd, request, NULL };
392  	va_list ap;
393  	va_start(ap, request);
394  	arg.arg = va_arg(ap, void *);
395  	va_end(ap);
396  	return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_ioctl, &arg);
397  }
398  
399  static inline ssize_t rt_dev_read(int fd, void *buf, size_t nbytes)
400  {
401          struct { long fd; void *buf; long nbytes; } arg = { fd, buf, nbytes };
402          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_read, &arg);
403  }
404  
405  static inline ssize_t rt_dev_write(int fd, const void *buf, size_t nbytes)
406  {
407          struct { long fd; const void *buf; long nbytes; } arg = { fd, buf, nbytes };
408          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_write, &arg);
409  }
410  
411  static inline ssize_t rt_dev_recvmsg(int fd, struct msghdr *msg, int flags)
412  {
413          struct { long fd; struct msghdr *msg; long flags; } arg = { fd, msg, flags };
414          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_recvmsg, &arg);
415  }
416  
417  static inline ssize_t rt_dev_sendmsg(int fd, const struct msghdr *msg, int flags)
418  {
419  	struct { long fd; const struct msghdr *msg; long flags; } arg = { fd, msg, flags };
420  	return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_sendmsg, &arg);
421  }
422  
423  static inline ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags, 
424  				      struct sockaddr *from, socklen_t *fromlen)
425  {
426  	struct iovec iov;
427  	struct msghdr msg;
428  	int ret;
429  
430  	iov.iov_base = buf;
431  	iov.iov_len = len;
432  
433  	msg.msg_name = from;
434  	msg.msg_namelen = from ? *fromlen : 0;
435  	msg.msg_iov = &iov;
436  	msg.msg_iovlen = 1;
437  	msg.msg_control = NULL;
438  	msg.msg_controllen = 0;
439  
440  	ret = rt_dev_recvmsg(fd, &msg, flags);
441  	if (ret >= 0 && from)
442  		*fromlen = msg.msg_namelen;
443  	return ret;
444  }
445  
446  static inline int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout)
447  {
448  #ifdef CONFIG_RTAI_RTDM_SELECT
449          struct { long nfds; fd_set *rfds; fd_set *wfds; fd_set *efds; nanosecs_rel_t timeout; } arg = { nfds, rfds, wfds, efds, timeout };
450          return RTDM_RTAI_LXRT(RTDM_INDX, SIZARG, __rtdm_select, &arg);
451  #else
452          return -ENOSYS;
453  #endif
454  }
455  
456  #ifdef __cplusplus
457  }
458  #endif
459  
460  #endif /* !__KERNEL__ */
461  
462  #ifdef __cplusplus
463  extern "C" {
464  #endif
465  
466  static inline ssize_t rt_dev_recv(int fd, void *buf, size_t len, int flags)
467  {
468  	return rt_dev_recvfrom(fd, buf, len, flags, NULL, NULL);
469  }
470  
471  static inline ssize_t rt_dev_sendto(int fd, const void *buf, size_t len,
472  				    int flags, const struct sockaddr *to,
473  				    socklen_t tolen)
474  {
475  	struct iovec iov;
476  	struct msghdr msg;
477  
478  	iov.iov_base = (void *)buf;
479  	iov.iov_len = len;
480  
481  	msg.msg_name = (struct sockaddr *)to;
482  	msg.msg_namelen = tolen;
483  	msg.msg_iov = &iov;
484  	msg.msg_iovlen = 1;
485  	msg.msg_control = NULL;
486  	msg.msg_controllen = 0;
487  
488  	return rt_dev_sendmsg(fd, &msg, flags);
489  }
490  
491  static inline ssize_t rt_dev_send(int fd, const void *buf, size_t len,
492  				  int flags)
493  {
494  	return rt_dev_sendto(fd, buf, len, flags, NULL, 0);
495  }
496  
497  static inline int rt_dev_getsockopt(int fd, int level, int optname,
498  				    void *optval, socklen_t *optlen)
499  {
500  	struct _rtdm_getsockopt_args args =
501  		{ level, optname, optval, optlen };
502  
503  	return rt_dev_ioctl(fd, _RTIOC_GETSOCKOPT, &args);
504  }
505  
506  static inline int rt_dev_setsockopt(int fd, int level, int optname,
507  				    const void *optval, socklen_t optlen)
508  {
509  	struct _rtdm_setsockopt_args args =
510  		{ level, optname, (void *)optval, optlen };
511  
512  	return rt_dev_ioctl(fd, _RTIOC_SETSOCKOPT, &args);
513  }
514  
515  static inline int rt_dev_bind(int fd, const struct sockaddr *my_addr,
516  			      socklen_t addrlen)
517  {
518  	struct _rtdm_setsockaddr_args args = { my_addr, addrlen };
519  
520  	return rt_dev_ioctl(fd, _RTIOC_BIND, &args);
521  }
522  
523  static inline int rt_dev_connect(int fd, const struct sockaddr *serv_addr,
524  				 socklen_t addrlen)
525  {
526  	struct _rtdm_setsockaddr_args args = { serv_addr, addrlen };
527  
528  	return rt_dev_ioctl(fd, _RTIOC_CONNECT, &args);
529  }
530  
531  static inline int rt_dev_listen(int fd, int backlog)
532  {
533  	return rt_dev_ioctl(fd, _RTIOC_LISTEN, backlog);
534  }
535  
536  static inline int rt_dev_accept(int fd, struct sockaddr *addr,
537  				socklen_t *addrlen)
538  {
539  	struct _rtdm_getsockaddr_args args = { addr, addrlen };
540  
541  	return rt_dev_ioctl(fd, _RTIOC_ACCEPT, &args);
542  }
543  
544  static inline int rt_dev_getsockname(int fd, struct sockaddr *name,
545  				     socklen_t *namelen)
546  {
547  	struct _rtdm_getsockaddr_args args = { name, namelen };
548  
549  	return rt_dev_ioctl(fd, _RTIOC_GETSOCKNAME, &args);
550  }
551  
552  static inline int rt_dev_getpeername(int fd, struct sockaddr *name,
553  				     socklen_t *namelen)
554  {
555  	struct _rtdm_getsockaddr_args args = { name, namelen };
556  
557  	return rt_dev_ioctl(fd, _RTIOC_GETPEERNAME, &args);
558  }
559  
560  static inline int rt_dev_shutdown(int fd, int how)
561  {
562  	return rt_dev_ioctl(fd, _RTIOC_SHUTDOWN, how);
563  }
564  
565  #ifdef __cplusplus
566  }
567  #endif
568  
569  #endif /* RTDM_NO_DEFAULT_USER_API */
570  
571  #endif /* _RTDM_H */