diff options
author | Spencer E. Olson <olsonse@umich.edu> | 2018-10-03 14:56:02 -0600 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-09 15:32:38 +0200 |
commit | d7569ad766511fe708a8bd7476baa305d1510daf (patch) | |
tree | 685c4f10769c8bce4dc734946e5211c884fc9d98 /drivers/staging | |
parent | 5912827dfe78a0befae8a5e44f419eaf3deced72 (diff) |
staging: comedi: add new device-global config interface
Adds interface for configuring options that are global to all sub-devices.
For now, only options to configure device-globally identified signal routes
have been defined.
Signed-off-by: Spencer E. Olson <olsonse@umich.edu>
Reviewed-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/comedi/comedi.h | 18 | ||||
-rw-r--r-- | drivers/staging/comedi/comedi_fops.c | 69 | ||||
-rw-r--r-- | drivers/staging/comedi/comedidev.h | 14 | ||||
-rw-r--r-- | drivers/staging/comedi/drivers.c | 19 |
4 files changed, 120 insertions, 0 deletions
diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index e9ce395836ec..e90b17775284 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -107,6 +107,7 @@ #define INSN_WRITE (1 | INSN_MASK_WRITE) #define INSN_BITS (2 | INSN_MASK_READ | INSN_MASK_WRITE) #define INSN_CONFIG (3 | INSN_MASK_READ | INSN_MASK_WRITE) +#define INSN_DEVICE_CONFIG (INSN_CONFIG | INSN_MASK_SPECIAL) #define INSN_GTOD (4 | INSN_MASK_READ | INSN_MASK_SPECIAL) #define INSN_WAIT (5 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) #define INSN_INTTRIG (6 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) @@ -351,6 +352,23 @@ enum configuration_ids { }; /** + * enum device_configuration_ids - COMEDI configuration instruction codes global + * to an entire device. + * @INSN_DEVICE_CONFIG_TEST_ROUTE: Validate the possibility of a + * globally-named route + * @INSN_DEVICE_CONFIG_CONNECT_ROUTE: Connect a globally-named route + * @INSN_DEVICE_CONFIG_DISCONNECT_ROUTE:Disconnect a globally-named route + * @INSN_DEVICE_CONFIG_GET_ROUTES: Get a list of all globally-named routes + * that are valid for a particular device. + */ +enum device_config_route_ids { + INSN_DEVICE_CONFIG_TEST_ROUTE = 0, + INSN_DEVICE_CONFIG_CONNECT_ROUTE = 1, + INSN_DEVICE_CONFIG_DISCONNECT_ROUTE = 2, + INSN_DEVICE_CONFIG_GET_ROUTES = 3, +}; + +/** * enum comedi_digital_trig_op - operations for configuring a digital trigger * @COMEDI_DIGITAL_TRIG_DISABLE: Return digital trigger to its default, * inactive, unconfigured state. diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 548baa790507..c1c6b2b4ab91 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1234,6 +1234,57 @@ static int check_insn_config_length(struct comedi_insn *insn, return -EINVAL; } +static int check_insn_device_config_length(struct comedi_insn *insn, + unsigned int *data) +{ + if (insn->n < 1) + return -EINVAL; + + switch (data[0]) { + case INSN_DEVICE_CONFIG_TEST_ROUTE: + case INSN_DEVICE_CONFIG_CONNECT_ROUTE: + case INSN_DEVICE_CONFIG_DISCONNECT_ROUTE: + if (insn->n == 3) + return 0; + break; + case INSN_DEVICE_CONFIG_GET_ROUTES: + /* + * Big enough for config_id and the length of the userland + * memory buffer. Additional length should be in factors of 2 + * to communicate any returned route pairs (source,destination). + */ + if (insn->n >= 2) + return 0; + break; + } + return -EINVAL; +} + +/** + * get_valid_routes() - Calls low-level driver get_valid_routes function to + * either return a count of valid routes to user, or copy + * of list of all valid device routes to buffer in + * userspace. + * @dev: comedi device pointer + * @data: data from user insn call. The length of the data must be >= 2. + * data[0] must contain the INSN_DEVICE_CONFIG config_id. + * data[1](input) contains the number of _pairs_ for which memory is + * allotted from the user. If the user specifies '0', then only + * the number of pairs available is returned. + * data[1](output) returns either the number of pairs available (if none + * where requested) or the number of _pairs_ that are copied back + * to the user. + * data[2::2] returns each (source, destination) pair. + * + * Return: -EINVAL if low-level driver does not allocate and return routes as + * expected. Returns 0 otherwise. + */ +static int get_valid_routes(struct comedi_device *dev, unsigned int *data) +{ + data[1] = dev->get_valid_routes(dev, data[1], data + 2); + return 0; +} + static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data, void *file) { @@ -1297,6 +1348,24 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, if (ret >= 0) ret = 1; break; + case INSN_DEVICE_CONFIG: + ret = check_insn_device_config_length(insn, data); + if (ret) + break; + + if (data[0] == INSN_DEVICE_CONFIG_GET_ROUTES) { + /* + * data[1] should be the number of _pairs_ that + * the memory can hold. + */ + data[1] = (insn->n - 2) / 2; + ret = get_valid_routes(dev, data); + break; + } + + /* other global device config instructions. */ + ret = dev->insn_device_config(dev, insn, data); + break; default: dev_dbg(dev->class_dev, "invalid insn\n"); ret = -EINVAL; diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 5775a93917f4..a7d569cfca5d 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -516,6 +516,15 @@ struct comedi_driver { * called when @use_count changes from 0 to 1. * @close: Optional pointer to a function set by the low-level driver to be * called when @use_count changed from 1 to 0. + * @insn_device_config: Optional pointer to a handler for all sub-instructions + * except %INSN_DEVICE_CONFIG_GET_ROUTES of the %INSN_DEVICE_CONFIG + * instruction. If this is not initialized by the low-level driver, a + * default handler will be set during post-configuration. + * @get_valid_routes: Optional pointer to a handler for the + * %INSN_DEVICE_CONFIG_GET_ROUTES sub-instruction of the + * %INSN_DEVICE_CONFIG instruction set. If this is not initialized by the + * low-level driver, a default handler that copies zero routes back to the + * user will be used. * * This is the main control data structure for a COMEDI device (as far as the * COMEDI core is concerned). There are two groups of COMEDI devices - @@ -565,6 +574,11 @@ struct comedi_device { int (*open)(struct comedi_device *dev); void (*close)(struct comedi_device *dev); + int (*insn_device_config)(struct comedi_device *dev, + struct comedi_insn *insn, unsigned int *data); + unsigned int (*get_valid_routes)(struct comedi_device *dev, + unsigned int n_pairs, + unsigned int *pair_data); }; /* diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index 57dd63d548b7..eefa62f42c0f 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -211,6 +211,19 @@ static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s) return -EINVAL; } +static int insn_device_inval(struct comedi_device *dev, + struct comedi_insn *insn, unsigned int *data) +{ + return -EINVAL; +} + +static unsigned int get_zero_valid_routes(struct comedi_device *dev, + unsigned int n_pairs, + unsigned int *pair_data) +{ + return 0; +} + int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { @@ -652,6 +665,12 @@ static int __comedi_device_postconfig(struct comedi_device *dev) int ret; int i; + if (!dev->insn_device_config) + dev->insn_device_config = insn_device_inval; + + if (!dev->get_valid_routes) + dev->get_valid_routes = get_zero_valid_routes; + for (i = 0; i < dev->n_subdevices; i++) { s = &dev->subdevices[i]; |