/ addons / rtdm / core.c
core.c
   1  /**
   2   * @file
   3   * Real-Time Driver Model for RTAI, device operation multiplexing
   4   *
   5   * @note Copyright (C) 2005 Jan Kiszka <jan.kiszka@web.de>
   6   * @note Copyright (C) 2005 Joerg Langenberg <joerg.langenberg@gmx.net>
   7   *
   8   * with adaptions for RTAI by Paolo Mantegazza <mantegazza@aero.polimi.it>
   9   *
  10   * RTAI is free software; you can redistribute it and/or modify it
  11   * under the terms of the GNU General Public License as published by
  12   * the Free Software Foundation; either version 2 of the License, or
  13   * (at your option) any later version.
  14   *
  15   * RTAI is distributed in the hope that it will be useful, but
  16   * WITHOUT ANY WARRANTY; without even the implied warranty of
  17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18   * General Public License for more details.
  19   *
  20   * You should have received a copy of the GNU General Public License
  21   * along with RTAI; if not, write to the Free Software Foundation,
  22   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23   */
  24  
  25  /*!
  26   * @ingroup driverapi
  27   * @defgroup interdrv Inter-Driver API
  28   * @{
  29   */
  30  
  31  #include <linux/delay.h>
  32  
  33  
  34  
  35  
  36  
  37  
  38  #include "rtdm/internal.h"
  39  
  40  #define CLOSURE_RETRY_PERIOD_MS	100
  41  
  42  #define FD_BITMAP_SIZE  ((RTDM_FD_MAX + BITS_PER_LONG-1) / BITS_PER_LONG)
  43  
  44  struct rtdm_fildes fildes_table[RTDM_FD_MAX] =
  45  	{ [0 ... RTDM_FD_MAX-1] = { NULL } };
  46  static unsigned long used_fildes[FD_BITMAP_SIZE];
  47  int open_fildes;	/* number of used descriptors */
  48  
  49  static DECLARE_WORK_FUNC(close_callback);
  50  static DECLARE_DELAYED_WORK_NODATA(close_work, close_callback);
  51  static LIST_HEAD(cleanup_queue);
  52  
  53  DEFINE_XNLOCK(rt_fildes_lock);
  54  
  55  /**
  56   * @brief Retrieve and lock a device context
  57   *
  58   * @param[in] fd File descriptor
  59   *
  60   * @return Pointer to associated device context, or NULL on error
  61   *
  62   * @note The device context has to be unlocked using rtdm_context_put() when
  63   * it is no longer referenced.
  64   *
  65   * Environments:
  66   *
  67   * This service can be called from:
  68   *
  69   * - Kernel module initialization/cleanup code
  70   * - Interrupt service routine
  71   * - Kernel-based task
  72   * - User-space task (RT, non-RT)
  73   *
  74   * Rescheduling: never.
  75   */
  76  struct rtdm_dev_context *rtdm_context_get(int fd)
  77  {
  78  	struct rtdm_dev_context *context;
  79  	spl_t s;
  80  
  81  	if ((unsigned int)fd >= RTDM_FD_MAX)
  82  		return NULL;
  83  
  84  	xnlock_get_irqsave(&rt_fildes_lock, s);
  85  
  86  	context = fildes_table[fd].context;
  87  	if (unlikely(!context)) {
  88  		xnlock_put_irqrestore(&rt_fildes_lock, s);
  89  		return NULL;
  90  	}
  91  
  92  	atomic_inc(&context->close_lock_count);
  93  
  94  	xnlock_put_irqrestore(&rt_fildes_lock, s);
  95  
  96  	return context;
  97  }
  98  
  99  EXPORT_SYMBOL(rtdm_context_get);
 100  
 101  static int create_instance(struct rtdm_device *device,
 102  			   struct rtdm_dev_context **context_ptr,
 103  			   struct rtdm_fildes **fildes_ptr,
 104  			   rtdm_user_info_t *user_info, int nrt_mem)
 105  {
 106  	struct rtdm_dev_context *context;
 107  
 108  	int fd;
 109  	spl_t s;
 110  
 111  	/* 
 112  	 * Reset to NULL so that we can always use cleanup_files/instance to
 113  	 * revert also partially successful allocations.
 114  	 */
 115  	*context_ptr = NULL;
 116  	*fildes_ptr = NULL;
 117  
 118  	/* Reserve a file descriptor */
 119  	xnlock_get_irqsave(&rt_fildes_lock, s);
 120  
 121  	if (unlikely(open_fildes >= RTDM_FD_MAX)) {
 122  		xnlock_put_irqrestore(&rt_fildes_lock, s);
 123  		return -ENFILE;
 124  	}
 125  
 126  	fd = find_first_zero_bit(used_fildes, RTDM_FD_MAX);
 127  	__set_bit(fd, used_fildes);
 128  	open_fildes++;
 129  
 130  	xnlock_put_irqrestore(&rt_fildes_lock, s);
 131  
 132  	*fildes_ptr = &fildes_table[fd];
 133  
 134  	context = device->reserved.exclusive_context;
 135  	if (context) {
 136  		xnlock_get_irqsave(&rt_dev_lock, s);
 137  
 138  		if (unlikely(context->device != NULL)) {
 139  			xnlock_put_irqrestore(&rt_dev_lock, s);
 140  			return -EBUSY;
 141  		}
 142  		context->device = device;
 143  
 144  		xnlock_put_irqrestore(&rt_dev_lock, s);
 145  	} else {
 146  		if (nrt_mem)
 147  			context = kmalloc(sizeof(struct rtdm_dev_context) +
 148  					  device->context_size, GFP_KERNEL);
 149  		else
 150  			context = xnmalloc(sizeof(struct rtdm_dev_context) +
 151  					   device->context_size);
 152  		if (unlikely(!context))
 153  			return -ENOMEM;
 154  
 155  		context->device = device;
 156  	}
 157  
 158  	*context_ptr = context;
 159  
 160  	context->fd = fd;
 161  	context->ops = &device->ops;
 162  	atomic_set(&context->close_lock_count, 0);
 163  
 164  
 165  
 166  
 167  
 168  	context->reserved.owner = NULL;
 169  
 170  
 171  
 172  	return 0;
 173  }
 174  
 175  static void __cleanup_fildes(struct rtdm_fildes *fildes)
 176  {
 177  	__clear_bit((fildes - fildes_table), used_fildes);
 178  	fildes->context = NULL;
 179  	open_fildes--;
 180  }
 181  
 182  static void cleanup_fildes(struct rtdm_fildes *fildes)
 183  {
 184  	spl_t s;
 185  
 186  	if (!fildes)
 187  		return;
 188  
 189  	xnlock_get_irqsave(&rt_fildes_lock, s);
 190  	__cleanup_fildes(fildes);
 191  	xnlock_put_irqrestore(&rt_fildes_lock, s);
 192  }
 193  
 194  static void cleanup_instance(struct rtdm_device *device,
 195  			     struct rtdm_dev_context *context,
 196  			     int nrt_mem)
 197  {
 198  	if (context) {
 199  		if (device->reserved.exclusive_context)
 200  			context->device = NULL;
 201  		else {
 202  			if (nrt_mem)
 203  				kfree(context);
 204  			else
 205  				xnfree(context);
 206  		}
 207  	}
 208  
 209  	rtdm_dereference_device(device);
 210  }
 211  
 212  static DECLARE_WORK_FUNC(close_callback)
 213  {
 214  	struct rtdm_dev_context *context;
 215  	LIST_HEAD(deferred_list);
 216  	int reschedule = 0;
 217  	int err;
 218  	spl_t s;
 219  
 220  	xnlock_get_irqsave(&rt_fildes_lock, s);
 221  
 222  	while (!list_empty(&cleanup_queue)) {
 223  		context = list_first_entry(&cleanup_queue,
 224  					   struct rtdm_dev_context,
 225  					   reserved.cleanup);
 226  		list_del(&context->reserved.cleanup);
 227  		atomic_inc(&context->close_lock_count);
 228  
 229  		xnlock_put_irqrestore(&rt_fildes_lock, s);
 230  
 231  		err = context->ops->close_nrt(context, NULL);
 232  
 233  		if (err == -EAGAIN ||
 234  		    atomic_read(&context->close_lock_count) > 1) {
 235  			atomic_dec(&context->close_lock_count);
 236  			list_add_tail(&context->reserved.cleanup,
 237  				      &deferred_list);
 238  			if (err == -EAGAIN)
 239  				reschedule = 1;
 240  		} else {
 241  			trace_mark(xn_rtdm, fd_closed, "fd %d", context->fd);
 242  
 243  			cleanup_instance(context->device, context,
 244  					 test_bit(RTDM_CREATED_IN_NRT,
 245  						  &context->context_flags));
 246  		}
 247  
 248  		xnlock_get_irqsave(&rt_fildes_lock, s);
 249  	}
 250  
 251  	list_splice(&deferred_list, &cleanup_queue);
 252  
 253  	xnlock_put_irqrestore(&rt_fildes_lock, s);
 254  
 255  	if (reschedule)
 256  		schedule_delayed_work(&close_work,
 257  				      (HZ * CLOSURE_RETRY_PERIOD_MS) / 1000);
 258  }
 259  
 260  void rtdm_apc_handler(void *cookie)
 261  {
 262  	schedule_delayed_work(&close_work, 0);
 263  }
 264  
 265  
 266  int __rt_dev_open(rtdm_user_info_t *user_info, const char *path, int oflag)
 267  {
 268  	struct rtdm_device *device;
 269  	struct rtdm_fildes *fildes;
 270  	struct rtdm_dev_context *context;
 271  	int ret;
 272  	int nrt_mode = !rtdm_in_rt_context();
 273  
 274  	device = get_named_device(path);
 275  	trace_mark(xn_rtdm, open, "user_info %p path %s oflag %d device %p",
 276  		   user_info, path, oflag, device);
 277  	ret = -ENODEV;
 278  	if (!device)
 279  		goto err_out;
 280  
 281  	ret = create_instance(device, &context, &fildes, user_info, nrt_mode);
 282  	if (ret != 0)
 283  		goto cleanup_out;
 284  
 285  	if (nrt_mode) {
 286  		context->context_flags = (1 << RTDM_CREATED_IN_NRT);
 287  		ret = device->open_nrt(context, user_info, oflag);
 288  	} else {
 289  		context->context_flags = 0;
 290  		ret = device->open_rt(context, user_info, oflag);
 291  	}
 292  
 293  	RTAI_ASSERT(RTDM, !rthal_local_irq_disabled(),
 294  		    rthal_local_irq_enable(););
 295  
 296  	if (unlikely(ret < 0))
 297  		goto cleanup_out;
 298  
 299  	fildes->context = context;
 300  
 301  	trace_mark(xn_rtdm, fd_created,
 302  		   "device %p fd %d", device, context->fd);
 303  
 304  	return context->fd;
 305  
 306  cleanup_out:
 307  	cleanup_fildes(fildes);
 308  	cleanup_instance(device, context, nrt_mode);
 309  
 310  err_out:
 311  	return ret;
 312  }
 313  
 314  EXPORT_SYMBOL(__rt_dev_open);
 315  
 316  int __rt_dev_socket(rtdm_user_info_t *user_info, int protocol_family,
 317  		    int socket_type, int protocol)
 318  {
 319  	struct rtdm_device *device;
 320  	struct rtdm_fildes *fildes;
 321  	struct rtdm_dev_context *context;
 322  	int ret;
 323  	int nrt_mode = !rtdm_in_rt_context();
 324  
 325  	device = get_protocol_device(protocol_family, socket_type);
 326  	trace_mark(xn_rtdm, socket, "user_info %p protocol_family %d "
 327  		   "socket_type %d protocol %d device %p",
 328  		   user_info, protocol_family, socket_type, protocol, device);
 329  	ret = -EAFNOSUPPORT;
 330  	if (!device)
 331  		goto err_out;
 332  
 333  	ret = create_instance(device, &context, &fildes, user_info, nrt_mode);
 334  	if (ret != 0)
 335  		goto cleanup_out;
 336  
 337  	if (nrt_mode) {
 338  		context->context_flags = (1 << RTDM_CREATED_IN_NRT);
 339  		ret = device->socket_nrt(context, user_info, protocol);
 340  	} else {
 341  		context->context_flags = 0;
 342  		ret = device->socket_rt(context, user_info, protocol);
 343  	}
 344  
 345  	RTAI_ASSERT(RTDM, !rthal_local_irq_disabled(),
 346  		    rthal_local_irq_enable(););
 347  
 348  	if (unlikely(ret < 0))
 349  		goto cleanup_out;
 350  
 351  	fildes->context = context;
 352  
 353  	trace_mark(xn_rtdm, fd_created,
 354  		   "device %p fd %d", device, context->fd);
 355  
 356  	return context->fd;
 357  
 358  cleanup_out:
 359  	cleanup_fildes(fildes);
 360  	cleanup_instance(device, context, nrt_mode);
 361  
 362  err_out:
 363  	return ret;
 364  }
 365  
 366  EXPORT_SYMBOL(__rt_dev_socket);
 367  
 368  int __rt_dev_close(rtdm_user_info_t *user_info, int fd)
 369  {
 370  	struct rtdm_dev_context *context;
 371  	spl_t s;
 372  	int ret;
 373  	int nrt_mode = !rtdm_in_rt_context();
 374  
 375  	trace_mark(xn_rtdm, close, "user_info %p fd %d", user_info, fd);
 376  
 377  	ret = -EBADF;
 378  	if (unlikely((unsigned int)fd >= RTDM_FD_MAX))
 379  		goto err_out;
 380  
 381  	xnlock_get_irqsave(&rt_fildes_lock, s);
 382  
 383  	context = fildes_table[fd].context;
 384  
 385  	if (unlikely(!context)) {
 386  		xnlock_put_irqrestore(&rt_fildes_lock, s);
 387  		goto err_out;	/* -EBADF */
 388  	}
 389  
 390  	/* Avoid asymmetric close context by switching to nrt. */
 391  	if (unlikely(test_bit(RTDM_CREATED_IN_NRT, &context->context_flags)) &&
 392  	    !nrt_mode) {
 393  		xnlock_put_irqrestore(&rt_fildes_lock, s);
 394  
 395  		ret = -ENOSYS;
 396  		goto err_out;
 397  	}
 398  
 399  	set_bit(RTDM_CLOSING, &context->context_flags);
 400  	atomic_inc(&context->close_lock_count);
 401  
 402  	__cleanup_fildes(&fildes_table[fd]);
 403  
 404  	xnlock_put_irqrestore(&rt_fildes_lock, s);
 405  
 406  	if (nrt_mode)
 407  		ret = context->ops->close_nrt(context, user_info);
 408  	else
 409  		ret = context->ops->close_rt(context, user_info);
 410  
 411  	RTAI_ASSERT(RTDM, !rthal_local_irq_disabled(),
 412  		    rthal_local_irq_enable(););
 413  
 414  	xnlock_get_irqsave(&rt_fildes_lock, s);
 415  
 416  	if (ret == -EAGAIN || atomic_read(&context->close_lock_count) > 2) {
 417  		atomic_dec(&context->close_lock_count);
 418  		list_add(&context->reserved.cleanup, &cleanup_queue);
 419  
 420  		xnlock_put_irqrestore(&rt_fildes_lock, s);
 421  
 422  		if (ret == -EAGAIN) {
 423  			rthal_apc_schedule(rtdm_apc);
 424  			ret = 0;
 425  		}
 426  		goto unlock_out;
 427  	}
 428  
 429  	xnlock_put_irqrestore(&rt_fildes_lock, s);
 430  
 431  	trace_mark(xn_rtdm, fd_closed, "fd %d", context->fd);
 432  
 433  	cleanup_instance(context->device, context,
 434  			 test_bit(RTDM_CREATED_IN_NRT,
 435  				  &context->context_flags));
 436  
 437  	return ret;
 438  
 439  unlock_out:
 440  	rtdm_context_unlock(context);
 441  
 442  err_out:
 443  	return ret;
 444  }
 445  
 446  EXPORT_SYMBOL(__rt_dev_close);
 447  
 448  void cleanup_owned_contexts(void *owner)
 449  {
 450  	struct rtdm_dev_context *context;
 451  	unsigned int fd;
 452  	int ret;
 453  	spl_t s;
 454  
 455  	for (fd = 0; fd < RTDM_FD_MAX; fd++) {
 456  		xnlock_get_irqsave(&rt_fildes_lock, s);
 457  
 458  		context = fildes_table[fd].context;
 459  		if (context && context->reserved.owner != owner)
 460  			context = NULL;
 461  
 462  		xnlock_put_irqrestore(&rt_fildes_lock, s);
 463  
 464  		if (context) {
 465  			if (RTAI_DEBUG(RTDM))
 466  				xnprintf("RTDM: closing file descriptor %d.\n",
 467  					 fd);
 468  
 469  			ret = __rt_dev_close(NULL, fd);
 470  			RTAI_ASSERT(RTDM, ret == 0 || ret == -EBADF,
 471  				    /* only warn here */;);
 472  		}
 473  	}
 474  }
 475  
 476  #define MAJOR_FUNCTION_WRAPPER_TH(operation, args...)			\
 477  do {									\
 478  	struct rtdm_dev_context *context;				\
 479  	struct rtdm_operations *ops;					\
 480  	int ret;							\
 481  									\
 482  	context = rtdm_context_get(fd);					\
 483  	ret = -EBADF;							\
 484  	if (unlikely(!context))						\
 485  		goto err_out;						\
 486  									\
 487  	ops = context->ops;						\
 488  									\
 489  	if (rtdm_in_rt_context())					\
 490  		ret = ops->operation##_rt(context, user_info, args);	\
 491  	else								\
 492  		ret = ops->operation##_nrt(context, user_info, args);	\
 493  									\
 494  	RTAI_ASSERT(RTDM, !rthal_local_irq_disabled(), 			\
 495  		    rthal_local_irq_enable();)
 496  
 497  #define MAJOR_FUNCTION_WRAPPER_BH()					\
 498  	rtdm_context_unlock(context);					\
 499  									\
 500  err_out:								\
 501  	trace_mark(xn_rtdm, operation##_done, "result %d", ret);	\
 502  	return ret;							\
 503  } while (0)
 504  
 505  #define MAJOR_FUNCTION_WRAPPER(operation, args...)			\
 506  do {									\
 507  	MAJOR_FUNCTION_WRAPPER_TH(operation, args);			\
 508  	MAJOR_FUNCTION_WRAPPER_BH();					\
 509  } while (0)
 510  
 511  int __rt_dev_ioctl(rtdm_user_info_t *user_info, int fd, int request, ...)
 512  {
 513  	va_list args;
 514  	void __user *arg;
 515  
 516  	va_start(args, request);
 517  	arg = va_arg(args, void __user *);
 518  	va_end(args);
 519  
 520  	trace_mark(xn_rtdm, ioctl, "user_info %p fd %d request %d arg %p",
 521  		   user_info, fd, request, arg);
 522  
 523  	MAJOR_FUNCTION_WRAPPER_TH(ioctl, (unsigned int)request, arg);
 524  
 525  	if (unlikely(ret < 0) && (unsigned int)request == RTIOC_DEVICE_INFO) {
 526  		struct rtdm_device *dev = context->device;
 527  		struct rtdm_device_info dev_info;
 528  
 529  		dev_info.device_flags = dev->device_flags;
 530  		dev_info.device_class = dev->device_class;
 531  		dev_info.device_sub_class = dev->device_sub_class;
 532  		dev_info.profile_version = dev->profile_version;
 533  
 534  		ret = rtdm_safe_copy_to_user(user_info, arg, &dev_info,
 535  					     sizeof(dev_info));
 536  	}
 537  
 538  	MAJOR_FUNCTION_WRAPPER_BH();
 539  }
 540  
 541  EXPORT_SYMBOL(__rt_dev_ioctl);
 542  
 543  ssize_t __rt_dev_read(rtdm_user_info_t *user_info, int fd, void *buf,
 544  		      size_t nbyte)
 545  {
 546  	trace_mark(xn_rtdm, read, "user_info %p fd %d buf %p nbyte %zu",
 547  		   user_info, fd, buf, nbyte);
 548  	MAJOR_FUNCTION_WRAPPER(read, buf, nbyte);
 549  }
 550  
 551  EXPORT_SYMBOL(__rt_dev_read);
 552  
 553  ssize_t __rt_dev_write(rtdm_user_info_t *user_info, int fd, const void *buf,
 554  		       size_t nbyte)
 555  {
 556  	trace_mark(xn_rtdm, write, "user_info %p fd %d buf %p nbyte %zu",
 557  		   user_info, fd, buf, nbyte);
 558  	MAJOR_FUNCTION_WRAPPER(write, buf, nbyte);
 559  }
 560  
 561  EXPORT_SYMBOL(__rt_dev_write);
 562  
 563  ssize_t __rt_dev_recvmsg(rtdm_user_info_t *user_info, int fd,
 564  			 struct msghdr *msg, int flags)
 565  {
 566  	trace_mark(xn_rtdm, recvmsg, "user_info %p fd %d msg_name %p "
 567  		   "msg_namelen %u msg_iov %p msg_iovlen %zu "
 568  		   "msg_control %p msg_controllen %zu msg_flags %d",
 569  		   user_info, fd, msg->msg_name, msg->msg_namelen,
 570  		   msg->msg_iov, msg->msg_iovlen, msg->msg_control,
 571  		   msg->msg_controllen, msg->msg_flags);
 572  	MAJOR_FUNCTION_WRAPPER(recvmsg, msg, flags);
 573  }
 574  
 575  EXPORT_SYMBOL(__rt_dev_recvmsg);
 576  
 577  ssize_t __rt_dev_sendmsg(rtdm_user_info_t *user_info, int fd,
 578  			 const struct msghdr *msg, int flags)
 579  {
 580  	trace_mark(xn_rtdm, sendmsg, "user_info %p fd %d msg_name %p "
 581  		   "msg_namelen %u msg_iov %p msg_iovlen %zu "
 582  		   "msg_control %p msg_controllen %zu msg_flags %d",
 583  		   user_info, fd, msg->msg_name, msg->msg_namelen,
 584  		   msg->msg_iov, msg->msg_iovlen, msg->msg_control,
 585  		   msg->msg_controllen, msg->msg_flags);
 586  	MAJOR_FUNCTION_WRAPPER(sendmsg, msg, flags);
 587  }
 588  
 589  EXPORT_SYMBOL(__rt_dev_sendmsg);
 590  
 591  /**
 592   * @brief Bind a selector to specified event types of a given file descriptor
 593   * @internal
 594   *
 595   * This function is invoked by higher RTOS layers implementing select-like
 596   * services. It shall not be called directly by RTDM drivers.
 597   *
 598   * @param[in] fd File descriptor to bind to
 599   * @param[in,out] selector Selector object that shall be bound to the given
 600   * event
 601   * @param[in] type Event type the caller is interested in
 602   * @param[in] fd_index Index in the file descriptor set of the caller
 603   *
 604   * @return 0 on success, otherwise:
 605   *
 606   * - -EBADF is returned if the file descriptor @a fd cannot be resolved.
 607   *
 608   * - -EINVAL is returned if @a type or @a fd_index are invalid.
 609   *
 610   * Environments:
 611   *
 612   * This service can be called from:
 613   *
 614   * - Kernel module initialization/cleanup code
 615   * - Kernel-based task
 616   * - User-space task (RT, non-RT)
 617   *
 618   * Rescheduling: never.
 619   */
 620  int rtdm_select_bind(int fd, rtdm_selector_t *selector,
 621  		     enum rtdm_selecttype type, unsigned fd_index)
 622  {
 623  	struct rtdm_dev_context *context;
 624  	struct rtdm_operations  *ops;
 625  	int ret;
 626  
 627  	context = rtdm_context_get(fd);
 628  
 629  	ret = -EBADF;
 630  	if (unlikely(!context))
 631  		goto err_out;
 632  
 633  	ops = context->ops;
 634  
 635  	ret = ops->select_bind(context, selector, type, fd_index);
 636  
 637  	RTAI_ASSERT(RTDM, !rthal_local_irq_disabled(),
 638  		    rthal_local_irq_enable(););
 639  
 640  	rtdm_context_unlock(context);
 641  
 642    err_out:
 643  	return ret;
 644  }
 645  
 646  EXPORT_SYMBOL(rtdm_select_bind);
 647  
 648  #ifdef DOXYGEN_CPP /* Only used for doxygen doc generation */
 649  
 650  /**
 651   * @brief Increment context reference counter
 652   *
 653   * @param[in] context Device context
 654   *
 655   * @note rtdm_context_get() automatically increments the lock counter. You
 656   * only need to call this function in special scenarios, e.g. when keeping
 657   * additional references to the context structure that have different
 658   * lifetimes. Only use rtdm_context_lock() on contexts that are currently
 659   * locked via an earlier rtdm_context_get()/rtdm_contex_lock() or while
 660   * running a device operation handler.
 661   *
 662   * Environments:
 663   *
 664   * This service can be called from:
 665   *
 666   * - Kernel module initialization/cleanup code
 667   * - Interrupt service routine
 668   * - Kernel-based task
 669   * - User-space task (RT, non-RT)
 670   *
 671   * Rescheduling: never.
 672   */
 673  void rtdm_context_lock(struct rtdm_dev_context *context);
 674  
 675  /**
 676   * @brief Decrement context reference counter
 677   *
 678   * @param[in] context Device context
 679   *
 680   * @note Every call to rtdm_context_locked() must be matched by a
 681   * rtdm_context_unlock() invocation.
 682   *
 683   * Environments:
 684   *
 685   * This service can be called from:
 686   *
 687   * - Kernel module initialization/cleanup code
 688   * - Interrupt service routine
 689   * - Kernel-based task
 690   * - User-space task (RT, non-RT)
 691   *
 692   * Rescheduling: never.
 693   */
 694  void rtdm_context_unlock(struct rtdm_dev_context *context);
 695  
 696  /**
 697   * @brief Release a device context obtained via rtdm_context_get()
 698   *
 699   * @param[in] context Device context
 700   *
 701   * @note Every successful call to rtdm_context_get() must be matched by a
 702   * rtdm_context_put() invocation.
 703   *
 704   * Environments:
 705   *
 706   * This service can be called from:
 707   *
 708   * - Kernel module initialization/cleanup code
 709   * - Interrupt service routine
 710   * - Kernel-based task
 711   * - User-space task (RT, non-RT)
 712   *
 713   * Rescheduling: never.
 714   */
 715  void rtdm_context_put(struct rtdm_dev_context *context);
 716  
 717  /**
 718   * @brief Open a device
 719   *
 720   * Refer to rt_dev_open() for parameters and return values
 721   *
 722   * Environments:
 723   *
 724   * Depends on driver implementation, see @ref profiles "Device Profiles".
 725   *
 726   * Rescheduling: possible.
 727   */
 728  int rtdm_open(const char *path, int oflag, ...);
 729  
 730  /**
 731   * @brief Create a socket
 732   *
 733   * Refer to rt_dev_socket() for parameters and return values
 734   *
 735   * Environments:
 736   *
 737   * Depends on driver implementation, see @ref profiles "Device Profiles".
 738   *
 739   * Rescheduling: possible.
 740   */
 741  int rtdm_socket(int protocol_family, int socket_type, int protocol);
 742  
 743  /**
 744   * @brief Close a device or socket
 745   *
 746   * Refer to rt_dev_close() for parameters and return values
 747   *
 748   * Environments:
 749   *
 750   * Depends on driver implementation, see @ref profiles "Device Profiles".
 751   *
 752   * Rescheduling: possible.
 753   */
 754  int rtdm_close(int fd);
 755  
 756  /**
 757   * @brief Issue an IOCTL
 758   *
 759   * Refer to rt_dev_ioctl() for parameters and return values
 760   *
 761   * Environments:
 762   *
 763   * Depends on driver implementation, see @ref profiles "Device Profiles".
 764   *
 765   * Rescheduling: possible.
 766   */
 767  int rtdm_ioctl(int fd, int request, ...);
 768  
 769  /**
 770   * @brief Read from device
 771   *
 772   * Refer to rt_dev_read() for parameters and return values
 773   *
 774   * Environments:
 775   *
 776   * Depends on driver implementation, see @ref profiles "Device Profiles".
 777   *
 778   * Rescheduling: possible.
 779   */
 780  ssize_t rtdm_read(int fd, void *buf, size_t nbyte);
 781  
 782  /**
 783   * @brief Write to device
 784   *
 785   * Refer to rt_dev_write() for parameters and return values
 786   *
 787   * Environments:
 788   *
 789   * Depends on driver implementation, see @ref profiles "Device Profiles".
 790   *
 791   * Rescheduling: possible.
 792   */
 793  ssize_t rtdm_write(int fd, const void *buf, size_t nbyte);
 794  
 795  /**
 796   * @brief Receive message from socket
 797   *
 798   * Refer to rt_dev_recvmsg() for parameters and return values
 799   *
 800   * Environments:
 801   *
 802   * Depends on driver implementation, see @ref profiles "Device Profiles".
 803   *
 804   * Rescheduling: possible.
 805   */
 806  ssize_t rtdm_recvmsg(int fd, struct msghdr *msg, int flags);
 807  
 808  /**
 809   * @brief Receive message from socket
 810   *
 811   * Refer to rt_dev_recvfrom() for parameters and return values
 812   *
 813   * Environments:
 814   *
 815   * Depends on driver implementation, see @ref profiles "Device Profiles".
 816   *
 817   * Rescheduling: possible.
 818   */
 819  ssize_t rtdm_recvfrom(int fd, void *buf, size_t len, int flags,
 820  		      struct sockaddr *from, socklen_t *fromlen);
 821  
 822  /**
 823   * @brief Receive message from socket
 824   *
 825   * Refer to rt_dev_recv() for parameters and return values
 826   *
 827   * Environments:
 828   *
 829   * Depends on driver implementation, see @ref profiles "Device Profiles".
 830   *
 831   * Rescheduling: possible.
 832   */
 833  ssize_t rtdm_recv(int fd, void *buf, size_t len, int flags);
 834  
 835  /**
 836   * @brief Transmit message to socket
 837   *
 838   * Refer to rt_dev_sendmsg() for parameters and return values
 839   *
 840   * Environments:
 841   *
 842   * Depends on driver implementation, see @ref profiles "Device Profiles".
 843   *
 844   * Rescheduling: possible.
 845   */
 846  ssize_t rtdm_sendmsg(int fd, const struct msghdr *msg, int flags);
 847  
 848  /**
 849   * @brief Transmit message to socket
 850   *
 851   * Refer to rt_dev_sendto() for parameters and return values
 852   *
 853   * Environments:
 854   *
 855   * Depends on driver implementation, see @ref profiles "Device Profiles".
 856   *
 857   * Rescheduling: possible.
 858   */
 859  ssize_t rtdm_sendto(int fd, const void *buf, size_t len, int flags,
 860  		    const struct sockaddr *to, socklen_t tolen);
 861  
 862  /**
 863   * @brief Transmit message to socket
 864   *
 865   * Refer to rt_dev_send() for parameters and return values
 866   *
 867   * Environments:
 868   *
 869   * Depends on driver implementation, see @ref profiles "Device Profiles".
 870   *
 871   * Rescheduling: possible.
 872   */
 873  ssize_t rtdm_send(int fd, const void *buf, size_t len, int flags);
 874  
 875  /**
 876   * @brief Bind to local address
 877   *
 878   * Refer to rt_dev_bind() for parameters and return values
 879   *
 880   * Environments:
 881   *
 882   * Depends on driver implementation, see @ref profiles "Device Profiles".
 883   *
 884   * Rescheduling: possible.
 885   */
 886  int rtdm_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen);
 887  
 888  /**
 889   * @brief Connect to remote address
 890   *
 891   * Refer to rt_dev_connect() for parameters and return values
 892   *
 893   * Environments:
 894   *
 895   * Depends on driver implementation, see @ref profiles "Device Profiles".
 896   *
 897   * Rescheduling: possible.
 898   */
 899  int rtdm_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen);
 900  
 901  /**
 902   * @brief Listen for incomming connection requests
 903   *
 904   * Refer to rt_dev_listen() for parameters and return values
 905   *
 906   * Environments:
 907   *
 908   * Depends on driver implementation, see @ref profiles "Device Profiles".
 909   *
 910   * Rescheduling: possible.
 911   */
 912  int rtdm_listen(int fd, int backlog);
 913  
 914  /**
 915   * @brief Accept a connection requests
 916   *
 917   * Refer to rt_dev_accept() for parameters and return values
 918   *
 919   * Environments:
 920   *
 921   * Depends on driver implementation, see @ref profiles "Device Profiles".
 922   *
 923   * Rescheduling: possible.
 924   */
 925  int rtdm_accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
 926  
 927  /**
 928   * @brief Shut down parts of a connection
 929   *
 930   * Refer to rt_dev_shutdown() for parameters and return values
 931   *
 932   * Environments:
 933   *
 934   * Depends on driver implementation, see @ref profiles "Device Profiles".
 935   *
 936   * Rescheduling: possible.
 937   */
 938  int rtdm_shutdown(int fd, int how);
 939  
 940  /**
 941   * @brief Get socket option
 942   *
 943   * Refer to rt_dev_getsockopt() for parameters and return values
 944   *
 945   * Environments:
 946   *
 947   * Depends on driver implementation, see @ref profiles "Device Profiles".
 948   *
 949   * Rescheduling: possible.
 950   */
 951  int rtdm_getsockopt(int fd, int level, int optname, void *optval,
 952  		    socklen_t *optlen);
 953  
 954  /**
 955   * @brief Set socket option
 956   *
 957   * Refer to rt_dev_setsockopt() for parameters and return values
 958   *
 959   * Environments:
 960   *
 961   * Depends on driver implementation, see @ref profiles "Device Profiles".
 962   *
 963   * Rescheduling: possible.
 964   */
 965  int rtdm_setsockopt(int fd, int level, int optname, const void *optval,
 966  		    socklen_t optlen);
 967  
 968  /**
 969   * @brief Get local socket address
 970   *
 971   * Refer to rt_dev_getsockname() for parameters and return values
 972   *
 973   * Environments:
 974   *
 975   * Depends on driver implementation, see @ref profiles "Device Profiles".
 976   *
 977   * Rescheduling: possible.
 978   */
 979  int rtdm_getsockname(int fd, struct sockaddr *name, socklen_t *namelen);
 980  
 981  /**
 982   * @brief Get socket destination address
 983   *
 984   * Refer to rt_dev_getpeername() for parameters and return values
 985   *
 986   * Environments:
 987   *
 988   * Depends on driver implementation, see @ref profiles "Device Profiles".
 989   *
 990   * Rescheduling: possible.
 991   */
 992  int rtdm_getpeername(int fd, struct sockaddr *name, socklen_t *namelen);
 993  
 994  /** @} */
 995  
 996  /*!
 997   * @addtogroup userapi
 998   * @{
 999   */
