int demo_ioctl_rt(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg) { struct demodrv_context *my_context; #ifdef USEMMAP int err; #endif int ret = 0; my_context = (struct demodrv_context *)context->dev_private; switch (request) { case MMAP: // set mmap pointer #ifdef USEMMAP printk("buf = %p:%x\n", my_context->buf, *(int *)my_context->buf); err = rtdm_mmap_to_user(user_info, my_context->buf, BUFFER_SIZE, PROT_READ|PROT_WRITE, (void **)arg, &mmap_ops, (void *)0x12345678); if (!err) { my_context->mapped_user_info = user_info; my_context->mapped_user_addr = *(void **)arg; } printk("rtdm_mmap = %p %d\n", my_context->mapped_user_info, err); #else return -EPERM; #endif break; case GETVALUE: // write "ioctlvalue" to user if (user_info) { if (!rtdm_rw_user_ok(user_info, arg, sizeof(int)) || rtdm_copy_to_user(user_info, arg, &ioctlvalue, sizeof(int))) return -EFAULT; } else memcpy(arg, &ioctlvalue, sizeof(int)); break; case SETVALUE: // read "ioctlvalue" from user if (user_info) { if ((unsigned long)arg < BUFFER_SIZE) ioctlvalue = ((int *)my_context->buf)[(unsigned long)arg]; else if (!rtdm_read_user_ok(user_info, arg, sizeof(int)) || rtdm_copy_from_user(user_info, &ioctlvalue, arg, sizeof(int))) return -EFAULT; } break; default: ret = -ENOTTY; } return ret; }
static int rtswitch_ioctl_rt(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg) { rtswitch_context_t *ctx = (rtswitch_context_t *) context->dev_private; struct rttst_swtest_task task; struct rttst_swtest_dir fromto; switch (request) { case RTTST_RTIOC_SWTEST_REGISTER_UTASK: case RTTST_RTIOC_SWTEST_CREATE_KTASK: case RTTST_RTIOC_SWTEST_GET_SWITCHES_COUNT: return -ENOSYS; case RTTST_RTIOC_SWTEST_PEND: if (!rtdm_read_user_ok(user_info, arg, sizeof(task))) return -EFAULT; rtdm_copy_from_user(user_info, &task, arg, sizeof(task)); return rtswitch_pend_rt(ctx, task.index); case RTTST_RTIOC_SWTEST_SWITCH_TO: if (!rtdm_read_user_ok(user_info, arg, sizeof(fromto))) return -EFAULT; rtdm_copy_from_user(user_info, &fromto, arg, sizeof(fromto)); return rtswitch_to_rt(ctx, fromto.from, fromto.to); case RTTST_RTIOC_SWTEST_GET_LAST_ERROR: if (!rtdm_rw_user_ok(user_info, arg, sizeof(ctx->error))) return -EFAULT; rtdm_copy_to_user(user_info, arg, &ctx->error, sizeof(ctx->error)); return 0; default: return -ENOTTY; } }
int demo_read_rt(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, void *buf, size_t nbyte) { struct demodrv_context *ctx; int dev_id; // rtdm_lockctx_t lock_ctx; char *out_pos = (char *)buf; rtdm_toseq_t timeout_seq; int ret; // zero bytes requested ? return! if (nbyte == 0) return 0; // check if R/W actions to user-space are allowed if (user_info && !rtdm_rw_user_ok(user_info, buf, nbyte)) return -EFAULT; ctx = (struct demodrv_context *)context->dev_private; dev_id = ctx->dev_id; // in case we need to check if reading is allowed (locking) /* if (test_and_set_bit(0, &ctx->in_lock)) return -EBUSY; */ /* // if we need to do some stuff with preemption disabled: rtdm_lock_get_irqsave(&ctx->lock, lock_ctx); // stuff here rtdm_lock_put_irqrestore(&ctx->lock, lock_ctx); */ // wait: if ctx->timeout = 0, it will block infintely until // rtdm_event_signal(&ctx->irq_event); is called from our // interrupt routine ret = rtdm_event_timedwait(&ctx->irq_event, ctx->timeout, &timeout_seq); // now write the requested stuff to user-space if (rtdm_copy_to_user(user_info, out_pos, dummy_buffer, BUFSIZE) != 0) { ret = -EFAULT; } else { ret = BUFSIZE; } return ret; }
static int rtswitch_ioctl_nrt(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg) { rtswitch_context_t *ctx = (rtswitch_context_t *) context->dev_private; struct rttst_swtest_task task; struct rttst_swtest_dir fromto; unsigned long count; int err; switch (request) { case RTTST_RTIOC_SWTEST_SET_TASKS_COUNT: return rtswitch_set_tasks_count(ctx, (unsigned long) arg); case RTTST_RTIOC_SWTEST_SET_CPU: if ((unsigned long) arg > xnarch_num_online_cpus() - 1) return -EINVAL; ctx->cpu = (unsigned long) arg; return 0; case RTTST_RTIOC_SWTEST_SET_PAUSE: ctx->pause_us = (unsigned long) arg; return 0; case RTTST_RTIOC_SWTEST_REGISTER_UTASK: if (!rtdm_rw_user_ok(user_info, arg, sizeof(task))) return -EFAULT; rtdm_copy_from_user(user_info, &task, arg, sizeof(task)); err = rtswitch_register_task(ctx, &task); if (!err) rtdm_copy_to_user(user_info, arg, &task, sizeof(task)); return err; case RTTST_RTIOC_SWTEST_CREATE_KTASK: if (!rtdm_rw_user_ok(user_info, arg, sizeof(task))) return -EFAULT; rtdm_copy_from_user(user_info, &task, arg, sizeof(task)); err = rtswitch_create_ktask(ctx, &task); if (!err) rtdm_copy_to_user(user_info, arg, &task, sizeof(task)); return err; case RTTST_RTIOC_SWTEST_PEND: if (!rtdm_read_user_ok(user_info, arg, sizeof(task))) return -EFAULT; rtdm_copy_from_user(user_info, &task, arg, sizeof(task)); return rtswitch_pend_nrt(ctx, task.index); case RTTST_RTIOC_SWTEST_SWITCH_TO: if (!rtdm_read_user_ok(user_info, arg, sizeof(fromto))) return -EFAULT; rtdm_copy_from_user(user_info, &fromto, arg, sizeof(fromto)); return rtswitch_to_nrt(ctx, fromto.from, fromto.to); case RTTST_RTIOC_SWTEST_GET_SWITCHES_COUNT: if (!rtdm_rw_user_ok(user_info, arg, sizeof(count))) return -EFAULT; count = ctx->switches_count; rtdm_copy_to_user(user_info, arg, &count, sizeof(count)); return 0; case RTTST_RTIOC_SWTEST_GET_LAST_ERROR: if (!rtdm_rw_user_ok(user_info, arg, sizeof(ctx->error))) return -EFAULT; rtdm_copy_to_user(user_info, arg, &ctx->error, sizeof(ctx->error)); return 0; default: return -ENOTTY; } }
// userpace task receives data from userspace mailbox static unsigned long tims_copy_userslot_user(rtdm_user_info_t *user_info, tims_mbx_slot *slot, const struct msghdr *msg) { unsigned long akt_copy_size = 0; unsigned long copy_bytes = 0; unsigned long bytes_copied = 0; unsigned long bytes_in_page = 0; int i; unsigned long ret; unsigned long p_src_map = slot->p_head_map; void *p_src = slot->p_head; void *p_dest = NULL; unsigned long src_page = slot->map_idx; tims_msg_head *p_head = (tims_msg_head *)slot->p_head_map; unsigned long databytes = p_head->msglen - TIMS_HEADLEN; for (i=0; i<2; i++) { if (!i) copy_bytes = TIMS_HEADLEN; else copy_bytes = databytes; p_dest = msg->msg_iov[i].iov_base; // check destination pointer ret = rtdm_rw_user_ok(user_info, p_dest, copy_bytes); if (!ret) { tims_error("ERROR: userspace destination 0x%p (%lu bytes) NOT OK \n", p_dest, copy_bytes); return ret; } // copy data while (copy_bytes) { bytes_in_page = get_remain_bytes_in_page(p_src_map); akt_copy_size = min_t(unsigned long, bytes_in_page, copy_bytes); ret = rtdm_copy_to_user(user_info, p_dest, (void *)p_src_map, akt_copy_size); if (ret) { if (ret < 0) { tims_error("ERROR while copy userbuffer -> user, " "code = %lu \n", ret); } else { tims_error("ERROR while copy userbuffer -> user, " "only %lu/%lu bytes were copied \n", akt_copy_size - ret, akt_copy_size); } return ret; } bytes_in_page -= akt_copy_size; copy_bytes -= akt_copy_size; p_src_map += akt_copy_size; p_src += akt_copy_size; p_dest += akt_copy_size; bytes_copied += akt_copy_size; if (!bytes_in_page) { src_page++; if (slot->p_mbx->p_mapInfo[src_page].mapped) { p_src_map = slot->p_mbx->p_mapInfo[src_page].virtual; } else { return -EFAULT; } }