diff -r 794cbccdcd00 -r 632a6b91f8e4 master/cdev.c --- a/master/cdev.c Wed Oct 01 14:37:34 2008 +0000 +++ b/master/cdev.c Wed Oct 01 14:42:28 2008 +0000 @@ -66,6 +66,15 @@ /*****************************************************************************/ +/** Private data structure for file handles. + */ +typedef struct { + ec_cdev_t *cdev; + unsigned int requested; +} ec_cdev_priv_t; + +/*****************************************************************************/ + /** Constructor. * * \return 0 in case of success, else < 0 @@ -1354,6 +1363,32 @@ return 0; } +/*****************************************************************************/ + +/** Request the master from userspace. + */ +int ec_cdev_ioctl_request( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_request_t data; + int ret = 0; + + data.handle = ecrt_request_master(master->index); + + if (IS_ERR(data.handle)) { + ret = PTR_ERR(data.handle); + } else { + priv->requested = 1; + if (copy_to_user((void __user *) arg, &data, sizeof(data))) + ret = -EFAULT; + } + + return ret; +} + /****************************************************************************** * File operations *****************************************************************************/ @@ -1364,8 +1399,18 @@ { ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev); ec_master_t *master = cdev->master; - - filp->private_data = cdev; + ec_cdev_priv_t *priv; + + priv = kmalloc(sizeof(ec_cdev_priv_t), GFP_KERNEL); + if (!priv) { + EC_ERR("Failed to allocate memory for private data structure.\n"); + return -ENOMEM; + } + + priv->cdev = cdev; + priv->requested = 0; + + filp->private_data = priv; if (master->debug_level) EC_DBG("File opened.\n"); return 0; @@ -1377,11 +1422,15 @@ */ int eccdev_release(struct inode *inode, struct file *filp) { - ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data; - ec_master_t *master = cdev->master; + ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data; + ec_master_t *master = priv->cdev->master; + + if (priv->requested) + ecrt_release_master(master); if (master->debug_level) EC_DBG("File closed.\n"); + kfree(priv); return 0; } @@ -1391,8 +1440,8 @@ */ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data; - ec_master_t *master = cdev->master; + ec_cdev_priv_t *priv = (ec_cdev_priv_t *) filp->private_data; + ec_master_t *master = priv->cdev->master; if (master->debug_level) EC_DBG("ioctl(filp = %x, cmd = %u (%u), arg = %x)\n", @@ -1453,6 +1502,10 @@ return ec_cdev_ioctl_config_pdo_entry(master, arg); case EC_IOCTL_CONFIG_SDO: return ec_cdev_ioctl_config_sdo(master, arg); + case EC_IOCTL_REQUEST: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_request(master, arg, priv); default: return -ENOTTY; }