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