1000  
1001  /**
1002   * @brief Open a device
1003   *
1004   * @param[in] path Device name
1005   * @param[in] oflag Open flags
1006   * @param ... Further parameters will be ignored.
1007   *
1008   * @return Positive file descriptor value on success, otherwise a negative
1009   * error code.
1010   *
1011   * Environments:
1012   *
1013   * Depends on driver implementation, see @ref profiles "Device Profiles".
1014   *
1015   * Rescheduling: possible.
1016   *
1017   * @see @c open() in IEEE Std 1003.1,
1018   * http://www.opengroup.org/onlinepubs/009695399
1019   */
1020  int rt_dev_open(const char *path, int oflag, ...);
1021  
1022  /**
1023   * @brief Create a socket
1024   *
1025   * @param[in] protocol_family Protocol family (@c PF_xxx)
1026   * @param[in] socket_type Socket type (@c SOCK_xxx)
1027   * @param[in] protocol Protocol ID, 0 for default
1028   *
1029   * @return Positive file descriptor value on success, otherwise a negative
1030   * error code.
1031   *
1032   * Environments:
1033   *
1034   * Depends on driver implementation, see @ref profiles "Device Profiles".
1035   *
1036   * Rescheduling: possible.
1037   *
1038   * @see @c socket() in IEEE Std 1003.1,
1039   * http://www.opengroup.org/onlinepubs/009695399
1040   */
1041  int rt_dev_socket(int protocol_family, int socket_type, int protocol);
1042  
1043  /**
1044   * @brief Close a device or socket
1045   *
1046   * @param[in] fd File descriptor as returned by rt_dev_open() or rt_dev_socket()
1047   *
1048   * @return 0 on success, otherwise a negative error code.
1049   *
1050   * @note If the matching rt_dev_open() or rt_dev_socket() call took place in
1051   * non-real-time context, rt_dev_close() must be issued within non-real-time
1052   * as well. Otherwise, the call will fail.
1053   *
1054   * Environments:
1055   *
1056   * Depends on driver implementation, see @ref profiles "Device Profiles".
1057   *
1058   * Rescheduling: possible.
1059   *
1060   * @see @c close() in IEEE Std 1003.1,
1061   * http://www.opengroup.org/onlinepubs/009695399
1062   */
1063  int rt_dev_close(int fd);
1064  
1065  /**
1066   * @brief Issue an IOCTL
1067   *
1068   * @param[in] fd File descriptor as returned by rt_dev_open() or rt_dev_socket()
1069   * @param[in] request IOCTL code
1070   * @param ... Optional third argument, depending on IOCTL function
1071   * (@c void @c * or @c unsigned @c long)
1072   *
1073   * @return Positiv value on success, otherwise negative error code
1074   *
1075   * Environments:
1076   *
1077   * Depends on driver implementation, see @ref profiles "Device Profiles".
1078   *
1079   * Rescheduling: possible.
1080   *
1081   * @see @c ioctl() in IEEE Std 1003.1,
1082   * http://www.opengroup.org/onlinepubs/009695399
1083   */
1084  int rt_dev_ioctl(int fd, int request, ...);
1085  
1086  /**
1087   * @brief Read from device
1088   *
1089   * @param[in] fd File descriptor as returned by rt_dev_open()
1090   * @param[out] buf Input buffer
1091   * @param[in] nbyte Number of bytes to read
1092   *
1093   * @return Number of bytes read, otherwise negative error code
1094   *
1095   * Environments:
1096   *
1097   * Depends on driver implementation, see @ref profiles "Device Profiles".
1098   *
1099   * Rescheduling: possible.
1100   *
1101   * @see @c read() in IEEE Std 1003.1,
1102   * http://www.opengroup.org/onlinepubs/009695399
1103   */
1104  ssize_t rt_dev_read(int fd, void *buf, size_t nbyte);
1105  
1106  /**
1107   * @brief Write to device
1108   *
1109   * @param[in] fd File descriptor as returned by rt_dev_open()
1110   * @param[in] buf Output buffer
1111   * @param[in] nbyte Number of bytes to write
1112   *
1113   * @return Number of bytes written, otherwise negative error code
1114   *
1115   * Environments:
1116   *
1117   * Depends on driver implementation, see @ref profiles "Device Profiles".
1118   *
1119   * Rescheduling: possible.
1120   *
1121   * @see @c write() in IEEE Std 1003.1,
1122   * http://www.opengroup.org/onlinepubs/009695399
1123   */
1124  ssize_t rt_dev_write(int fd, const void *buf, size_t nbyte);
1125  
1126  /**
1127   * @brief Receive message from socket
1128   *
1129   * @param[in] fd File descriptor as returned by rt_dev_socket()
1130   * @param[in,out] msg Message descriptor
1131   * @param[in] flags Message flags
1132   *
1133   * @return Number of bytes received, otherwise negative error code
1134   *
1135   * Environments:
1136   *
1137   * Depends on driver implementation, see @ref profiles "Device Profiles".
1138   *
1139   * Rescheduling: possible.
1140   *
1141   * @see @c recvmsg() in IEEE Std 1003.1,
1142   * http://www.opengroup.org/onlinepubs/009695399
1143   */
1144  ssize_t rt_dev_recvmsg(int fd, struct msghdr *msg, int flags);
1145  
1146  /**
1147   * @brief Receive message from socket
1148   *
1149   * @param[in] fd File descriptor as returned by rt_dev_socket()
1150   * @param[out] buf Message buffer
1151   * @param[in] len Message buffer size
1152   * @param[in] flags Message flags
1153   * @param[out] from Buffer for message sender address
1154   * @param[in,out] fromlen Address buffer size
1155   *
1156   * @return Number of bytes received, otherwise negative error code
1157   *
1158   * Environments:
1159   *
1160   * Depends on driver implementation, see @ref profiles "Device Profiles".
1161   *
1162   * Rescheduling: possible.
1163   *
1164   * @see @c recvfrom() in IEEE Std 1003.1,
1165   * http://www.opengroup.org/onlinepubs/009695399
1166   */
1167  ssize_t rt_dev_recvfrom(int fd, void *buf, size_t len, int flags,
1168  			struct sockaddr *from, socklen_t *fromlen);
1169  
1170  /**
1171   * @brief Receive message from socket
1172   *
1173   * @param[in] fd File descriptor as returned by rt_dev_socket()
1174   * @param[out] buf Message buffer
1175   * @param[in] len Message buffer size
1176   * @param[in] flags Message flags
1177   *
1178   * @return Number of bytes received, otherwise negative error code
1179   *
1180   * Environments:
1181   *
1182   * Depends on driver implementation, see @ref profiles "Device Profiles".
1183   *
1184   * Rescheduling: possible.
1185   *
1186   * @see @c recv() in IEEE Std 1003.1,
1187   * http://www.opengroup.org/onlinepubs/009695399
1188   */
1189  ssize_t rt_dev_recv(int fd, void *buf, size_t len, int flags);
1190  
1191  /**
1192   * @brief Transmit message to socket
1193   *
1194   * @param[in] fd File descriptor as returned by rt_dev_socket()
1195   * @param[in] msg Message descriptor
1196   * @param[in] flags Message flags
1197   *
1198   * @return Number of bytes sent, otherwise negative error code
1199   *
1200   * Environments:
1201   *
1202   * Depends on driver implementation, see @ref profiles "Device Profiles".
1203   *
1204   * Rescheduling: possible.
1205   *
1206   * @see @c sendmsg() in IEEE Std 1003.1,
1207   * http://www.opengroup.org/onlinepubs/009695399
1208   */
1209  ssize_t rt_dev_sendmsg(int fd, const struct msghdr *msg, int flags);
1210  
1211  /**
1212   * @brief Transmit message to socket
1213   *
1214   * @param[in] fd File descriptor as returned by rt_dev_socket()
1215   * @param[in] buf Message buffer
1216   * @param[in] len Message buffer size
1217   * @param[in] flags Message flags
1218   * @param[in] to Buffer for message destination address
1219   * @param[in] tolen Address buffer size
1220   *
1221   * @return Number of bytes sent, otherwise negative error code
1222   *
1223   * Environments:
1224   *
1225   * Depends on driver implementation, see @ref profiles "Device Profiles".
1226   *
1227   * Rescheduling: possible.
1228   *
1229   * @see @c sendto() in IEEE Std 1003.1,
1230   * http://www.opengroup.org/onlinepubs/009695399
1231   */
1232  ssize_t rt_dev_sendto(int fd, const void *buf, size_t len, int flags,
1233  		      const struct sockaddr *to, socklen_t tolen);
1234  
1235  /**
1236   * @brief Transmit message to socket
1237   *
1238   * @param[in] fd File descriptor as returned by rt_dev_socket()
1239   * @param[in] buf Message buffer
1240   * @param[in] len Message buffer size
1241   * @param[in] flags Message flags
1242   *
1243   * @return Number of bytes sent, otherwise negative error code
1244   *
1245   * Environments:
1246   *
1247   * Depends on driver implementation, see @ref profiles "Device Profiles".
1248   *
1249   * Rescheduling: possible.
1250   *
1251   * @see @c send() in IEEE Std 1003.1,
1252   * http://www.opengroup.org/onlinepubs/009695399
1253   */
1254  ssize_t rt_dev_send(int fd, const void *buf, size_t len, int flags);
1255  
1256  /**
1257   * @brief Bind to local address
1258   *
1259   * @param[in] fd File descriptor as returned by rt_dev_socket()
1260   * @param[in] my_addr Address buffer
1261   * @param[in] addrlen Address buffer size
1262   *
1263   * @return 0 on success, otherwise negative error code
1264   *
1265   * Environments:
1266   *
1267   * Depends on driver implementation, see @ref profiles "Device Profiles".
1268   *
1269   * Rescheduling: possible.
1270   *
1271   * @see @c bind() in IEEE Std 1003.1,
1272   * http://www.opengroup.org/onlinepubs/009695399
1273   */
1274  int rt_dev_bind(int fd, const struct sockaddr *my_addr, socklen_t addrlen);
1275  
1276  /**
1277   * @brief Connect to remote address
1278   *
1279   * @param[in] fd File descriptor as returned by rt_dev_socket()
1280   * @param[in] serv_addr Address buffer
1281   * @param[in] addrlen Address buffer size
1282   *
1283   * @return 0 on success, otherwise negative error code
1284   *
1285   * Environments:
1286   *
1287   * Depends on driver implementation, see @ref profiles "Device Profiles".
1288   *
1289   * Rescheduling: possible.
1290   *
1291   * @see @c connect() in IEEE Std 1003.1,
1292   * http://www.opengroup.org/onlinepubs/009695399
1293   */
1294  int rt_dev_connect(int fd, const struct sockaddr *serv_addr,
1295  		   socklen_t addrlen);
1296  
1297  /**
1298   * @brief Listen for incomming connection requests
1299   *
1300   * @param[in] fd File descriptor as returned by rt_dev_socket()
1301   * @param[in] backlog Maximum queue length
1302   *
1303   * @return 0 on success, otherwise negative error code
1304   *
1305   * Environments:
1306   *
1307   * Depends on driver implementation, see @ref profiles "Device Profiles".
1308   *
1309   * Rescheduling: possible.
1310   *
1311   * @see @c lsiten() in IEEE Std 1003.1,
1312   * http://www.opengroup.org/onlinepubs/009695399
1313   */
1314  int rt_dev_listen(int fd, int backlog);
1315  
1316  /**
1317   * @brief Accept a connection requests
1318   *
1319   * @param[in] fd File descriptor as returned by rt_dev_socket()
1320   * @param[out] addr Buffer for remote address
1321   * @param[in,out] addrlen Address buffer size
1322   *
1323   * @return 0 on success, otherwise negative error code
1324   *
1325   * Environments:
1326   *
1327   * Depends on driver implementation, see @ref profiles "Device Profiles".
1328   *
1329   * Rescheduling: possible.
1330   *
1331   * @see @c accept() in IEEE Std 1003.1,
1332   * http://www.opengroup.org/onlinepubs/009695399
1333   */
1334  int rt_dev_accept(int fd, struct sockaddr *addr, socklen_t *addrlen);
1335  
1336  /**
1337   * @brief Shut down parts of a connection
1338   *
1339   * @param[in] fd File descriptor as returned by rt_dev_socket()
1340   * @param[in] how Specifies the part to be shut down (@c SHUT_xxx)
1341  *
1342   * @return 0 on success, otherwise negative error code
1343   *
1344   * Environments:
1345   *
1346   * Depends on driver implementation, see @ref profiles "Device Profiles".
1347   *
1348   * Rescheduling: possible.
1349   *
1350   * @see @c shutdown() in IEEE Std 1003.1,
1351   * http://www.opengroup.org/onlinepubs/009695399
1352   */
1353  int rt_dev_shutdown(int fd, int how);
1354  
1355  /**
1356   * @brief Get socket option
1357   *
1358   * @param[in] fd File descriptor as returned by rt_dev_socket()
1359   * @param[in] level Addressed stack level
1360   * @param[in] optname Option name ID
1361   * @param[out] optval Value buffer
1362   * @param[in,out] optlen Value buffer size
1363   *
1364   * @return 0 on success, otherwise negative error code
1365   *
1366   * Environments:
1367   *
1368   * Depends on driver implementation, see @ref profiles "Device Profiles".
1369   *
1370   * Rescheduling: possible.
1371   *
1372   * @see @c getsockopt() in IEEE Std 1003.1,
1373   * http://www.opengroup.org/onlinepubs/009695399
1374   */
1375  int rt_dev_getsockopt(int fd, int level, int optname, void *optval,
1376  		      socklen_t *optlen);
1377  
1378  /**
1379   * @brief Set socket option
1380   *
1381   * @param[in] fd File descriptor as returned by rt_dev_socket()
1382   * @param[in] level Addressed stack level
1383   * @param[in] optname Option name ID
1384   * @param[in] optval Value buffer
1385   * @param[in] optlen Value buffer size
1386   *
1387   * @return 0 on success, otherwise negative error code
1388   *
1389   * Environments:
1390   *
1391   * Depends on driver implementation, see @ref profiles "Device Profiles".
1392   *
1393   * Rescheduling: possible.
1394   *
1395   * @see @c setsockopt() in IEEE Std 1003.1,
1396   * http://www.opengroup.org/onlinepubs/009695399
1397   */
1398  int rt_dev_setsockopt(int fd, int level, int optname, const void *optval,
1399  		      socklen_t optlen);
1400  
1401  /**
1402   * @brief Get local socket address
1403   *
1404   * @param[in] fd File descriptor as returned by rt_dev_socket()
1405   * @param[out] name Address buffer
1406   * @param[in,out] namelen Address buffer size
1407   *
1408   * @return 0 on success, otherwise negative error code
1409   *
1410   * Environments:
1411   *
1412   * Depends on driver implementation, see @ref profiles "Device Profiles".
1413   *
1414   * Rescheduling: possible.
1415   *
1416   * @see @c getsockname() in IEEE Std 1003.1,
1417   * http://www.opengroup.org/onlinepubs/009695399
1418   */
1419  int rt_dev_getsockname(int fd, struct sockaddr *name, socklen_t *namelen);
1420  
1421  /**
1422   * @brief Get socket destination address
1423   *
1424   * @param[in] fd File descriptor as returned by rt_dev_socket()
1425   * @param[out] name Address buffer
1426   * @param[in,out] namelen Address buffer size
1427   *
1428   * @return 0 on success, otherwise negative error code
1429   *
1430   * Environments:
1431   *
1432   * Depends on driver implementation, see @ref profiles "Device Profiles".
1433   *
1434   * Rescheduling: possible.
1435   *
1436   * @see @c getpeername() in IEEE Std 1003.1,
1437   * http://www.opengroup.org/onlinepubs/009695399
1438   */
1439  int rt_dev_getpeername(int fd, struct sockaddr *name, socklen_t *namelen);
1440  /** @} */
1441  
1442  #endif /* DOXYGEN_CPP */
1443  
1444  #ifdef CONFIG_RTAI_RTDM_SELECT
1445  
1446  /*
1447   RTAI extension to use select as any other usual RTDM rt_dev_xxx service.
1448   At the moment selector kept and stack, initialised/destroyed at each call.
1449   Usage is as for: 
1450   int rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds,
1451                     nanosecs_rel_t timeout);.
1452   As it can be seen args are as for the standard select call execpt for the
1453   timout which is in nanos, in place of timespec.
1454  */
1455  
1456  #define SELECT_DIM  XNSELECT_MAX_TYPES
1457  
1458  /*
1459  RTDM_FD_START kept in case we'll ever need a shift for fd being different from 
1460  fd_index in the call to:
1461  int rtdm_select_bind(int fd, rtdm_selector_t *selector, enum rtdm_selecttype type, unsigned fd_index);
1462  */
1463  
1464  #define RTDM_FD_START  0
1465  
1466  int __rt_dev_select(int nfds, fd_set *rfds, fd_set *wfds, fd_set *efds, nanosecs_rel_t timeout, struct xnselector *selector, int space)
1467  {
1468  	int i, fd, ret;
1469  	fd_set *fds[SELECT_DIM] = { rfds, wfds, efds };
1470  	fd_set *reqp[SELECT_DIM], req[SELECT_DIM];
1471  	fd_set *resp[SELECT_DIM], res[SELECT_DIM];
1472  	fd_set **bp, *cp;
1473  
1474  	for (ret = i = 0; i < SELECT_DIM; i++) {
1475  		if (fds[i] && find_first_bit(fds[i]->fds_bits, nfds) < nfds) {
1476  			ret = 1;
1477  			reqp[i] = &req[i];
1478  			resp[i] = &res[i];
1479  			if (space) {
1480  				memcpy((void *)reqp[i], (void *)fds[i], __FDELT__(nfds + __NFDBITS__ - 1)*sizeof(long));
1481  			} else {
1482  				rt_copy_from_user((void *)reqp[i], (void *)fds[i], __FDELT__(nfds + __NFDBITS__ - 1)*sizeof(long));
1483  			}
1484  		} else {
1485  			reqp[i] = resp[i] = NULL;
1486  		}
1487  	}
1488  
1489  	if (!ret && !timeout) {
1490  		return -EINVAL;
1491  	}
1492  
1493  	if (timeout) {
1494  		timeout = rt_get_time() + nano2count(timeout);
1495  	}
1496  
1497  	do {
1498  		for (bp = reqp, i = 0; i < SELECT_DIM; i++) {
1499  			if ((cp = bp[i])) {
1500  				for (fd = find_first_bit(cp->fds_bits, nfds); fd < nfds; fd = find_next_bit(cp->fds_bits, nfds, fd + 1)) {
1501  					if ((ret = rtdm_select_bind(fd - RTDM_FD_START, selector, i, fd))) {
1502  						return ret;
1503  					}
1504  				}
1505  			}
1506  		}
1507  		bp = resp;
1508  		ret = xnselect(selector, resp, reqp, nfds, timeout, XN_ABSOLUTE);
1509  	} while (ret == -ECHRNG);
1510  
1511  	if (ret > 0) {
1512  		for (i = 0; i < SELECT_DIM; i++) {
1513  			if (fds[i]) {
1514  				if (space) {
1515  					memcpy((void *)fds[i], (void *)resp[i], sizeof(fd_set));
1516  				} else {
1517  					rt_copy_to_user((void *)fds[i], (void *)resp[i], sizeof(fd_set));
1518  				}
1519  			}
1520  		}
1521  	}
1522  	return ret;
1523  }
1524  
1525  EXPORT_SYMBOL(__rt_dev_select);
1526  
1527  #endif