Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: n_gsm: add ioctl for DLC config via ldisc handle

The application which initializes the n_gsm ldisc may like to set
individual default parameters for each DLCI or take over of the application
specific DLCI configuration completely. This is currently not possible.
It is either possible to set common default parameters for all DLCIs or let
the user application set its DLCI specific configuration parameters.

Add support of GSMIOC_GETCONF_DLCI and GSMIOC_SETCONF_DLCI for the n_gsm
ldisc handle to support DLCI specific parameter configuration upfront.

Add a code example for this use case to the n_gsm documentation.

Signed-off-by: Daniel Starke <daniel.starke@siemens.com>
Link: https://lore.kernel.org/r/20230315105354.6234-3-daniel.starke@siemens.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Daniel Starke and committed by
Greg Kroah-Hartman
afe3154b 8629745c

+45
+16
Documentation/driver-api/tty/n_gsm.rst
··· 47 47 int ldisc = N_GSM0710; 48 48 struct gsm_config c; 49 49 struct gsm_config_ext ce; 50 + struct gsm_dlci_config dc; 50 51 struct termios configuration; 51 52 uint32_t first; 52 53 ··· 84 83 c.mtu = 127; 85 84 /* set the new configuration */ 86 85 ioctl(fd, GSMIOC_SETCONF, &c); 86 + /* get DLC 1 configuration */ 87 + dc.channel = 1; 88 + ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); 89 + /* the first user channel gets a higher priority */ 90 + dc.priority = 1; 91 + /* set the new DLC 1 specific configuration */ 92 + ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); 87 93 /* get first gsmtty device node */ 88 94 ioctl(fd, GSMIOC_GETFIRST, &first); 89 95 printf("first muxed line: /dev/gsmtty%i\n", first); ··· 144 136 int ldisc = N_GSM0710; 145 137 struct gsm_config c; 146 138 struct gsm_config_ext ce; 139 + struct gsm_dlci_config dc; 147 140 struct termios configuration; 148 141 uint32_t first; 149 142 ··· 174 165 c.mtu = 127; 175 166 /* set the new configuration */ 176 167 ioctl(fd, GSMIOC_SETCONF, &c); 168 + /* get DLC 1 configuration */ 169 + dc.channel = 1; 170 + ioctl(fd, GSMIOC_GETCONF_DLCI, &dc); 171 + /* the first user channel gets a higher priority */ 172 + dc.priority = 1; 173 + /* set the new DLC 1 specific configuration */ 174 + ioctl(fd, GSMIOC_SETCONF_DLCI, &dc); 177 175 /* get first gsmtty device node */ 178 176 ioctl(fd, GSMIOC_GETFIRST, &first); 179 177 printf("first muxed line: /dev/gsmtty%i\n", first);
+29
drivers/tty/n_gsm.c
··· 3716 3716 { 3717 3717 struct gsm_config c; 3718 3718 struct gsm_config_ext ce; 3719 + struct gsm_dlci_config dc; 3719 3720 struct gsm_mux *gsm = tty->disc_data; 3721 + struct gsm_dlci *dlci; 3720 3722 unsigned int base; 3721 3723 3722 3724 switch (cmd) { ··· 3743 3741 if (copy_from_user(&ce, (void __user *)arg, sizeof(ce))) 3744 3742 return -EFAULT; 3745 3743 return gsm_config_ext(gsm, &ce); 3744 + case GSMIOC_GETCONF_DLCI: 3745 + if (copy_from_user(&dc, (void __user *)arg, sizeof(dc))) 3746 + return -EFAULT; 3747 + if (dc.channel == 0 || dc.channel >= NUM_DLCI) 3748 + return -EINVAL; 3749 + dlci = gsm->dlci[dc.channel]; 3750 + if (!dlci) { 3751 + dlci = gsm_dlci_alloc(gsm, dc.channel); 3752 + if (!dlci) 3753 + return -ENOMEM; 3754 + } 3755 + gsm_dlci_copy_config_values(dlci, &dc); 3756 + if (copy_to_user((void __user *)arg, &dc, sizeof(dc))) 3757 + return -EFAULT; 3758 + return 0; 3759 + case GSMIOC_SETCONF_DLCI: 3760 + if (copy_from_user(&dc, (void __user *)arg, sizeof(dc))) 3761 + return -EFAULT; 3762 + if (dc.channel == 0 || dc.channel >= NUM_DLCI) 3763 + return -EINVAL; 3764 + dlci = gsm->dlci[dc.channel]; 3765 + if (!dlci) { 3766 + dlci = gsm_dlci_alloc(gsm, dc.channel); 3767 + if (!dlci) 3768 + return -ENOMEM; 3769 + } 3770 + return gsm_dlci_config(dlci, &dc, 0); 3746 3771 default: 3747 3772 return n_tty_ioctl_helper(tty, cmd, arg); 3748 3773 }