master/cdev.c
changeset 922 fede1d8f5b71
child 935 b954e9d91ea5
equal deleted inserted replaced
921:c8c2caf0d667 922:fede1d8f5b71
       
     1 /******************************************************************************
       
     2  *
       
     3  *  $Id$
       
     4  *
       
     5  *  Copyright (C) 2006  Florian Pose, Ingenieurgemeinschaft IgH
       
     6  *
       
     7  *  This file is part of the IgH EtherCAT Master.
       
     8  *
       
     9  *  The IgH EtherCAT Master is free software; you can redistribute it
       
    10  *  and/or modify it under the terms of the GNU General Public License
       
    11  *  as published by the Free Software Foundation; either version 2 of the
       
    12  *  License, or (at your option) any later version.
       
    13  *
       
    14  *  The IgH EtherCAT Master is distributed in the hope that it will be
       
    15  *  useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  *  GNU General Public License for more details.
       
    18  *
       
    19  *  You should have received a copy of the GNU General Public License
       
    20  *  along with the IgH EtherCAT Master; if not, write to the Free Software
       
    21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    22  *
       
    23  *  The right to use EtherCAT Technology is granted and comes free of
       
    24  *  charge under condition of compatibility of product made by
       
    25  *  Licensee. People intending to distribute/sell products based on the
       
    26  *  code, have to sign an agreement to guarantee that products using
       
    27  *  software based on IgH EtherCAT master stay compatible with the actual
       
    28  *  EtherCAT specification (which are released themselves as an open
       
    29  *  standard) as the (only) precondition to have the right to use EtherCAT
       
    30  *  Technology, IP and trade marks.
       
    31  *
       
    32  *****************************************************************************/
       
    33 
       
    34 /**
       
    35    \file
       
    36    EtherCAT master character device.
       
    37 */
       
    38 
       
    39 /*****************************************************************************/
       
    40 
       
    41 #include <linux/module.h>
       
    42 
       
    43 #include "cdev.h"
       
    44 #include "master.h"
       
    45 #include "ioctl.h"
       
    46 
       
    47 /*****************************************************************************/
       
    48 
       
    49 /** \cond */
       
    50 
       
    51 int eccdev_open(struct inode *, struct file *);
       
    52 int eccdev_release(struct inode *, struct file *);
       
    53 ssize_t eccdev_read(struct file *, char __user *, size_t, loff_t *);
       
    54 ssize_t eccdev_write(struct file *, const char __user *, size_t, loff_t *);
       
    55 int eccdev_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
       
    56 
       
    57 /*****************************************************************************/
       
    58 
       
    59 static struct file_operations eccdev_fops = {
       
    60     .owner   = THIS_MODULE,
       
    61     .open    = eccdev_open,
       
    62     .release = eccdev_release,
       
    63     .ioctl   = eccdev_ioctl
       
    64 };
       
    65 
       
    66 /** \endcond */
       
    67 
       
    68 /*****************************************************************************/
       
    69 
       
    70 /** Constructor.
       
    71  * 
       
    72  * \return 0 in case of success, else < 0
       
    73  */
       
    74 int ec_cdev_init(
       
    75 		ec_cdev_t *cdev, /**< EtherCAT master character device. */
       
    76 		ec_master_t *master, /**< Parent master. */
       
    77 		dev_t dev_num /**< Device number. */
       
    78 		)
       
    79 {
       
    80     cdev->master = master;
       
    81 
       
    82     cdev_init(&cdev->cdev, &eccdev_fops);
       
    83     cdev->cdev.owner = THIS_MODULE;
       
    84 
       
    85     if (cdev_add(&cdev->cdev,
       
    86 		 MKDEV(MAJOR(dev_num), master->index), 1)) {
       
    87 		EC_ERR("Failed to add character device!\n");
       
    88 		return -1;
       
    89     }
       
    90 
       
    91     return 0;
       
    92 }
       
    93 
       
    94 /*****************************************************************************/
       
    95 
       
    96 /** Destructor.
       
    97  */
       
    98 void ec_cdev_clear(ec_cdev_t *cdev /**< EtherCAT XML device */)
       
    99 {
       
   100     cdev_del(&cdev->cdev);
       
   101 }
       
   102 
       
   103 /******************************************************************************
       
   104  * File operations
       
   105  *****************************************************************************/
       
   106 
       
   107 int eccdev_open(struct inode *inode, struct file *filp)
       
   108 {
       
   109     ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
       
   110 
       
   111     filp->private_data = cdev;
       
   112     EC_DBG("File opened.\n");
       
   113     return 0;
       
   114 }
       
   115 
       
   116 /*****************************************************************************/
       
   117 
       
   118 int eccdev_release(struct inode *inode, struct file *filp)
       
   119 {
       
   120     //ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
       
   121 
       
   122     EC_DBG("File closed.\n");
       
   123     return 0;
       
   124 }
       
   125 
       
   126 /*****************************************************************************/
       
   127 
       
   128 int eccdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
       
   129         unsigned long arg)
       
   130 {
       
   131     ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
       
   132     ec_master_t *master = cdev->master;
       
   133 
       
   134     if (master->debug_level)
       
   135         EC_DBG("ioctl(inode = %x, filp = %x, cmd = %u, arg = %u)\n",
       
   136                 (u32) inode, (u32) filp, (u32) cmd, (u32) arg);
       
   137 
       
   138     switch (cmd) {
       
   139         case EC_IOCTL_SLAVE_COUNT:
       
   140             {
       
   141                 unsigned int slave_count = master->slave_count;
       
   142                 EC_INFO("EC_IOCTL_SLAVE_COUNT\n");
       
   143                 if (!arg)
       
   144                     return -EFAULT;
       
   145                 if (copy_to_user((void __user *) arg, &slave_count,
       
   146                             sizeof(unsigned int)))
       
   147                     return -EFAULT;
       
   148                 return 0;
       
   149             }
       
   150 
       
   151         case EC_IOCTL_SLAVE_INFO:
       
   152             {
       
   153                 struct ec_ioctl_slave_info *infos, *info;
       
   154                 unsigned int slave_count = master->slave_count;
       
   155                 const ec_slave_t *slave;
       
   156                 unsigned int i = 0;
       
   157 
       
   158                 if (master->debug_level)
       
   159                     EC_DBG("EC_IOCTL_SLAVE_INFOS\n");
       
   160 
       
   161                 if (!slave_count)
       
   162                     return 0;
       
   163 
       
   164                 if (!arg)
       
   165                     return -EFAULT;
       
   166 
       
   167                 if (!(infos = kmalloc(slave_count *
       
   168                                 sizeof(struct ec_ioctl_slave_info),
       
   169                                 GFP_KERNEL)))
       
   170                     return -ENOMEM;
       
   171 
       
   172                 list_for_each_entry(slave, &master->slaves, list) {
       
   173                     info = &infos[i++];
       
   174                     info->vendor_id = slave->sii.vendor_id;
       
   175                     info->product_code = slave->sii.product_code;
       
   176                     info->alias = slave->sii.alias;
       
   177                     info->ring_position = slave->ring_position;
       
   178                     info->state = slave->current_state;
       
   179                     if (slave->sii.name) {
       
   180                         strncpy(info->description, slave->sii.name,
       
   181                                 EC_IOCTL_SLAVE_INFO_DESC_SIZE);
       
   182                         info->description[EC_IOCTL_SLAVE_INFO_DESC_SIZE - 1]
       
   183                             = 0;
       
   184                     } else {
       
   185                         info->description[0] = 0;
       
   186                     }
       
   187                 }
       
   188 
       
   189                 if (copy_to_user((void __user *) arg, infos, slave_count *
       
   190                             sizeof(struct ec_ioctl_slave_info))) {
       
   191                     kfree(infos);
       
   192                     return -EFAULT;
       
   193                 }
       
   194 
       
   195                 kfree(infos);
       
   196                 return 0;
       
   197             }
       
   198 
       
   199         default:
       
   200             return -ENOIOCTLCMD;
       
   201     }
       
   202 }
       
   203 
       
   204 /*****************************************************************************/