From 12dcaeb77e67c1162a2604f6b589266baec2d1ef Mon Sep 17 00:00:00 2001 From: Guido Kiener Date: Wed, 18 Jul 2018 10:45:39 +0200 Subject: usb: usbtmc: Add ioctl for termination character add USBTMC_IOCTL_CONFIG_TERMCHAR to control TermChar handling for next read(). Controls field 'TermChar' and Bit 1 of field 'bmTransferAttributes' of REQUEST_DEV_DEP_MSG_IN BULK-OUT header. Allows enabling/disabling of terminating a read on reception of term_char individually for each read request. Reviewed-by: Steve Bayless Tested-by: Dave Penkler Signed-off-by: Dave Penkler Signed-off-by: Guido Kiener Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) (limited to 'drivers/usb/class/usbtmc.c') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index c77e0ac6260b..1b7b2e402adb 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -121,6 +121,8 @@ struct usbtmc_file_data { u8 srq_byte; atomic_t srq_asserted; u8 eom_val; + u8 term_char; + bool term_char_enabled; }; /* Forward declarations */ @@ -157,7 +159,10 @@ static int usbtmc_open(struct inode *inode, struct file *filp) mutex_lock(&data->io_mutex); file_data->data = data; + /* copy default values from device settings */ file_data->timeout = USBTMC_TIMEOUT; + file_data->term_char = data->TermChar; + file_data->term_char_enabled = data->TermCharEnabled; file_data->eom_val = 1; INIT_LIST_HEAD(&file_data->file_elem); @@ -634,9 +639,9 @@ static int send_request_dev_dep_msg_in(struct usbtmc_file_data *file_data, buffer[5] = transfer_size >> 8; buffer[6] = transfer_size >> 16; buffer[7] = transfer_size >> 24; - buffer[8] = data->TermCharEnabled * 2; + buffer[8] = file_data->term_char_enabled * 2; /* Use term character? */ - buffer[9] = data->TermChar; + buffer[9] = file_data->term_char; buffer[10] = 0; /* Reserved */ buffer[11] = 0; /* Reserved */ @@ -1298,6 +1303,28 @@ static int usbtmc_ioctl_eom_enable(struct usbtmc_file_data *file_data, return 0; } +/* + * Configure termination character for read() + */ +static int usbtmc_ioctl_config_termc(struct usbtmc_file_data *file_data, + void __user *arg) +{ + struct usbtmc_termchar termc; + + if (copy_from_user(&termc, arg, sizeof(termc))) + return -EFAULT; + + if ((termc.term_char_enabled > 1) || + (termc.term_char_enabled && + !(file_data->data->capabilities.device_capabilities & 1))) + return -EINVAL; + + file_data->term_char = termc.term_char; + file_data->term_char_enabled = termc.term_char_enabled; + + return 0; +} + static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct usbtmc_file_data *file_data; @@ -1353,6 +1380,11 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) (void __user *)arg); break; + case USBTMC_IOCTL_CONFIG_TERMCHAR: + retval = usbtmc_ioctl_config_termc(file_data, + (void __user *)arg); + break; + case USBTMC488_IOCTL_GET_CAPS: retval = copy_to_user((void __user *)arg, &data->usb488_caps, -- cgit