# HG changeset patch # User Florian Pose # Date 1233581820 0 # Node ID 275d2fdeab48baa2bef271f1305adb26741b0a97 # Parent cf8f08631c8e3176e92b04f26032e2d73aed0525 Implemented SDO requests in userspace library. diff -r cf8f08631c8e -r 275d2fdeab48 TODO --- a/TODO Mon Feb 02 13:34:01 2009 +0000 +++ b/TODO Mon Feb 02 13:37:00 2009 +0000 @@ -12,11 +12,10 @@ * Remove ecrt_domain_state(). * Segmented SDO downloads. -* Implement SDO handlers in userspace library. * Clear slave list on link down. * Check force_config flag before error. * Remove allow_scanning flag. -* File access over EtherCAT (FoE). +* Test File access over EtherCAT (FoE) reading. * Improve application-triggered SDO transfers by moving the statemachine into the SDO handlers. * External memory for SDO transfers. diff -r cf8f08631c8e -r 275d2fdeab48 examples/user/main.c --- a/examples/user/main.c Mon Feb 02 13:34:01 2009 +0000 +++ b/examples/user/main.c Mon Feb 02 13:37:00 2009 +0000 @@ -45,6 +45,7 @@ // Optional features #define CONFIGURE_PDOS 1 +#define SDO_ACCESS 0 /****************************************************************************/ @@ -68,14 +69,15 @@ static uint8_t *domain1_pd = NULL; #define BusCouplerPos 0, 0 -#define AnaOutSlavePos 0, 1 -#define AnaInSlavePos 0, 2 -#define DigOutSlavePos 0, 3 +#define DigOutSlavePos 0, 2 +#define AnaInSlavePos 0, 3 +#define AnaOutSlavePos 0, 4 #define Beckhoff_EK1100 0x00000002, 0x044c2c52 #define Beckhoff_EL2004 0x00000002, 0x07d43052 #define Beckhoff_EL2032 0x00000002, 0x07f03052 #define Beckhoff_EL3152 0x00000002, 0x0c503052 +#define Beckhoff_EL3102 0x00000002, 0x0c1e3052 #define Beckhoff_EL4102 0x00000002, 0x10063052 // offsets for PDO entries @@ -85,8 +87,8 @@ static unsigned int off_dig_out; const static ec_pdo_entry_reg_t domain1_regs[] = { - {AnaInSlavePos, Beckhoff_EL3152, 0x3101, 1, &off_ana_in_status}, - {AnaInSlavePos, Beckhoff_EL3152, 0x3101, 2, &off_ana_in_value}, + {AnaInSlavePos, Beckhoff_EL3102, 0x3101, 1, &off_ana_in_status}, + {AnaInSlavePos, Beckhoff_EL3102, 0x3101, 2, &off_ana_in_value}, {AnaOutSlavePos, Beckhoff_EL4102, 0x3001, 1, &off_ana_out}, {DigOutSlavePos, Beckhoff_EL2032, 0x3001, 1, &off_dig_out}, {} @@ -101,7 +103,7 @@ // Analog in -------------------------- -static ec_pdo_entry_info_t el3152_pdo_entries[] = { +static ec_pdo_entry_info_t el3102_pdo_entries[] = { {0x3101, 1, 8}, // channel 1 status {0x3101, 2, 16}, // channel 1 value {0x3102, 1, 8}, // channel 2 status @@ -110,14 +112,14 @@ {0x6401, 2, 16} // channel 2 value (alt.) }; -static ec_pdo_info_t el3152_pdos[] = { - {0x1A00, 2, el3152_pdo_entries}, - {0x1A01, 2, el3152_pdo_entries + 2} -}; - -static ec_sync_info_t el3152_syncs[] = { +static ec_pdo_info_t el3102_pdos[] = { + {0x1A00, 2, el3102_pdo_entries}, + {0x1A01, 2, el3102_pdo_entries + 2} +}; + +static ec_sync_info_t el3102_syncs[] = { {2, EC_DIR_OUTPUT}, - {3, EC_DIR_INPUT, 2, el3152_pdos}, + {3, EC_DIR_INPUT, 2, el3102_pdos}, {0xff} }; @@ -164,6 +166,12 @@ /*****************************************************************************/ +#if SDO_ACCESS +static ec_sdo_request_t *sdo; +#endif + +/*****************************************************************************/ + void check_domain1_state(void) { ec_domain_state_t ds; @@ -215,6 +223,31 @@ sc_ana_in_state = s; } +/*****************************************************************************/ + +#if SDO_ACCESS +void read_sdo(void) +{ + switch (ecrt_sdo_request_state(sdo)) { + case EC_REQUEST_UNUSED: // request was not used yet + ecrt_sdo_request_read(sdo); // trigger first read + break; + case EC_REQUEST_BUSY: + fprintf(stderr, "Still busy...\n"); + break; + case EC_REQUEST_SUCCESS: + fprintf(stderr, "SDO value: 0x%04X\n", + EC_READ_U16(ecrt_sdo_request_data(sdo))); + ecrt_sdo_request_read(sdo); // trigger next read + break; + case EC_REQUEST_ERROR: + fprintf(stderr, "Failed to read SDO!\n"); + ecrt_sdo_request_read(sdo); // retry reading + break; + } +} +#endif + /****************************************************************************/ void cyclic_task() @@ -241,6 +274,12 @@ // check for islave configuration state(s) (optional) check_slave_config_states(); + +#if SDO_ACCESS + // read process data SDO + read_sdo(); +#endif + } #if 0 @@ -287,14 +326,23 @@ return -1; if (!(sc_ana_in = ecrt_master_slave_config( - master, AnaInSlavePos, Beckhoff_EL3152))) { + master, AnaInSlavePos, Beckhoff_EL3102))) { fprintf(stderr, "Failed to get slave configuration.\n"); return -1; } +#if SDO_ACCESS + fprintf(stderr, "Creating SDO requests...\n"); + if (!(sdo = ecrt_slave_config_create_sdo_request(sc_ana_in, 0x3102, 2, 2))) { + fprintf(stderr, "Failed to create SDO request.\n"); + return -1; + } + ecrt_sdo_request_timeout(sdo, 500); // ms +#endif + #if CONFIGURE_PDOS printf("Configuring PDOs...\n"); - if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3152_syncs)) { + if (ecrt_slave_config_pdos(sc_ana_in, EC_END, el3102_syncs)) { fprintf(stderr, "Failed to configure PDOs.\n"); return -1; } diff -r cf8f08631c8e -r 275d2fdeab48 include/ecrt.h --- a/include/ecrt.h Mon Feb 02 13:34:01 2009 +0000 +++ b/include/ecrt.h Mon Feb 02 13:37:00 2009 +0000 @@ -45,6 +45,8 @@ * - Renamed ec_sdo_request_state_t to ec_request_state_t, because it is also * used by VoE handlers. * - Added ecrt_master_slave() to get information about a certain slave. + * - Removed 'const' from argument of ecrt_sdo_request_state(), because the + * userspace library has to modify object internals. * * Changes in Version 1.4: * @@ -969,9 +971,15 @@ * * \return Request state. */ +#ifdef __KERNEL__ ec_request_state_t ecrt_sdo_request_state( - const ec_sdo_request_t *req /**< SDO request. */ + const ec_sdo_request_t *req /**< SDO request. */ ); +#else +ec_request_state_t ecrt_sdo_request_state( + ec_sdo_request_t *req /**< SDO request. */ + ); +#endif /** Schedule an SDO write operation. * diff -r cf8f08631c8e -r 275d2fdeab48 lib/Makefile.am --- a/lib/Makefile.am Mon Feb 02 13:34:01 2009 +0000 +++ b/lib/Makefile.am Mon Feb 02 13:37:00 2009 +0000 @@ -37,12 +37,14 @@ common.c \ domain.c \ master.c \ + sdo_request.c \ slave_config.c \ voe_handler.c noinst_HEADERS = \ domain.h \ master.h \ + sdo_request.h \ slave_config.h \ voe_handler.h diff -r cf8f08631c8e -r 275d2fdeab48 lib/sdo_request.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/sdo_request.c Mon Feb 02 13:37:00 2009 +0000 @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Using the EtherCAT technology and brand is permitted in compliance with + * the industrial property and similar rights of Beckhoff Automation GmbH. + * + *****************************************************************************/ + +/** \file + * Canopen over EtherCAT SDO request functions. + */ + +/*****************************************************************************/ + +#include +#include +#include + +#include "sdo_request.h" +#include "master/ioctl.h" +#include "slave_config.h" +#include "master.h" + +/***************************************************************************** + * Realtime interface. + ****************************************************************************/ + +void ecrt_sdo_request_timeout(ec_sdo_request_t *req, uint32_t timeout) +{ + ec_ioctl_sdo_request_t data; + + data.config_index = req->config->index; + data.request_index = req->index; + data.timeout = timeout; + + if (ioctl(req->config->master->fd, EC_IOCTL_SDO_REQUEST_TIMEOUT, + &data) == -1) + fprintf(stderr, "Failed to set SDO request timeout: %s\n", + strerror(errno)); +} + +/*****************************************************************************/ + +uint8_t *ecrt_sdo_request_data(ec_sdo_request_t *req) +{ + return req->data; +} + +/*****************************************************************************/ + +size_t ecrt_sdo_request_data_size(const ec_sdo_request_t *req) +{ + return req->data_size; +} + +/*****************************************************************************/ + +ec_request_state_t ecrt_sdo_request_state(ec_sdo_request_t *req) +{ + ec_ioctl_sdo_request_t data; + + data.config_index = req->config->index; + data.request_index = req->index; + + if (ioctl(req->config->master->fd, EC_IOCTL_SDO_REQUEST_STATE, + &data) == -1) + fprintf(stderr, "Failed to get SDO request state: %s\n", + strerror(errno)); + + if (data.size) { // new data waiting to be copied + if (req->mem_size < data.size) { + if (req->data) + free(req->data); + req->data = malloc(data.size); + if (!req->data) { + req->mem_size = 0; + fprintf(stderr, "Failed to allocate %u bytes of SDO data" + " memory!\n", data.size); + return EC_REQUEST_ERROR; + } + req->mem_size = data.size; + } + + data.data = req->data; + + if (ioctl(req->config->master->fd, EC_IOCTL_SDO_REQUEST_DATA, + &data) == -1) { + fprintf(stderr, "Failed to get SDO data: %s\n", strerror(errno)); + return EC_REQUEST_ERROR; + } + req->data_size = data.size; + } + + return data.state; +} + +/*****************************************************************************/ + +void ecrt_sdo_request_read(ec_sdo_request_t *req) +{ + ec_ioctl_sdo_request_t data; + + data.config_index = req->config->index; + data.request_index = req->index; + + if (ioctl(req->config->master->fd, EC_IOCTL_SDO_REQUEST_READ, + &data) == -1) + fprintf(stderr, "Failed to command an SDO read operation : %s\n", + strerror(errno)); +} + +/*****************************************************************************/ + +void ecrt_sdo_request_write(ec_sdo_request_t *req) +{ + ec_ioctl_sdo_request_t data; + + data.config_index = req->config->index; + data.request_index = req->index; + data.data = req->data; + data.size = req->data_size; + + if (ioctl(req->config->master->fd, EC_IOCTL_SDO_REQUEST_WRITE, + &data) == -1) + fprintf(stderr, "Failed to command an SDO write operation : %s\n", + strerror(errno)); +} + +/*****************************************************************************/ diff -r cf8f08631c8e -r 275d2fdeab48 lib/sdo_request.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/sdo_request.h Mon Feb 02 13:37:00 2009 +0000 @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT master userspace library. + * + * The IgH EtherCAT master userspace library is free software; you can + * redistribute it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * The IgH EtherCAT master userspace library is distributed in the hope that + * it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the IgH EtherCAT master userspace library. If not, see + * . + * + * Using the EtherCAT technology and brand is permitted in compliance with + * the industrial property and similar rights of Beckhoff Automation GmbH. + * + *****************************************************************************/ + +#include "include/ecrt.h" + +/*****************************************************************************/ + +struct ec_sdo_request { + ec_slave_config_t *config; /**< Parent slave configuration. */ + unsigned int index; /**< Request index (identifier). */ + uint16_t sdo_index; /**< SDO index. */ + uint8_t sdo_subindex; /**< SDO subindex. */ + uint8_t *data; /**< Pointer to SDO data. */ + size_t mem_size; /**< Size of SDO data memory. */ + size_t data_size; /**< Size of SDO data. */ +}; + +/*****************************************************************************/ diff -r cf8f08631c8e -r 275d2fdeab48 lib/slave_config.c --- a/lib/slave_config.c Mon Feb 02 13:34:01 2009 +0000 +++ b/lib/slave_config.c Mon Feb 02 13:37:00 2009 +0000 @@ -33,6 +33,7 @@ #include "slave_config.h" #include "domain.h" +#include "sdo_request.h" #include "voe_handler.h" #include "master.h" #include "master/ioctl.h" @@ -297,7 +298,48 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, size_t size) { - return 0; // TODO + ec_ioctl_sdo_request_t data; + ec_sdo_request_t *req; + + req = malloc(sizeof(ec_sdo_request_t)); + if (!req) { + fprintf(stderr, "Failed to allocate memory.\n"); + return 0; + } + + if (size) { + req->data = malloc(size); + if (!req->data) { + fprintf(stderr, "Failed to allocate %u bytes of SDO data" + " memory.\n", size); + free(req); + return 0; + } + } else { + req->data = NULL; + } + + data.config_index = sc->index; + data.sdo_index = index; + data.sdo_subindex = subindex; + data.size = size; + + if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO_REQUEST, &data) == -1) { + fprintf(stderr, "Failed to create SDO request: %s\n", + strerror(errno)); + if (req->data) + free(req->data); + free(req); + return NULL; + } + + req->config = sc; + req->index = data.request_index; + req->sdo_index = data.sdo_index; + req->sdo_subindex = data.sdo_subindex; + req->data_size = size; + req->mem_size = size; + return req; } /*****************************************************************************/ diff -r cf8f08631c8e -r 275d2fdeab48 master/cdev.c --- a/master/cdev.c Mon Feb 02 13:34:01 2009 +0000 +++ b/master/cdev.c Mon Feb 02 13:37:00 2009 +0000 @@ -1874,6 +1874,55 @@ /*****************************************************************************/ +/** Create an SDO request. + */ +int ec_cdev_ioctl_sc_create_sdo_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_sdo_request_t data; + ec_slave_config_t *sc; + ec_sdo_request_t *req; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { + return -EFAULT; + } + + data.request_index = 0; + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + sc = ec_master_get_config(master, data.config_index); + if (!sc) { + up(&master->master_sem); + return -ENOENT; + } + + list_for_each_entry(req, &sc->sdo_requests, list) { + data.request_index++; + } + + up(&master->master_sem); + + req = ecrt_slave_config_create_sdo_request_err(sc, data.sdo_index, + data.sdo_subindex, data.size); + if (IS_ERR(req)) + return PTR_ERR(req); + + if (copy_to_user((void __user *) arg, &data, sizeof(data))) + return -EFAULT; + + return 0; +} + +/*****************************************************************************/ + /** Create a VoE handler. */ int ec_cdev_ioctl_sc_create_voe_handler( @@ -2088,6 +2137,209 @@ /*****************************************************************************/ +/** Sets an SDO request's timeout. + */ +int ec_cdev_ioctl_sdo_request_timeout( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sdo_request_t data; + ec_slave_config_t *sc; + ec_sdo_request_t *req; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + if (!(sc = ec_master_get_config(master, data.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { + up(&master->master_sem); + return -ENOENT; + } + + up(&master->master_sem); + + ecrt_sdo_request_timeout(req, data.timeout); + return 0; +} + +/*****************************************************************************/ + +/** Gets an SDO request's state. + */ +int ec_cdev_ioctl_sdo_request_state( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sdo_request_t data; + ec_slave_config_t *sc; + ec_sdo_request_t *req; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + if (!(sc = ec_master_get_config(master, data.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { + up(&master->master_sem); + return -ENOENT; + } + + data.state = ecrt_sdo_request_state(req); + if (data.state == EC_REQUEST_SUCCESS && req->dir == EC_DIR_INPUT) + data.size = ecrt_sdo_request_data_size(req); + else + data.size = 0; + + up(&master->master_sem); + + if (copy_to_user((void __user *) arg, &data, sizeof(data))) + return -EFAULT; + + return 0; +} + +/*****************************************************************************/ + +/** Starts an SDO read operation. + */ +int ec_cdev_ioctl_sdo_request_read( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sdo_request_t data; + ec_slave_config_t *sc; + ec_sdo_request_t *req; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + if (!(sc = ec_master_get_config(master, data.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { + up(&master->master_sem); + return -ENOENT; + } + + up(&master->master_sem); + + ecrt_sdo_request_read(req); + return 0; +} + +/*****************************************************************************/ + +/** Starts an SDO write operation. + */ +int ec_cdev_ioctl_sdo_request_write( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sdo_request_t data; + ec_slave_config_t *sc; + ec_sdo_request_t *req; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + if (!(sc = ec_master_get_config(master, data.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { + up(&master->master_sem); + return -ENOENT; + } + + up(&master->master_sem); + + ecrt_sdo_request_write(req); + return 0; +} + +/*****************************************************************************/ + +/** Read SDO data. + */ +int ec_cdev_ioctl_sdo_request_data( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sdo_request_t data; + ec_slave_config_t *sc; + ec_sdo_request_t *req; + + if (unlikely(!priv->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + if (!(sc = ec_master_get_config(master, data.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + if (!(req = ec_slave_config_find_sdo_request(sc, data.request_index))) { + up(&master->master_sem); + return -ENOENT; + } + + up(&master->master_sem); + + ecrt_sdo_request_timeout(req, data.timeout); + return 0; +} + +/*****************************************************************************/ + /** Sets the VoE send header. */ int ec_cdev_ioctl_voe_send_header( @@ -2646,7 +2898,7 @@ ec_master_t *master = priv->cdev->master; if (master->debug_level) - EC_DBG("ioctl(filp = 0x%x, cmd = 0x%x (0x%x), arg = 0x%x)\n", + EC_DBG("ioctl(filp = 0x%x, cmd = 0x%08x (0x%02x), arg = 0x%x)\n", (u32) filp, (u32) cmd, (u32) _IOC_NR(cmd), (u32) arg); switch (cmd) { @@ -2764,6 +3016,10 @@ if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; return ec_cdev_ioctl_sc_sdo(master, arg, priv); + case EC_IOCTL_SC_SDO_REQUEST: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_sc_create_sdo_request(master, arg, priv); case EC_IOCTL_SC_VOE: if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; @@ -2782,6 +3038,22 @@ return ec_cdev_ioctl_domain_queue(master, arg, priv); case EC_IOCTL_DOMAIN_STATE: return ec_cdev_ioctl_domain_state(master, arg, priv); + case EC_IOCTL_SDO_REQUEST_TIMEOUT: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_sdo_request_timeout(master, arg, priv); + case EC_IOCTL_SDO_REQUEST_STATE: + return ec_cdev_ioctl_sdo_request_state(master, arg, priv); + case EC_IOCTL_SDO_REQUEST_READ: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_sdo_request_read(master, arg, priv); + case EC_IOCTL_SDO_REQUEST_WRITE: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_sdo_request_write(master, arg, priv); + case EC_IOCTL_SDO_REQUEST_DATA: + return ec_cdev_ioctl_sdo_request_data(master, arg, priv); case EC_IOCTL_VOE_SEND_HEADER: if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; diff -r cf8f08631c8e -r 275d2fdeab48 master/ioctl.h --- a/master/ioctl.h Mon Feb 02 13:34:01 2009 +0000 +++ b/master/ioctl.h Mon Feb 02 13:37:00 2009 +0000 @@ -90,19 +90,25 @@ #define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x23, ec_ioctl_config_pdo_t) #define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x24, ec_ioctl_reg_pdo_entry_t) #define EC_IOCTL_SC_SDO EC_IOW(0x25, ec_ioctl_sc_sdo_t) -#define EC_IOCTL_SC_VOE EC_IOWR(0x26, ec_ioctl_voe_t) -#define EC_IOCTL_SC_STATE EC_IOWR(0x27, ec_ioctl_sc_state_t) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x28) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x29) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x2a) -#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x2b, ec_ioctl_domain_state_t) -#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x2c, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x2d, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ EC_IOW(0x2e, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x2f, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_WRITE EC_IOWR(0x30, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_EXEC EC_IOWR(0x31, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_DATA EC_IOWR(0x32, ec_ioctl_voe_t) +#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x26, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SC_VOE EC_IOWR(0x27, ec_ioctl_voe_t) +#define EC_IOCTL_SC_STATE EC_IOWR(0x28, ec_ioctl_sc_state_t) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x29) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x2a) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x2b) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x2c, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x2d, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x2e, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x2f, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x30, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x31, ec_ioctl_sdo_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x32, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x33, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x34, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x35, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x36, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x37, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x38, ec_ioctl_voe_t) /*****************************************************************************/ @@ -468,6 +474,22 @@ uint32_t config_index; // inputs/outputs + uint32_t request_index; + uint16_t sdo_index; + uint8_t sdo_subindex; + size_t size; + uint8_t *data; + uint32_t timeout; + ec_request_state_t state; +} ec_ioctl_sdo_request_t; + +/*****************************************************************************/ + +typedef struct { + // inputs + uint32_t config_index; + + // inputs/outputs uint32_t voe_index; uint32_t *vendor_id; uint16_t *vendor_type;