master/cdev.c
changeset 935 b954e9d91ea5
parent 922 fede1d8f5b71
child 938 5b936e8e39fa
equal deleted inserted replaced
934:96241b092fac 935:b954e9d91ea5
    50 
    50 
    51 int eccdev_open(struct inode *, struct file *);
    51 int eccdev_open(struct inode *, struct file *);
    52 int eccdev_release(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 *);
    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 *);
    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);
    55 long eccdev_ioctl(struct file *, unsigned int, unsigned long);
    56 
    56 
    57 /*****************************************************************************/
    57 /*****************************************************************************/
    58 
    58 
    59 static struct file_operations eccdev_fops = {
    59 static struct file_operations eccdev_fops = {
    60     .owner   = THIS_MODULE,
    60     .owner          = THIS_MODULE,
    61     .open    = eccdev_open,
    61     .open           = eccdev_open,
    62     .release = eccdev_release,
    62     .release        = eccdev_release,
    63     .ioctl   = eccdev_ioctl
    63     .unlocked_ioctl = eccdev_ioctl
    64 };
    64 };
    65 
    65 
    66 /** \endcond */
    66 /** \endcond */
    67 
    67 
    68 /*****************************************************************************/
    68 /*****************************************************************************/
   105  *****************************************************************************/
   105  *****************************************************************************/
   106 
   106 
   107 int eccdev_open(struct inode *inode, struct file *filp)
   107 int eccdev_open(struct inode *inode, struct file *filp)
   108 {
   108 {
   109     ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
   109     ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
       
   110     ec_master_t *master = cdev->master;
   110 
   111 
   111     filp->private_data = cdev;
   112     filp->private_data = cdev;
   112     EC_DBG("File opened.\n");
   113     if (master->debug_level)
       
   114         EC_DBG("File opened.\n");
   113     return 0;
   115     return 0;
   114 }
   116 }
   115 
   117 
   116 /*****************************************************************************/
   118 /*****************************************************************************/
   117 
   119 
   118 int eccdev_release(struct inode *inode, struct file *filp)
   120 int eccdev_release(struct inode *inode, struct file *filp)
   119 {
   121 {
   120     //ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
   122     ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data;
   121 
   123     ec_master_t *master = cdev->master;
   122     EC_DBG("File closed.\n");
   124 
       
   125     if (master->debug_level)
       
   126         EC_DBG("File closed.\n");
   123     return 0;
   127     return 0;
   124 }
   128 }
   125 
   129 
   126 /*****************************************************************************/
   130 /*****************************************************************************/
   127 
   131 
   128 int eccdev_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
   132 long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
   129         unsigned long arg)
   133 {
   130 {
   134     ec_cdev_t *cdev = (ec_cdev_t *) filp->private_data;
   131     ec_cdev_t *cdev = container_of(inode->i_cdev, ec_cdev_t, cdev);
       
   132     ec_master_t *master = cdev->master;
   135     ec_master_t *master = cdev->master;
       
   136     long retval = 0;
   133 
   137 
   134     if (master->debug_level)
   138     if (master->debug_level)
   135         EC_DBG("ioctl(inode = %x, filp = %x, cmd = %u, arg = %u)\n",
   139         EC_DBG("ioctl(filp = %x, cmd = %u, arg = %u)\n",
   136                 (u32) inode, (u32) filp, (u32) cmd, (u32) arg);
   140                 (u32) filp, (u32) cmd, (u32) arg);
   137 
   141 
       
   142     // FIXME lock
       
   143     
   138     switch (cmd) {
   144     switch (cmd) {
   139         case EC_IOCTL_SLAVE_COUNT:
   145         case EC_IOCTL_SLAVE_COUNT:
       
   146             retval = master->slave_count;
       
   147             break;
       
   148 
       
   149         case EC_IOCTL_SLAVE:
   140             {
   150             {
   141                 unsigned int slave_count = master->slave_count;
   151                 ec_ioctl_slave_t data;
   142                 EC_INFO("EC_IOCTL_SLAVE_COUNT\n");
   152                 const ec_slave_t *slave;
   143                 if (!arg)
   153 
   144                     return -EFAULT;
   154                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
   145                 if (copy_to_user((void __user *) arg, &slave_count,
   155                     retval = -EFAULT;
   146                             sizeof(unsigned int)))
   156                     break;
   147                     return -EFAULT;
   157                 }
   148                 return 0;
   158 
       
   159                 if (!(slave = ec_master_find_slave(
       
   160                                 master, 0, data.position))) {
       
   161                     EC_ERR("Slave %u does not exist!\n", data.position);
       
   162                     retval = -EINVAL;
       
   163                     break;
       
   164                 }
       
   165 
       
   166                 data.vendor_id = slave->sii.vendor_id;
       
   167                 data.product_code = slave->sii.product_code;
       
   168                 data.alias = slave->sii.alias;
       
   169                 data.state = slave->current_state;
       
   170 
       
   171                 data.sync_count = slave->sii.sync_count;
       
   172 
       
   173                 if (slave->sii.name) {
       
   174                     strncpy(data.name, slave->sii.name,
       
   175                             EC_IOCTL_SLAVE_NAME_SIZE);
       
   176                     data.name[EC_IOCTL_SLAVE_NAME_SIZE - 1] = 0;
       
   177                 } else {
       
   178                     data.name[0] = 0;
       
   179                 }
       
   180 
       
   181                 if (copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   182                     retval = -EFAULT;
       
   183                     break;
       
   184                 }
       
   185 
       
   186                 break;
   149             }
   187             }
   150 
   188 
   151         case EC_IOCTL_SLAVE_INFO:
   189         case EC_IOCTL_SYNC:
   152             {
   190             {
   153                 struct ec_ioctl_slave_info *infos, *info;
   191                 ec_ioctl_sync_t data;
   154                 unsigned int slave_count = master->slave_count;
       
   155                 const ec_slave_t *slave;
   192                 const ec_slave_t *slave;
   156                 unsigned int i = 0;
   193                 const ec_sync_t *sync;
   157 
   194 
   158                 if (master->debug_level)
   195                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
   159                     EC_DBG("EC_IOCTL_SLAVE_INFOS\n");
   196                     retval = -EFAULT;
   160 
   197                     break;
   161                 if (!slave_count)
   198                 }
   162                     return 0;
   199                 
   163 
   200                 if (!(slave = ec_master_find_slave(
   164                 if (!arg)
   201                                 master, 0, data.slave_position))) {
   165                     return -EFAULT;
   202                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
   166 
   203                     retval = -EINVAL;
   167                 if (!(infos = kmalloc(slave_count *
   204                     break;
   168                                 sizeof(struct ec_ioctl_slave_info),
   205                 }
   169                                 GFP_KERNEL)))
   206 
   170                     return -ENOMEM;
   207                 if (data.sync_index >= slave->sii.sync_count) {
   171 
   208                     EC_ERR("Sync manager %u does not exist in slave %u!\n",
   172                 list_for_each_entry(slave, &master->slaves, list) {
   209                             data.sync_index, data.slave_position);
   173                     info = &infos[i++];
   210                     retval = -EINVAL;
   174                     info->vendor_id = slave->sii.vendor_id;
   211                     break;
   175                     info->product_code = slave->sii.product_code;
   212                 }
   176                     info->alias = slave->sii.alias;
   213 
   177                     info->ring_position = slave->ring_position;
   214                 sync = &slave->sii.syncs[data.sync_index];
   178                     info->state = slave->current_state;
   215 
   179                     if (slave->sii.name) {
   216                 data.physical_start_address = sync->physical_start_address;
   180                         strncpy(info->description, slave->sii.name,
   217                 data.default_size = sync->length;
   181                                 EC_IOCTL_SLAVE_INFO_DESC_SIZE);
   218                 data.control_register = sync->control_register;
   182                         info->description[EC_IOCTL_SLAVE_INFO_DESC_SIZE - 1]
   219                 data.enable = sync->enable;
   183                             = 0;
   220                 data.assign_source = sync->assign_source;
   184                     } else {
   221                 data.pdo_count = ec_pdo_list_count(&sync->pdos);
   185                         info->description[0] = 0;
   222 
   186                     }
   223                 if (copy_to_user((void __user *) arg, &data, sizeof(data))) {
   187                 }
   224                     retval = -EFAULT;
   188 
   225                     break;
   189                 if (copy_to_user((void __user *) arg, infos, slave_count *
   226                 }
   190                             sizeof(struct ec_ioctl_slave_info))) {
   227                 break;
   191                     kfree(infos);
       
   192                     return -EFAULT;
       
   193                 }
       
   194 
       
   195                 kfree(infos);
       
   196                 return 0;
       
   197             }
   228             }
   198 
   229 
       
   230         case EC_IOCTL_PDO:
       
   231             {
       
   232                 ec_ioctl_pdo_t data;
       
   233                 const ec_slave_t *slave;
       
   234                 const ec_sync_t *sync;
       
   235                 const ec_pdo_t *pdo;
       
   236 
       
   237                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   238                     retval = -EFAULT;
       
   239                     break;
       
   240                 }
       
   241                 
       
   242                 if (!(slave = ec_master_find_slave(
       
   243                                 master, 0, data.slave_position))) {
       
   244                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   245                     retval = -EINVAL;
       
   246                     break;
       
   247                 }
       
   248 
       
   249                 if (data.sync_index >= slave->sii.sync_count) {
       
   250                     EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   251                             data.sync_index, data.slave_position);
       
   252                     retval = -EINVAL;
       
   253                     break;
       
   254                 }
       
   255 
       
   256                 sync = &slave->sii.syncs[data.sync_index];
       
   257                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   258                                 &sync->pdos, data.pdo_pos))) {
       
   259                     EC_ERR("Sync manager %u does not contain a Pdo with "
       
   260                             "position %u in slave %u!\n", data.sync_index,
       
   261                             data.pdo_pos, data.slave_position);
       
   262                     retval = -EINVAL;
       
   263                     break;
       
   264                 }
       
   265 
       
   266                 data.dir = pdo->dir;
       
   267                 data.index = pdo->index;
       
   268                 data.entry_count = ec_pdo_entry_count(pdo);
       
   269 
       
   270                 if (pdo->name) {
       
   271                     strncpy(data.name, pdo->name, EC_IOCTL_PDO_NAME_SIZE);
       
   272                     data.name[EC_IOCTL_PDO_NAME_SIZE - 1] = 0;
       
   273                 } else {
       
   274                     data.name[0] = 0;
       
   275                 }
       
   276 
       
   277                 if (copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   278                     retval = -EFAULT;
       
   279                     break;
       
   280                 }
       
   281                 break;
       
   282             }
       
   283 
       
   284         case EC_IOCTL_PDO_ENTRY:
       
   285             {
       
   286                 ec_ioctl_pdo_entry_t data;
       
   287                 const ec_slave_t *slave;
       
   288                 const ec_sync_t *sync;
       
   289                 const ec_pdo_t *pdo;
       
   290                 const ec_pdo_entry_t *entry;
       
   291 
       
   292                 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) {
       
   293                     retval = -EFAULT;
       
   294                     break;
       
   295                 }
       
   296                 
       
   297                 if (!(slave = ec_master_find_slave(
       
   298                                 master, 0, data.slave_position))) {
       
   299                     EC_ERR("Slave %u does not exist!\n", data.slave_position);
       
   300                     retval = -EINVAL;
       
   301                     break;
       
   302                 }
       
   303 
       
   304                 if (data.sync_index >= slave->sii.sync_count) {
       
   305                     EC_ERR("Sync manager %u does not exist in slave %u!\n",
       
   306                             data.sync_index, data.slave_position);
       
   307                     retval = -EINVAL;
       
   308                     break;
       
   309                 }
       
   310 
       
   311                 sync = &slave->sii.syncs[data.sync_index];
       
   312                 if (!(pdo = ec_pdo_list_find_pdo_by_pos_const(
       
   313                                 &sync->pdos, data.pdo_pos))) {
       
   314                     EC_ERR("Sync manager %u does not contain a Pdo with "
       
   315                             "position %u in slave %u!\n", data.sync_index,
       
   316                             data.pdo_pos, data.slave_position);
       
   317                     retval = -EINVAL;
       
   318                     break;
       
   319                 }
       
   320 
       
   321                 if (!(entry = ec_pdo_find_entry_by_pos_const(
       
   322                                 pdo, data.entry_pos))) {
       
   323                     EC_ERR("Pdo 0x%04X does not contain an entry with "
       
   324                             "position %u in slave %u!\n", data.pdo_pos,
       
   325                             data.entry_pos, data.slave_position);
       
   326                     retval = -EINVAL;
       
   327                     break;
       
   328                 }
       
   329 
       
   330                 data.index = entry->index;
       
   331                 data.subindex = entry->subindex;
       
   332                 data.bit_length = entry->bit_length;
       
   333                 if (entry->name) {
       
   334                     strncpy(data.name, entry->name,
       
   335                             EC_IOCTL_PDO_ENTRY_NAME_SIZE);
       
   336                     data.name[EC_IOCTL_PDO_ENTRY_NAME_SIZE - 1] = 0;
       
   337                 } else {
       
   338                     data.name[0] = 0;
       
   339                 }
       
   340 
       
   341                 if (copy_to_user((void __user *) arg, &data, sizeof(data))) {
       
   342                     retval = -EFAULT;
       
   343                     break;
       
   344                 }
       
   345                 break;
       
   346             }
       
   347 
   199         default:
   348         default:
   200             return -ENOIOCTLCMD;
   349             retval = -ENOIOCTLCMD;
   201     }
   350     }
   202 }
   351 
   203 
   352     return retval;
   204 /*****************************************************************************/
   353 }
       
   354 
       
   355 /*****************************************************************************/