root/drivers/staging/gdm724x/gdm_tty.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gdm_port_destruct
  2. gdm_tty_install
  3. gdm_tty_open
  4. gdm_tty_cleanup
  5. gdm_tty_hangup
  6. gdm_tty_close
  7. gdm_tty_recv_complete
  8. gdm_tty_send_complete
  9. gdm_tty_write
  10. gdm_tty_write_room
  11. register_lte_tty_device
  12. unregister_lte_tty_device
  13. register_lte_tty_driver
  14. unregister_lte_tty_driver

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
   3 
   4 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/errno.h>
   8 #include <linux/tty.h>
   9 #include <linux/tty_driver.h>
  10 #include <linux/tty_flip.h>
  11 #include <linux/module.h>
  12 #include <linux/slab.h>
  13 #include <linux/usb/cdc.h>
  14 #include <linux/serial.h>
  15 #include "gdm_tty.h"
  16 
  17 #define GDM_TTY_MAJOR 0
  18 #define GDM_TTY_MINOR 32
  19 
  20 #define ACM_CTRL_DTR 0x01
  21 #define ACM_CTRL_RTS 0x02
  22 #define ACM_CTRL_DSR 0x02
  23 #define ACM_CTRL_RI  0x08
  24 #define ACM_CTRL_DCD 0x01
  25 
  26 #define WRITE_SIZE 2048
  27 
  28 #define MUX_TX_MAX_SIZE 2048
  29 
  30 #define GDM_TTY_READY(gdm) (gdm && gdm->tty_dev && gdm->port.count)
  31 
  32 static struct tty_driver *gdm_driver[TTY_MAX_COUNT];
  33 static struct gdm *gdm_table[TTY_MAX_COUNT][GDM_TTY_MINOR];
  34 static DEFINE_MUTEX(gdm_table_lock);
  35 
  36 static const char *DRIVER_STRING[TTY_MAX_COUNT] = {"GCTATC", "GCTDM"};
  37 static char *DEVICE_STRING[TTY_MAX_COUNT] = {"GCT-ATC", "GCT-DM"};
  38 
  39 static void gdm_port_destruct(struct tty_port *port)
  40 {
  41         struct gdm *gdm = container_of(port, struct gdm, port);
  42 
  43         mutex_lock(&gdm_table_lock);
  44         gdm_table[gdm->index][gdm->minor] = NULL;
  45         mutex_unlock(&gdm_table_lock);
  46 
  47         kfree(gdm);
  48 }
  49 
  50 static const struct tty_port_operations gdm_port_ops = {
  51         .destruct = gdm_port_destruct,
  52 };
  53 
  54 static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
  55 {
  56         struct gdm *gdm = NULL;
  57         int ret;
  58 
  59         ret = match_string(DRIVER_STRING, TTY_MAX_COUNT,
  60                            tty->driver->driver_name);
  61         if (ret < 0)
  62                 return -ENODEV;
  63 
  64         mutex_lock(&gdm_table_lock);
  65         gdm = gdm_table[ret][tty->index];
  66         if (!gdm) {
  67                 mutex_unlock(&gdm_table_lock);
  68                 return -ENODEV;
  69         }
  70 
  71         tty_port_get(&gdm->port);
  72 
  73         ret = tty_standard_install(driver, tty);
  74         if (ret) {
  75                 tty_port_put(&gdm->port);
  76                 mutex_unlock(&gdm_table_lock);
  77                 return ret;
  78         }
  79 
  80         tty->driver_data = gdm;
  81         mutex_unlock(&gdm_table_lock);
  82 
  83         return 0;
  84 }
  85 
  86 static int gdm_tty_open(struct tty_struct *tty, struct file *filp)
  87 {
  88         struct gdm *gdm = tty->driver_data;
  89 
  90         return tty_port_open(&gdm->port, tty, filp);
  91 }
  92 
  93 static void gdm_tty_cleanup(struct tty_struct *tty)
  94 {
  95         struct gdm *gdm = tty->driver_data;
  96 
  97         tty_port_put(&gdm->port);
  98 }
  99 
 100 static void gdm_tty_hangup(struct tty_struct *tty)
 101 {
 102         struct gdm *gdm = tty->driver_data;
 103 
 104         tty_port_hangup(&gdm->port);
 105 }
 106 
 107 static void gdm_tty_close(struct tty_struct *tty, struct file *filp)
 108 {
 109         struct gdm *gdm = tty->driver_data;
 110 
 111         tty_port_close(&gdm->port, tty, filp);
 112 }
 113 
 114 static int gdm_tty_recv_complete(void *data,
 115                                  int len,
 116                                  int index,
 117                                  struct tty_dev *tty_dev,
 118                                  int complete)
 119 {
 120         struct gdm *gdm = tty_dev->gdm[index];
 121 
 122         if (!GDM_TTY_READY(gdm)) {
 123                 if (complete == RECV_PACKET_PROCESS_COMPLETE)
 124                         gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
 125                                                 gdm_tty_recv_complete);
 126                 return TO_HOST_PORT_CLOSE;
 127         }
 128 
 129         if (data && len) {
 130                 if (tty_buffer_request_room(&gdm->port, len) == len) {
 131                         tty_insert_flip_string(&gdm->port, data, len);
 132                         tty_flip_buffer_push(&gdm->port);
 133                 } else {
 134                         return TO_HOST_BUFFER_REQUEST_FAIL;
 135                 }
 136         }
 137 
 138         if (complete == RECV_PACKET_PROCESS_COMPLETE)
 139                 gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
 140                                         gdm_tty_recv_complete);
 141 
 142         return 0;
 143 }
 144 
 145 static void gdm_tty_send_complete(void *arg)
 146 {
 147         struct gdm *gdm = arg;
 148 
 149         if (!GDM_TTY_READY(gdm))
 150                 return;
 151 
 152         tty_port_tty_wakeup(&gdm->port);
 153 }
 154 
 155 static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf,
 156                          int len)
 157 {
 158         struct gdm *gdm = tty->driver_data;
 159         int remain = len;
 160         int sent_len = 0;
 161         int sending_len = 0;
 162 
 163         if (!GDM_TTY_READY(gdm))
 164                 return -ENODEV;
 165 
 166         if (!len)
 167                 return 0;
 168 
 169         while (1) {
 170                 sending_len = min(MUX_TX_MAX_SIZE, remain);
 171                 gdm->tty_dev->send_func(gdm->tty_dev->priv_dev,
 172                                         (void *)(buf + sent_len),
 173                                         sending_len,
 174                                         gdm->index,
 175                                         gdm_tty_send_complete,
 176                                         gdm);
 177                 sent_len += sending_len;
 178                 remain -= sending_len;
 179                 if (remain <= 0)
 180                         break;
 181         }
 182 
 183         return len;
 184 }
 185 
 186 static int gdm_tty_write_room(struct tty_struct *tty)
 187 {
 188         struct gdm *gdm = tty->driver_data;
 189 
 190         if (!GDM_TTY_READY(gdm))
 191                 return -ENODEV;
 192 
 193         return WRITE_SIZE;
 194 }
 195 
 196 int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device)
 197 {
 198         struct gdm *gdm;
 199         int i;
 200         int j;
 201 
 202         for (i = 0; i < TTY_MAX_COUNT; i++) {
 203                 gdm = kmalloc(sizeof(*gdm), GFP_KERNEL);
 204                 if (!gdm)
 205                         return -ENOMEM;
 206 
 207                 mutex_lock(&gdm_table_lock);
 208                 for (j = 0; j < GDM_TTY_MINOR; j++) {
 209                         if (!gdm_table[i][j])
 210                                 break;
 211                 }
 212 
 213                 if (j == GDM_TTY_MINOR) {
 214                         kfree(gdm);
 215                         mutex_unlock(&gdm_table_lock);
 216                         return -EINVAL;
 217                 }
 218 
 219                 gdm_table[i][j] = gdm;
 220                 mutex_unlock(&gdm_table_lock);
 221 
 222                 tty_dev->gdm[i] = gdm;
 223                 tty_port_init(&gdm->port);
 224 
 225                 gdm->port.ops = &gdm_port_ops;
 226                 gdm->index = i;
 227                 gdm->minor = j;
 228                 gdm->tty_dev = tty_dev;
 229 
 230                 tty_port_register_device(&gdm->port, gdm_driver[i],
 231                                          gdm->minor, device);
 232         }
 233 
 234         for (i = 0; i < MAX_ISSUE_NUM; i++)
 235                 gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
 236                                         gdm_tty_recv_complete);
 237 
 238         return 0;
 239 }
 240 
 241 void unregister_lte_tty_device(struct tty_dev *tty_dev)
 242 {
 243         struct gdm *gdm;
 244         struct tty_struct *tty;
 245         int i;
 246 
 247         for (i = 0; i < TTY_MAX_COUNT; i++) {
 248                 gdm = tty_dev->gdm[i];
 249                 if (!gdm)
 250                         continue;
 251 
 252                 mutex_lock(&gdm_table_lock);
 253                 gdm_table[gdm->index][gdm->minor] = NULL;
 254                 mutex_unlock(&gdm_table_lock);
 255 
 256                 tty = tty_port_tty_get(&gdm->port);
 257                 if (tty) {
 258                         tty_vhangup(tty);
 259                         tty_kref_put(tty);
 260                 }
 261 
 262                 tty_unregister_device(gdm_driver[i], gdm->minor);
 263                 tty_port_put(&gdm->port);
 264         }
 265 }
 266 
 267 static const struct tty_operations gdm_tty_ops = {
 268         .install =      gdm_tty_install,
 269         .open =         gdm_tty_open,
 270         .close =        gdm_tty_close,
 271         .cleanup =      gdm_tty_cleanup,
 272         .hangup =       gdm_tty_hangup,
 273         .write =        gdm_tty_write,
 274         .write_room =   gdm_tty_write_room,
 275 };
 276 
 277 int register_lte_tty_driver(void)
 278 {
 279         struct tty_driver *tty_driver;
 280         int i;
 281         int ret;
 282 
 283         for (i = 0; i < TTY_MAX_COUNT; i++) {
 284                 tty_driver = alloc_tty_driver(GDM_TTY_MINOR);
 285                 if (!tty_driver)
 286                         return -ENOMEM;
 287 
 288                 tty_driver->owner = THIS_MODULE;
 289                 tty_driver->driver_name = DRIVER_STRING[i];
 290                 tty_driver->name = DEVICE_STRING[i];
 291                 tty_driver->major = GDM_TTY_MAJOR;
 292                 tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
 293                 tty_driver->subtype = SERIAL_TYPE_NORMAL;
 294                 tty_driver->flags = TTY_DRIVER_REAL_RAW |
 295                                         TTY_DRIVER_DYNAMIC_DEV;
 296                 tty_driver->init_termios = tty_std_termios;
 297                 tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
 298                 tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
 299                 tty_set_operations(tty_driver, &gdm_tty_ops);
 300 
 301                 ret = tty_register_driver(tty_driver);
 302                 if (ret) {
 303                         put_tty_driver(tty_driver);
 304                         return ret;
 305                 }
 306 
 307                 gdm_driver[i] = tty_driver;
 308         }
 309 
 310         return ret;
 311 }
 312 
 313 void unregister_lte_tty_driver(void)
 314 {
 315         struct tty_driver *tty_driver;
 316         int i;
 317 
 318         for (i = 0; i < TTY_MAX_COUNT; i++) {
 319                 tty_driver = gdm_driver[i];
 320                 if (tty_driver) {
 321                         tty_unregister_driver(tty_driver);
 322                         put_tty_driver(tty_driver);
 323                 }
 324         }
 325 }
 326 

/* [<][>][^][v][top][bottom][index][help] */