/* --- Command descriptor management functions --- */ int a4l_fill_cmddesc(struct a4l_device_context *cxt, struct a4l_cmd_desc *desc, unsigned int **chan_descs, void *arg) { unsigned int *tmpchans = NULL; int ret = 0; ret = rtdm_safe_copy_from_user(rtdm_private_to_fd(cxt), desc, arg, sizeof(struct a4l_cmd_desc)); if (ret != 0) goto out_cmddesc; if (desc->nb_chan == 0) { ret = -EINVAL; goto out_cmddesc; } tmpchans = rtdm_malloc(desc->nb_chan * sizeof(unsigned int)); if (tmpchans == NULL) { ret = -ENOMEM; goto out_cmddesc; } ret = rtdm_safe_copy_from_user(rtdm_private_to_fd(cxt), tmpchans, desc->chan_descs, desc->nb_chan * sizeof(unsigned int)); if (ret != 0) { __a4l_err("%s invalid arguments \n", __FUNCTION__); goto out_cmddesc; } *chan_descs = desc->chan_descs; desc->chan_descs = tmpchans; __a4l_dbg(1, core_dbg, "desc dump: \n"); __a4l_dbg(1, core_dbg, "\t->idx_subd=%u\n", desc->idx_subd); __a4l_dbg(1, core_dbg, "\t->flags=%lu\n", desc->flags); __a4l_dbg(1, core_dbg, "\t->nb_chan=%u\n", desc->nb_chan); __a4l_dbg(1, core_dbg, "\t->chan_descs=0x%x\n", *desc->chan_descs); __a4l_dbg(1, core_dbg, "\t->data_len=%u\n", desc->data_len); __a4l_dbg(1, core_dbg, "\t->pdata=0x%p\n", desc->data); out_cmddesc: if (ret != 0) { __a4l_err("a4l_fill_cmddesc: %d \n", ret); if (tmpchans != NULL) rtdm_free(tmpchans); desc->chan_descs = NULL; } return ret; }
int a4l_fill_insndsc(a4l_cxt_t * cxt, a4l_kinsn_t * dsc, void *arg) { int ret = 0; void *tmp_data = NULL; ret = rtdm_safe_copy_from_user(cxt->user_info, dsc, arg, sizeof(a4l_insn_t)); if (ret != 0) goto out_insndsc; if (dsc->data_size != 0 && dsc->data == NULL) { __a4l_err("a4l_fill_insndsc: no data pointer specified\n"); ret = -EINVAL; goto out_insndsc; } if (dsc->data_size != 0 && dsc->data != NULL) { tmp_data = rtdm_malloc(dsc->data_size); if (tmp_data == NULL) { ret = -ENOMEM; goto out_insndsc; } if ((dsc->type & A4L_INSN_MASK_WRITE) != 0) { ret = rtdm_safe_copy_from_user(cxt->user_info, tmp_data, dsc->data, dsc->data_size); if (ret < 0) goto out_insndsc; } } dsc->__udata = dsc->data; dsc->data = tmp_data; out_insndsc: if (ret != 0 && tmp_data != NULL) rtdm_free(tmp_data); return ret; }
/** * Write in the device * * This function is called when the device is written in non-realtime context. * */ static ssize_t simple_rtdm_write_nrt(struct rtdm_dev_context *context, rtdm_user_info_t * user_info, const void *buf, size_t nbyte) { buffer_t * buffer = (buffer_t *) context->dev_private; buffer->size = (nbyte > SIZE_MAX) ? SIZE_MAX : nbyte; if (rtdm_safe_copy_from_user(user_info, buffer->data, buf, buffer->size)) rtdm_printk("ERROR : can't copy data to driver\n"); return nbyte; }
int a4l_fill_ilstdsc(a4l_cxt_t * cxt, a4l_kilst_t * dsc, void *arg) { int i, ret = 0; dsc->insns = NULL; /* Recovers the structure from user space */ ret = rtdm_safe_copy_from_user(cxt->user_info, dsc, arg, sizeof(a4l_insnlst_t)); if (ret < 0) return ret; /* Some basic checking */ if (dsc->count == 0) { __a4l_err("a4l_fill_ilstdsc: instruction list's count is 0\n"); return -EINVAL; } /* Keeps the user pointer in an opaque field */ dsc->__uinsns = (a4l_insn_t *)dsc->insns; dsc->insns = rtdm_malloc(dsc->count * sizeof(a4l_kinsn_t)); if (dsc->insns == NULL) return -ENOMEM; /* Recovers the instructions, one by one. This part is not optimized */ for (i = 0; i < dsc->count && ret == 0; i++) ret = a4l_fill_insndsc(cxt, &(dsc->insns[i]), &(dsc->__uinsns[i])); /* In case of error, frees the allocated memory */ if (ret < 0 && dsc->insns != NULL) rtdm_free(dsc->insns); return ret; }
static ssize_t uart_wr_rt(struct rtdm_dev_context *context,rtdm_user_info_t * user_info,const void *buf, size_t nbyte) { int ret=0; int err; int count; char c; MY_DEV *up=(MY_DEV *)context->device->device_data; char *tmp; up->buf_len_tx = nbyte; printk("uart_wr_rt start\n"); tmp=rtdm_malloc(nbyte); if ((rtdm_safe_copy_from_user(user_info,tmp, buf, up->buf_len_tx))) rtdm_printk("ERROR : can't copy data to driver\n"); count=nbyte; while(count--) { write_buffer(up,*tmp); tmp=tmp+1; // up->buf_tx=(char *)tmp; // printk("up->buf_tx=%x\n",*up->buf_tx); //enable Trasmitter holding Register if (!(up->ier & UART_IER_THRI)) { up->ier |= UART_IER_THRI; up->systime = rtdm_clock_read(); serial_out(up, UART_IER, up->ier); } } printk("Tx interrupt enable\n"); printk("rtdm_event_wait before\n"); err=rtdm_event_wait(&up->w_event_tx); if(err<0) { dev_err(up->dev,"controller timed out\n"); rtdm_printk("rtdm_event_timedwait: timeout\n"); return -ETIMEDOUT; } up->systime1 = rtdm_clock_read(); up->timeout=(up->systime1)-(up->systime); printk("scheduling latency=%ld\n",up->timeout); if(err==0) { ret=nbyte; } printk("rtdm_event_wait after\n"); printk("uart_wr_rt end\n"); rtdm_free(tmp); return ret; }
int a4l_fill_lnkdesc(a4l_cxt_t * cxt, a4l_lnkdesc_t * link_arg, void *arg) { int ret; char *tmpname = NULL; void *tmpopts = NULL; ret = rtdm_safe_copy_from_user(cxt->user_info, link_arg, arg, sizeof(a4l_lnkdesc_t)); if (ret != 0) { __a4l_err("a4l_fill_lnkdesc: " "call1(copy_from_user) failed\n"); goto out_get_lnkdesc; } if (link_arg->bname_size != 0 && link_arg->bname != NULL) { tmpname = rtdm_malloc(link_arg->bname_size + 1); if (tmpname == NULL) { __a4l_err("a4l_fill_lnkdesc: " "call1(alloc) failed\n"); ret = -ENOMEM; goto out_get_lnkdesc; } tmpname[link_arg->bname_size] = 0; ret = rtdm_safe_copy_from_user(cxt->user_info, tmpname, link_arg->bname, link_arg->bname_size); if (ret != 0) { __a4l_err("a4l_fill_lnkdesc: " "call2(copy_from_user) failed\n"); goto out_get_lnkdesc; } } else { __a4l_err("a4l_fill_lnkdesc: board name missing\n"); ret = -EINVAL; goto out_get_lnkdesc; } if (link_arg->opts_size != 0 && link_arg->opts != NULL) { tmpopts = rtdm_malloc(link_arg->opts_size); if (tmpopts == NULL) { __a4l_err("a4l_fill_lnkdesc: " "call2(alloc) failed\n"); ret = -ENOMEM; goto out_get_lnkdesc; } ret = rtdm_safe_copy_from_user(cxt->user_info, tmpopts, link_arg->opts, link_arg->opts_size); if (ret != 0) { __a4l_err("a4l_fill_lnkdesc: " "call3(copy_from_user) failed\n"); goto out_get_lnkdesc; } } link_arg->bname = tmpname; link_arg->opts = tmpopts; out_get_lnkdesc: if (tmpname == NULL) { link_arg->bname = NULL; link_arg->bname_size = 0; } if (tmpopts == NULL) { link_arg->opts = NULL; link_arg->opts_size = 0; } return ret; }
static int rtdmtest_ioctl(struct rtdm_dev_context *context, rtdm_user_info_t *user_info, unsigned int request, void *arg) { struct rtdmtest_context *ctx; struct rttst_rtdmtest_config config_buf, *config; rtdm_toseq_t toseq_local, *toseq = NULL; int i, err = 0; ctx = (struct rtdmtest_context *)context->dev_private; switch (request) { case RTTST_RTIOC_RTDMTEST_SEM_TIMEDDOWN: case RTTST_RTIOC_RTDMTEST_EVENT_TIMEDWAIT: case RTTST_RTIOC_RTDMTEST_MUTEX_TIMEDTEST: case RTTST_RTIOC_RTDMTEST_MUTEX_TEST: config = arg; if (user_info) { if (rtdm_safe_copy_from_user (user_info, &config_buf, arg, sizeof(struct rttst_rtdmtest_config)) < 0) return -EFAULT; config = &config_buf; } if (!config->seqcount) config->seqcount = 1; if (config->timeout && config->seqcount > 1) { toseq = &toseq_local; rtdm_toseq_init(toseq, config->timeout); } switch(request) { case RTTST_RTIOC_RTDMTEST_SEM_TIMEDDOWN: for (i = 0; i < config->seqcount; i++) { err = rtdm_sem_timeddown(&ctx->sem, config->timeout, toseq); if (err) break; } break; case RTTST_RTIOC_RTDMTEST_EVENT_TIMEDWAIT: for (i = 0; i < config->seqcount; i++) { err = rtdm_event_timedwait(&ctx->event, config->timeout, toseq); if (err) break; } break; case RTTST_RTIOC_RTDMTEST_MUTEX_TIMEDTEST: for (i = 0; i < config->seqcount; i++) { err = rtdm_mutex_timedlock(&ctx->mutex, config->timeout, toseq); if (err) break; if (config->delay_jiffies) { __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(config->delay_jiffies); } rtdm_lock_count++; rtdm_mutex_unlock(&ctx->mutex); } break; case RTTST_RTIOC_RTDMTEST_MUTEX_TEST: for (i = 0; i < config->seqcount; i++) { if ((err = rtdm_mutex_lock(&ctx->mutex))) break; rtdm_lock_count++; rtdm_mutex_unlock(&ctx->mutex); } break; } break; case RTTST_RTIOC_RTDMTEST_SEM_DOWN: err = rtdm_sem_down(&ctx->sem); break; case RTTST_RTIOC_RTDMTEST_SEM_UP: rtdm_sem_up(&ctx->sem); break; case RTTST_RTIOC_RTDMTEST_SEM_DESTROY: rtdm_sem_destroy(&ctx->sem); break; case RTTST_RTIOC_RTDMTEST_EVENT_WAIT: err = rtdm_event_wait(&ctx->event); break; case RTTST_RTIOC_RTDMTEST_EVENT_SIGNAL: rtdm_event_signal(&ctx->event); break; case RTTST_RTIOC_RTDMTEST_EVENT_DESTROY: rtdm_event_destroy(&ctx->event); break; case RTTST_RTIOC_RTDMTEST_MUTEX_DESTROY: rtdm_mutex_destroy(&ctx->mutex); break; case RTTST_RTIOC_RTDMTEST_MUTEX_GETSTAT: printk("RTTST_RTIOC_RTDMTEST_MUTEX_GETSTAT\n"); if (user_info) config = &config_buf; else config = arg; config->seqcount = rtdm_lock_count; if (user_info) { if (rtdm_safe_copy_to_user (user_info, arg, &config_buf, sizeof(struct rttst_rtdmtest_config)) < 0) return -EFAULT; } break; case RTTST_RTIOC_RTDMTEST_NRTSIG_PEND: rtdm_nrtsig_pend(&ctx->nrtsig); break; case RTTST_RTIOC_RTDMTEST_TASK_CREATE: case RTTST_RTIOC_RTDMTEST_TASK_SET_PRIO: config = arg; if (user_info) { if (rtdm_safe_copy_from_user (user_info, &config_buf, arg, sizeof(struct rttst_rtdmtest_config)) < 0) return -EFAULT; config = &config_buf; } if (request == RTTST_RTIOC_RTDMTEST_TASK_CREATE) { task_period = config->timeout; rtdm_task_init(&task, "RTDMTEST", rtdmtest_task, (void *)config, config->priority, 0); } else { rtdm_task_set_priority(&task, config->priority); } break; case RTTST_RTIOC_RTDMTEST_TASK_DESTROY: rtdm_task_destroy(&task); rtdm_task_join_nrt(&task, 100); break; default: printk("request=%d\n", request); err = -ENOTTY; } return err; }