int a4l_close(struct rtdm_dev_context *context, rtdm_user_info_t * user_info) { int err; a4l_cxt_t *cxt = (a4l_cxt_t *)rtdm_context_to_private(context); /* Cancel the maybe occuring asynchronous transfer */ err = a4l_cancel_buffer(cxt); if (err < 0) { __a4l_err("close: unable to stop the asynchronous transfer\n"); return err; } /* Free the buffer which was linked with this context and... */ a4l_free_buffer(cxt->buffer); /* ...free the other buffer resources (sync) and... */ a4l_cleanup_buffer(cxt->buffer); /* ...free the structure */ rtdm_free(cxt->buffer); return 0; }
int a4l_ioctl_cmd(struct a4l_device_context * ctx, void *arg) { int ret = 0, simul_flag = 0; struct a4l_cmd_desc *cmd_desc = NULL; struct a4l_device *dev = a4l_get_dev(ctx); unsigned int *chan_descs, *tmp; struct a4l_subdevice *subd; /* The command launching cannot be done in real-time because of some possible buffer allocations in the drivers */ if (rtdm_in_rt_context()) return -ENOSYS; /* Basically check the device */ if (!test_bit(A4L_DEV_ATTACHED_NR, &dev->flags)) { __a4l_err("a4l_ioctl_cmd: cannot command " "an unattached device\n"); return -EINVAL; } /* Allocates the command */ cmd_desc = (struct a4l_cmd_desc *) rtdm_malloc(sizeof(struct a4l_cmd_desc)); if (cmd_desc == NULL) return -ENOMEM; memset(cmd_desc, 0, sizeof(struct a4l_cmd_desc)); /* Gets the command */ ret = a4l_fill_cmddesc(ctx, cmd_desc, &chan_descs, arg); if (ret != 0) goto out_ioctl_cmd; /* Checks the command */ ret = a4l_check_cmddesc(ctx, cmd_desc); if (ret != 0) goto out_ioctl_cmd; ret = a4l_check_generic_cmdcnt(cmd_desc); if (ret != 0) goto out_ioctl_cmd; ret = a4l_check_specific_cmdcnt(ctx, cmd_desc); if (ret != 0) goto out_ioctl_cmd; __a4l_dbg(1, core_dbg,"1st cmd checks passed\n"); subd = dev->transfer.subds[cmd_desc->idx_subd]; /* Tests the command with the cmdtest function */ if (cmd_desc->flags & A4L_CMD_SIMUL) { simul_flag = 1; if (!subd->do_cmdtest) { __a4l_err("a4l_ioctl_cmd: driver's cmd_test NULL\n"); ret = -EINVAL; goto out_ioctl_cmd; } ret = subd->do_cmdtest(subd, cmd_desc); if (ret != 0) { __a4l_err("a4l_ioctl_cmd: driver's cmd_test failed\n"); goto out_ioctl_cmd; } __a4l_dbg(1, core_dbg, "driver's cmd checks passed\n"); goto out_ioctl_cmd; } /* Gets the transfer system ready */ ret = a4l_setup_buffer(ctx, cmd_desc); if (ret < 0) goto out_ioctl_cmd; /* Eventually launches the command */ ret = subd->do_cmd(subd, cmd_desc); if (ret != 0) { a4l_cancel_buffer(ctx); goto out_ioctl_cmd; } out_ioctl_cmd: if (simul_flag) { /* copy the kernel based descriptor */ tmp = cmd_desc->chan_descs; /* return the user based descriptor */ cmd_desc->chan_descs = chan_descs; rtdm_safe_copy_to_user(rtdm_private_to_fd(ctx), arg, cmd_desc, sizeof(struct a4l_cmd_desc)); /* make sure we release the memory associated to the kernel */ cmd_desc->chan_descs = tmp; } if (ret != 0 || simul_flag == 1) { a4l_free_cmddesc(cmd_desc); rtdm_free(cmd_desc); } return ret; }